diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21166e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +xcuserdata/ \ No newline at end of file diff --git a/ActiveGS_iOS/Default-568h@2x.png b/ActiveGS_iOS/Default-568h@2x.png new file mode 100644 index 0000000..94cb7e8 Binary files /dev/null and b/ActiveGS_iOS/Default-568h@2x.png differ diff --git a/ActiveGS_iOS/Default.png b/ActiveGS_iOS/Default.png new file mode 100644 index 0000000..94cb7e8 Binary files /dev/null and b/ActiveGS_iOS/Default.png differ diff --git a/ActiveGS_iOS/Entitlements.plist b/ActiveGS_iOS/Entitlements.plist new file mode 100644 index 0000000..5d8d603 --- /dev/null +++ b/ActiveGS_iOS/Entitlements.plist @@ -0,0 +1,10 @@ + + + + + application-identifier + SQ9T3Q7RV4.com.freetoolsassociation.activegs + get-task-allow + + + diff --git a/ActiveGS_iOS/Resources-iPad/MainWindow-iPad.xib b/ActiveGS_iOS/Resources-iPad/MainWindow-iPad.xib new file mode 100644 index 0000000..5dcbd05 --- /dev/null +++ b/ActiveGS_iOS/Resources-iPad/MainWindow-iPad.xib @@ -0,0 +1,455 @@ + + + + 1056 + 10F569 + 804 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 131 + + + YES + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBIPadFramework + + + IBFirstResponder + IBIPadFramework + + + IBIPadFramework + + + activegsViewController + + 1 + + IBIPadFramework + NO + + + + 292 + {768, 1004} + + 1 + MSAxIDEAA + + NO + NO + + 2 + + IBIPadFramework + YES + + + + + YES + + + delegate + + + + 4 + + + + viewController + + + + 11 + + + + window + + + + 14 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + activegs App Delegate + + + -2 + + + + + 10 + + + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.CustomClassName + 10.IBEditorWindowLastContentRect + 10.IBPluginDependency + 12.IBEditorWindowLastContentRect + 12.IBLastUsedUIStatusBarStylesToTargetRuntimesMap + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + activegsViewController + {{512, 351}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{525, 346}, {320, 480}} + + IBCocoaTouchFramework + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + activegsAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 14 + + + + YES + + activegsAppDelegate + NSObject + + YES + + YES + viewController + window + + + YES + activegsViewController + UIWindow + + + + YES + + YES + viewController + window + + + YES + + viewController + activegsViewController + + + window + UIWindow + + + + + IBProjectSource + Classes/activegsAppDelegate.h + + + + activegsAppDelegate + NSObject + + IBUserSource + + + + + activegsViewController + UIViewController + + IBProjectSource + Classes/activegsViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBIPadFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + activegs.xcodeproj + 3 + 131 + + diff --git a/ActiveGS_iOS/activegs.plist b/ActiveGS_iOS/activegs.plist new file mode 100644 index 0000000..e07b1ad --- /dev/null +++ b/ActiveGS_iOS/activegs.plist @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ActiveGS + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFiles + + icon.png + icon72.png + icon@2x.png + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ActiveGS + CFBundlePackageType + APPL + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + 1.40 + LSRequiresIPhoneOS + + UIAppFonts + + ShastonHi640.ttf + + UIFileSharingEnabled + + UIStatusBarHidden + + UIStatusBarHidden~ipad + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ActiveGS_iOS/activegs.xcodeproj/project.pbxproj b/ActiveGS_iOS/activegs.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ee361d3 --- /dev/null +++ b/ActiveGS_iOS/activegs.xcodeproj/project.pbxproj @@ -0,0 +1,1582 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0902FEC812820467002E7C03 /* Tab2GS.png in Resources */ = {isa = PBXBuildFile; fileRef = 0902FEC712820467002E7C03 /* Tab2GS.png */; }; + 0902FEE712820626002E7C03 /* TabFTA@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0902FEE612820626002E7C03 /* TabFTA@2x.png */; }; + 0902FEEF12820678002E7C03 /* TabFTA.png in Resources */ = {isa = PBXBuildFile; fileRef = 0902FEEE12820678002E7C03 /* TabFTA.png */; }; + 09052B7719053C9F00853FAE /* png.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4419053C9F00853FAE /* png.cpp */; }; + 09052B7819053C9F00853FAE /* pngerror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4719053C9F00853FAE /* pngerror.cpp */; }; + 09052B7919053C9F00853FAE /* pnggccrd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4819053C9F00853FAE /* pnggccrd.cpp */; }; + 09052B7A19053C9F00853FAE /* pngget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4919053C9F00853FAE /* pngget.cpp */; }; + 09052B7B19053C9F00853FAE /* pngmem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4A19053C9F00853FAE /* pngmem.cpp */; }; + 09052B7C19053C9F00853FAE /* pngpread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4B19053C9F00853FAE /* pngpread.cpp */; }; + 09052B7D19053C9F00853FAE /* pngread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4C19053C9F00853FAE /* pngread.cpp */; }; + 09052B7E19053C9F00853FAE /* pngrio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4D19053C9F00853FAE /* pngrio.cpp */; }; + 09052B7F19053C9F00853FAE /* pngrtran.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4E19053C9F00853FAE /* pngrtran.cpp */; }; + 09052B8019053C9F00853FAE /* pngrutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B4F19053C9F00853FAE /* pngrutil.cpp */; }; + 09052B8119053C9F00853FAE /* pngset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5019053C9F00853FAE /* pngset.cpp */; }; + 09052B8219053C9F00853FAE /* pngtrans.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5119053C9F00853FAE /* pngtrans.cpp */; }; + 09052B8319053C9F00853FAE /* pngvcrd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5219053C9F00853FAE /* pngvcrd.cpp */; }; + 09052B8419053C9F00853FAE /* pngwio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5319053C9F00853FAE /* pngwio.cpp */; }; + 09052B8519053C9F00853FAE /* pngwrite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5419053C9F00853FAE /* pngwrite.cpp */; }; + 09052B8619053C9F00853FAE /* pngwtran.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5519053C9F00853FAE /* pngwtran.cpp */; }; + 09052B8719053C9F00853FAE /* pngwutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5619053C9F00853FAE /* pngwutil.cpp */; }; + 09052B8819053C9F00853FAE /* ioapi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5919053C9F00853FAE /* ioapi.cpp */; }; + 09052B8919053C9F00853FAE /* iowin32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5B19053C9F00853FAE /* iowin32.cpp */; }; + 09052B8A19053C9F00853FAE /* unzip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5D19053C9F00853FAE /* unzip.cpp */; }; + 09052B8B19053C9F00853FAE /* zip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B5F19053C9F00853FAE /* zip.cpp */; }; + 09052B8C19053C9F00853FAE /* adler32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6219053C9F00853FAE /* adler32.cpp */; }; + 09052B8D19053C9F00853FAE /* compress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6319053C9F00853FAE /* compress.cpp */; }; + 09052B8E19053C9F00853FAE /* crc32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6419053C9F00853FAE /* crc32.cpp */; }; + 09052B8F19053C9F00853FAE /* deflate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6619053C9F00853FAE /* deflate.cpp */; }; + 09052B9019053C9F00853FAE /* inffast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6819053C9F00853FAE /* inffast.cpp */; }; + 09052B9119053C9F00853FAE /* inflate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6B19053C9F00853FAE /* inflate.cpp */; }; + 09052B9219053C9F00853FAE /* inftrees.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6D19053C9F00853FAE /* inftrees.cpp */; }; + 09052B9319053C9F00853FAE /* trees.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B6F19053C9F00853FAE /* trees.cpp */; }; + 09052B9419053C9F00853FAE /* uncompr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B7119053C9F00853FAE /* uncompr.cpp */; }; + 09052B9519053C9F00853FAE /* zutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09052B7519053C9F00853FAE /* zutil.cpp */; }; + 0905905213A76C23006E67D7 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0905905113A76C23006E67D7 /* AudioToolbox.framework */; }; + 0907BCC9142F567A0051CA0A /* asynccommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0907BCC8142F567A0051CA0A /* asynccommand.mm */; }; + 09087F3A12244C0500C52D88 /* delta_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F2B12244C0500C52D88 /* delta_1.png */; }; + 09087F3B12244C0500C52D88 /* delta_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F2C12244C0500C52D88 /* delta_2.png */; }; + 09087F3C12244C0500C52D88 /* delta_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F2D12244C0500C52D88 /* delta_3.png */; }; + 09087F3D12244C0500C52D88 /* delta_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F2E12244C0500C52D88 /* delta_4.png */; }; + 09087F3E12244C0500C52D88 /* delta_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F2F12244C0500C52D88 /* delta_5.png */; }; + 09087F3F12244C0500C52D88 /* delta_6.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3012244C0500C52D88 /* delta_6.png */; }; + 09087F4012244C0500C52D88 /* delta_7.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3112244C0500C52D88 /* delta_7.png */; }; + 09087F4312244C0500C52D88 /* photonix_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3412244C0500C52D88 /* photonix_1.png */; }; + 09087F4412244C0500C52D88 /* photonix_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3512244C0500C52D88 /* photonix_2.png */; }; + 09087F4612244C0500C52D88 /* thumb_delta.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3712244C0500C52D88 /* thumb_delta.png */; }; + 09087F4712244C0500C52D88 /* thumb_gsos.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3812244C0500C52D88 /* thumb_gsos.png */; }; + 09087F4812244C0500C52D88 /* thumb_photonix.png in Resources */ = {isa = PBXBuildFile; fileRef = 09087F3912244C0500C52D88 /* thumb_photonix.png */; }; + 090A6077163093D800C8FB59 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 090A6076163093D800C8FB59 /* Default-568h@2x.png */; }; + 090E7BD6123F965F003EE2C3 /* poms_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BCF123F965F003EE2C3 /* poms_1.png */; }; + 090E7BD7123F965F003EE2C3 /* poms_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BD0123F965F003EE2C3 /* poms_2.png */; }; + 090E7BD8123F965F003EE2C3 /* poms_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BD1123F965F003EE2C3 /* poms_3.png */; }; + 090E7BD9123F965F003EE2C3 /* poms_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BD2123F965F003EE2C3 /* poms_4.png */; }; + 090E7BDA123F965F003EE2C3 /* poms_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BD3123F965F003EE2C3 /* poms_5.png */; }; + 090E7BDB123F965F003EE2C3 /* poms_6.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BD4123F965F003EE2C3 /* poms_6.png */; }; + 090E7BDE123F966C003EE2C3 /* thumb_poms.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E7BDD123F966C003EE2C3 /* thumb_poms.png */; }; + 0916BB04129473CE001727AF /* infoViewController-ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0916BB03129473CE001727AF /* infoViewController-ipad.xib */; }; + 0941E66E1670E086003E0411 /* NUCLEUS.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 0941E66D1670E086003E0411 /* NUCLEUS.FTA */; }; + 0941E6701670E143003E0411 /* DELTA.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 0941E66F1670E143003E0411 /* DELTA.FTA */; }; + 0941E6721670E23F003E0411 /* PHOTONIX.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 0941E6711670E23F003E0411 /* PHOTONIX.FTA */; }; + 0941E6751670E391003E0411 /* BOUNCIN_FERNO.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 0941E6731670E391003E0411 /* BOUNCIN_FERNO.FTA */; }; + 0941E6761670E391003E0411 /* MINIPRIX.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 0941E6741670E391003E0411 /* MINIPRIX.FTA */; }; + 0941E6AB16720840003E0411 /* ActiveGSList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0941E6A916720840003E0411 /* ActiveGSList.cpp */; }; + 0941E6AF16720886003E0411 /* simplexml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0941E6AD16720886003E0411 /* simplexml.cpp */; }; + 095036E519054799006A457A /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 095036E419054799006A457A /* CoreData.framework */; }; + 095036E7190547A0006A457A /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 095036E6190547A0006A457A /* AdSupport.framework */; }; + 095036E9190547BE006A457A /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 095036E8190547BE006A457A /* CoreLocation.framework */; }; + 09520D8316AEF8130065E84A /* driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09520D8116AEF8130065E84A /* driver.cpp */; }; + 09520D8916AEF8250065E84A /* activegs_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09520D8616AEF8250065E84A /* activegs_driver.cpp */; }; + 09520D8E16AEF8650065E84A /* apple2e.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09520D8C16AEF8650065E84A /* apple2e.cpp */; }; + 0955429F12836F4D0035AE09 /* Tab2GS@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0955429E12836F4D0035AE09 /* Tab2GS@2x.png */; }; + 095542A8128375C40035AE09 /* Tab][.png in Resources */ = {isa = PBXBuildFile; fileRef = 095542A6128375C40035AE09 /* Tab][.png */; }; + 095542A9128375C40035AE09 /* Tab][@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 095542A7128375C40035AE09 /* Tab][@2x.png */; }; + 09712D82133B66E4007AAADF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09712D81133B66E4007AAADF /* SystemConfiguration.framework */; }; + 09712D86133B66F0007AAADF /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09712D85133B66F0007AAADF /* CoreTelephony.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 0971D931126E4BE500EEBB1E /* icon72.png in Resources */ = {isa = PBXBuildFile; fileRef = 0971D930126E4BE500EEBB1E /* icon72.png */; }; + 0972554713CF2232006194F9 /* activegsEmulatorController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0972554613CF2232006194F9 /* activegsEmulatorController.mm */; }; + 0982685E124028E00064F134 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 0982685C124028E00064F134 /* icon.png */; }; + 0982685F124028E00064F134 /* icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0982685D124028E00064F134 /* icon@2x.png */; }; + 099B5B8111F62D4900E597B6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 099B5B8011F62D4900E597B6 /* QuartzCore.framework */; }; + 099CD905125E6F6E008EFD6C /* detailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 099CD904125E6F6E008EFD6C /* detailViewController.xib */; }; + 09A5CE60125D41860018DC22 /* infoViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09A5CE5F125D41860018DC22 /* infoViewController.mm */; }; + 09A5CE76125D422D0018DC22 /* infoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 09A5CE75125D422D0018DC22 /* infoViewController.xib */; }; + 09AADC78125C560A00654DF1 /* detailViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09AADC77125C560A00654DF1 /* detailViewController.mm */; }; + 09AB6C11123EE1AE00816DB7 /* bouncinferno_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C09123EE1AE00816DB7 /* bouncinferno_1.png */; }; + 09AB6C12123EE1AE00816DB7 /* bouncinferno_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C0A123EE1AE00816DB7 /* bouncinferno_2.png */; }; + 09AB6C13123EE1AE00816DB7 /* bouncinferno_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C0B123EE1AE00816DB7 /* bouncinferno_3.png */; }; + 09AB6C14123EE1AE00816DB7 /* bouncinferno_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C0C123EE1AE00816DB7 /* bouncinferno_4.png */; }; + 09AB6C15123EE1AE00816DB7 /* bouncinferno_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C0D123EE1AE00816DB7 /* bouncinferno_5.png */; }; + 09AB6C16123EE1AE00816DB7 /* bouncinferno_6.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C0E123EE1AE00816DB7 /* bouncinferno_6.png */; }; + 09AB6C17123EE1AE00816DB7 /* bouncinferno_7.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C0F123EE1AE00816DB7 /* bouncinferno_7.png */; }; + 09AB6C19123EE1BA00816DB7 /* harrier1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C18123EE1BA00816DB7 /* harrier1.png */; }; + 09AB6C1D123EE1CB00816DB7 /* SPACE_HARRIER.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C1A123EE1CB00816DB7 /* SPACE_HARRIER.FTA */; }; + 09AB6C1E123EE1CB00816DB7 /* thumb_bouncinferno.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C1B123EE1CB00816DB7 /* thumb_bouncinferno.png */; }; + 09AB6C1F123EE1CB00816DB7 /* thumb_harrier.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C1C123EE1CB00816DB7 /* thumb_harrier.png */; }; + 09AB6C25123EE2FA00816DB7 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AB6C24123EE2FA00816DB7 /* Default.png */; }; + 09AF98051283F0DF00083D60 /* Oil_Landers.fta in Resources */ = {isa = PBXBuildFile; fileRef = 09AF98041283F0DF00083D60 /* Oil_Landers.fta */; }; + 09AF980C1283F12200083D60 /* StarWizard (2002).fta in Resources */ = {isa = PBXBuildFile; fileRef = 09AF98061283F12200083D60 /* StarWizard (2002).fta */; }; + 09AF980D1283F12200083D60 /* starwizard_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AF98071283F12200083D60 /* starwizard_2.png */; }; + 09AF980E1283F12200083D60 /* starwizard_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AF98081283F12200083D60 /* starwizard_3.png */; }; + 09AF980F1283F12200083D60 /* starwizard_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AF98091283F12200083D60 /* starwizard_4.png */; }; + 09AF98101283F12200083D60 /* starwizard_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AF980A1283F12200083D60 /* starwizard_5.png */; }; + 09AF98111283F12200083D60 /* starwizard.png in Resources */ = {isa = PBXBuildFile; fileRef = 09AF980B1283F12200083D60 /* starwizard.png */; }; + 09BB434511D92F65005ADA46 /* ActiveDownloadMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB434111D92F65005ADA46 /* ActiveDownloadMac.cpp */; }; + 09BB434711D92F65005ADA46 /* CEmulatorCtrlMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB434311D92F65005ADA46 /* CEmulatorCtrlMac.cpp */; }; + 09BB43B011D92F70005ADA46 /* activeconfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438111D92F70005ADA46 /* activeconfig.cpp */; }; + 09BB43B111D92F70005ADA46 /* ActiveDownload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438211D92F70005ADA46 /* ActiveDownload.cpp */; }; + 09BB43B211D92F70005ADA46 /* ActiveZip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438411D92F70005ADA46 /* ActiveZip.cpp */; }; + 09BB43B311D92F70005ADA46 /* CA2Text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438511D92F70005ADA46 /* CA2Text.cpp */; }; + 09BB43B411D92F70005ADA46 /* CEmulatorCtrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438611D92F70005ADA46 /* CEmulatorCtrl.cpp */; }; + 09BB43B511D92F70005ADA46 /* interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438811D92F70005ADA46 /* interface.cpp */; }; + 09BB43B611D92F70005ADA46 /* libpng.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438A11D92F70005ADA46 /* libpng.cpp */; }; + 09BB43B711D92F70005ADA46 /* rom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09BB438B11D92F70005ADA46 /* rom.cpp */; }; + 09BB43DC11D93063005ADA46 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BB43DB11D93063005ADA46 /* OpenAL.framework */; }; + 09BB43E311D93087005ADA46 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BB43E211D93087005ADA46 /* CFNetwork.framework */; }; + 09BCB6281211649D009858DF /* flobynoid (2002).dsk.zip in Resources */ = {isa = PBXBuildFile; fileRef = 09BCB6271211649D009858DF /* flobynoid (2002).dsk.zip */; }; + 09C81A781657ACAE008539D5 /* adb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A391657ACAE008539D5 /* adb.cpp */; }; + 09C81A791657ACAE008539D5 /* async_event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A3B1657ACAE008539D5 /* async_event.cpp */; }; + 09C81A7A1657ACAE008539D5 /* clock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A3D1657ACAE008539D5 /* clock.cpp */; }; + 09C81A7B1657ACAE008539D5 /* compile_time.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A3F1657ACAE008539D5 /* compile_time.cpp */; }; + 09C81A7C1657ACAE008539D5 /* compression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A401657ACAE008539D5 /* compression.cpp */; }; + 09C81A7D1657ACAE008539D5 /* config_generic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A431657ACAE008539D5 /* config_generic.cpp */; }; + 09C81A7F1657ACAE008539D5 /* dis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A491657ACAE008539D5 /* dis.cpp */; }; + 09C81A801657ACAE008539D5 /* engine_c.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A4B1657ACAE008539D5 /* engine_c.cpp */; }; + 09C81A811657ACAE008539D5 /* GraphCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A4C1657ACAE008539D5 /* GraphCounter.cpp */; }; + 09C81A821657ACAE008539D5 /* iwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A4E1657ACAE008539D5 /* iwm.cpp */; }; + 09C81A831657ACAE008539D5 /* marinetti.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A531657ACAE008539D5 /* marinetti.cpp */; }; + 09C81A841657ACAE008539D5 /* marinetti_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A551657ACAE008539D5 /* marinetti_helper.cpp */; }; + 09C81A851657ACAE008539D5 /* moremem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A561657ACAE008539D5 /* moremem.cpp */; }; + 09C81A861657ACAE008539D5 /* openalasync_snddriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A591657ACAE008539D5 /* openalasync_snddriver.cpp */; }; + 09C81A871657ACAE008539D5 /* paddles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A5A1657ACAE008539D5 /* paddles.cpp */; }; + 09C81A881657ACAE008539D5 /* SaveState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A651657ACAE008539D5 /* SaveState.cpp */; }; + 09C81A891657ACAE008539D5 /* scc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A671657ACAE008539D5 /* scc.cpp */; }; + 09C81A8A1657ACAE008539D5 /* scc_socket_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A691657ACAE008539D5 /* scc_socket_driver.cpp */; }; + 09C81A8B1657ACAE008539D5 /* sim65816.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A6A1657ACAE008539D5 /* sim65816.cpp */; }; + 09C81A8C1657ACAE008539D5 /* smartport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A6F1657ACAE008539D5 /* smartport.cpp */; }; + 09C81A8D1657ACAE008539D5 /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A701657ACAE008539D5 /* sound.cpp */; }; + 09C81A8E1657ACAE008539D5 /* sound_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A721657ACAE008539D5 /* sound_driver.cpp */; }; + 09C81A901657ACAE008539D5 /* video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A761657ACAE008539D5 /* video.cpp */; }; + 09C81A991657ACDD008539D5 /* 2mg.icns in Resources */ = {isa = PBXBuildFile; fileRef = 09C81A921657ACDC008539D5 /* 2mg.icns */; }; + 09C81A9A1657ACDD008539D5 /* 525.icns in Resources */ = {isa = PBXBuildFile; fileRef = 09C81A931657ACDC008539D5 /* 525.icns */; }; + 09C81A9B1657ACDD008539D5 /* macdriver_activegs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A941657ACDC008539D5 /* macdriver_activegs.cpp */; }; + 09C81A9C1657ACDD008539D5 /* macdriver_generic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A951657ACDC008539D5 /* macdriver_generic.cpp */; }; + 09C81A9F1657ACDD008539D5 /* scc_macdriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81A981657ACDC008539D5 /* scc_macdriver.cpp */; }; + 09C81AA71657AD18008539D5 /* emulatorView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09C81AA21657AD18008539D5 /* emulatorView.mm */; }; + 09C81AA81657AD18008539D5 /* joystick_iphone.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09C81AA31657AD18008539D5 /* joystick_iphone.cpp */; }; + 09C81AA91657AD18008539D5 /* zoomEmulatorView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09C81AA61657AD18008539D5 /* zoomEmulatorView.mm */; }; + 09D8BCF91285EFE900B6D785 /* miniprix_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BCF81285EFE900B6D785 /* miniprix_1.png */; }; + 09D8BCFC1285EFFA00B6D785 /* miniprix_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BCFA1285EFFA00B6D785 /* miniprix_2.png */; }; + 09D8BCFD1285EFFA00B6D785 /* miniprix_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BCFB1285EFFA00B6D785 /* miniprix_3.png */; }; + 09D8BD031285F00C00B6D785 /* oillanders_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BCFE1285F00C00B6D785 /* oillanders_1.png */; }; + 09D8BD041285F00C00B6D785 /* oillanders_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BCFF1285F00C00B6D785 /* oillanders_2.png */; }; + 09D8BD051285F00C00B6D785 /* oillanders_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BD001285F00C00B6D785 /* oillanders_3.png */; }; + 09D8BD061285F00C00B6D785 /* oillanders_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BD011285F00C00B6D785 /* oillanders_4.png */; }; + 09D8BD071285F00C00B6D785 /* oillanders_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 09D8BD021285F00C00B6D785 /* oillanders_5.png */; }; + 09E7BE0F11FC935E00DCCFE7 /* floby1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDE411FC935E00DCCFE7 /* floby1.png */; }; + 09E7BE1011FC935E00DCCFE7 /* floby2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDE511FC935E00DCCFE7 /* floby2.png */; }; + 09E7BE1111FC935E00DCCFE7 /* floby3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDE611FC935E00DCCFE7 /* floby3.png */; }; + 09E7BE1311FC935E00DCCFE7 /* list.activegsxml in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDE811FC935E00DCCFE7 /* list.activegsxml */; }; + 09E7BE1411FC935E00DCCFE7 /* MODULAE.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDE911FC935E00DCCFE7 /* MODULAE.FTA */; }; + 09E7BE1511FC935E00DCCFE7 /* modulae_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDEA11FC935E00DCCFE7 /* modulae_1.png */; }; + 09E7BE1611FC935E00DCCFE7 /* modulae_10.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDEB11FC935E00DCCFE7 /* modulae_10.png */; }; + 09E7BE1711FC935E00DCCFE7 /* modulae_11.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDEC11FC935E00DCCFE7 /* modulae_11.png */; }; + 09E7BE1811FC935E00DCCFE7 /* modulae_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDED11FC935E00DCCFE7 /* modulae_2.png */; }; + 09E7BE1911FC935E00DCCFE7 /* modulae_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDEE11FC935E00DCCFE7 /* modulae_3.png */; }; + 09E7BE1A11FC935E00DCCFE7 /* modulae_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDEF11FC935E00DCCFE7 /* modulae_4.png */; }; + 09E7BE1B11FC935E00DCCFE7 /* modulae_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF011FC935E00DCCFE7 /* modulae_5.png */; }; + 09E7BE1C11FC935E00DCCFE7 /* modulae_6.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF111FC935E00DCCFE7 /* modulae_6.png */; }; + 09E7BE1D11FC935E00DCCFE7 /* modulae_7.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF211FC935E00DCCFE7 /* modulae_7.png */; }; + 09E7BE1E11FC935E00DCCFE7 /* modulae_8.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF311FC935E00DCCFE7 /* modulae_8.png */; }; + 09E7BE1F11FC935E00DCCFE7 /* modulae_9.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF411FC935E00DCCFE7 /* modulae_9.png */; }; + 09E7BE2011FC935E00DCCFE7 /* NOISETRACKER.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF511FC935E00DCCFE7 /* NOISETRACKER.FTA */; }; + 09E7BE2111FC935E00DCCFE7 /* noisetracker_0.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF611FC935E00DCCFE7 /* noisetracker_0.png */; }; + 09E7BE2211FC935E00DCCFE7 /* noisetracker_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF711FC935E00DCCFE7 /* noisetracker_1.png */; }; + 09E7BE2311FC935E00DCCFE7 /* noisetracker_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF811FC935E00DCCFE7 /* noisetracker_2.png */; }; + 09E7BE2411FC935E00DCCFE7 /* noisetracker_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDF911FC935E00DCCFE7 /* noisetracker_3.png */; }; + 09E7BE2611FC935E00DCCFE7 /* nucleus.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDFB11FC935E00DCCFE7 /* nucleus.png */; }; + 09E7BE2711FC935E00DCCFE7 /* nucleus_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDFC11FC935E00DCCFE7 /* nucleus_2.png */; }; + 09E7BE2811FC935E00DCCFE7 /* nucleus_c.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDFD11FC935E00DCCFE7 /* nucleus_c.png */; }; + 09E7BE2911FC935E00DCCFE7 /* nucleus_t.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BDFE11FC935E00DCCFE7 /* nucleus_t.png */; }; + 09E7BE2B11FC935E00DCCFE7 /* thumb_floby.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0011FC935E00DCCFE7 /* thumb_floby.png */; }; + 09E7BE2C11FC935E00DCCFE7 /* thumb_system6.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0111FC935E00DCCFE7 /* thumb_system6.png */; }; + 09E7BE2D11FC935E00DCCFE7 /* thumb_modulae.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0211FC935E00DCCFE7 /* thumb_modulae.png */; }; + 09E7BE2E11FC935E00DCCFE7 /* thumb_noisetracker.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0311FC935E00DCCFE7 /* thumb_noisetracker.png */; }; + 09E7BE2F11FC935E00DCCFE7 /* thumb_nucleus.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0411FC935E00DCCFE7 /* thumb_nucleus.png */; }; + 09E7BE3011FC935E00DCCFE7 /* thumb_xmas.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0511FC935E00DCCFE7 /* thumb_xmas.png */; }; + 09E7BE3111FC935E00DCCFE7 /* xmas_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0611FC935E00DCCFE7 /* xmas_1.png */; }; + 09E7BE3211FC935E00DCCFE7 /* xmas_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0711FC935E00DCCFE7 /* xmas_2.png */; }; + 09E7BE3311FC935E00DCCFE7 /* xmas_3.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0811FC935E00DCCFE7 /* xmas_3.png */; }; + 09E7BE3411FC935E00DCCFE7 /* xmas_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0911FC935E00DCCFE7 /* xmas_4.png */; }; + 09E7BE3511FC935E00DCCFE7 /* xmas_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0A11FC935E00DCCFE7 /* xmas_5.png */; }; + 09E7BE3611FC935E00DCCFE7 /* xmas_6.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0B11FC935E00DCCFE7 /* xmas_6.png */; }; + 09E7BE3711FC935E00DCCFE7 /* xmas_7.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0C11FC935E00DCCFE7 /* xmas_7.png */; }; + 09E7BE3811FC935E00DCCFE7 /* xmas_8.png in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0D11FC935E00DCCFE7 /* xmas_8.png */; }; + 09E7BE3911FC935E00DCCFE7 /* XMASDEMO.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 09E7BE0E11FC935E00DCCFE7 /* XMASDEMO.FTA */; }; + 09FA6095125A7B3E00B07F77 /* activegsAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09FA607A125A7B3E00B07F77 /* activegsAppDelegate.mm */; }; + 09FA6096125A7B3E00B07F77 /* activegsList.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09FA607C125A7B3E00B07F77 /* activegsList.mm */; }; + 09FA6097125A7B3E00B07F77 /* activegsViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09FA607E125A7B3E00B07F77 /* activegsViewController.mm */; }; + 09FA6098125A7B3E00B07F77 /* activegsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 09FA607F125A7B3E00B07F77 /* activegsViewController.xib */; }; + 09FA609A125A7B3E00B07F77 /* asyncimageview.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09FA6083125A7B3E00B07F77 /* asyncimageview.mm */; }; + 09FA609C125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 09FA6087125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.m */; }; + 09FA609D125A7B3E00B07F77 /* icon_APPLE 2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09FA6088125A7B3E00B07F77 /* icon_APPLE 2.png */; }; + 09FA609E125A7B3E00B07F77 /* icon_APPLE 2GS.png in Resources */ = {isa = PBXBuildFile; fileRef = 09FA6089125A7B3E00B07F77 /* icon_APPLE 2GS.png */; }; + 09FA609F125A7B3E00B07F77 /* KBDController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09FA608B125A7B3E00B07F77 /* KBDController.mm */; }; + 09FD36F31278CCEB009C31AB /* BLUE_HELMET.FTA in Resources */ = {isa = PBXBuildFile; fileRef = 09FD36F01278CCEB009C31AB /* BLUE_HELMET.FTA */; }; + 09FD36F41278CCEB009C31AB /* bluehelmet_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 09FD36F11278CCEB009C31AB /* bluehelmet_1.png */; }; + 09FD36F51278CCEB009C31AB /* bluehelmet_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 09FD36F21278CCEB009C31AB /* bluehelmet_2.png */; }; + 1D60589B0D05DD56006BFB54 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.mm */; }; + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + 7E51481F1CA6B5CE005DA0A6 /* ActiveGS.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E51480C1CA6B5CE005DA0A6 /* ActiveGS.png */; }; + 7E5148201CA6B5CE005DA0A6 /* Apple_2_Disk_Drive_Sounds.txt in Resources */ = {isa = PBXBuildFile; fileRef = 7E51480D1CA6B5CE005DA0A6 /* Apple_2_Disk_Drive_Sounds.txt */; }; + 7E5148211CA6B5CE005DA0A6 /* disk.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E51480E1CA6B5CE005DA0A6 /* disk.png */; }; + 7E5148221CA6B5CE005DA0A6 /* disk_35_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E51480F1CA6B5CE005DA0A6 /* disk_35_1.png */; }; + 7E5148231CA6B5CE005DA0A6 /* disk_35_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148101CA6B5CE005DA0A6 /* disk_35_2.png */; }; + 7E5148241CA6B5CE005DA0A6 /* disk_525_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148111CA6B5CE005DA0A6 /* disk_525_1.png */; }; + 7E5148251CA6B5CE005DA0A6 /* disk_525_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148121CA6B5CE005DA0A6 /* disk_525_2.png */; }; + 7E5148261CA6B5CE005DA0A6 /* facebook-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148131CA6B5CE005DA0A6 /* facebook-logo.png */; }; + 7E5148271CA6B5CE005DA0A6 /* floppy_eject.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148141CA6B5CE005DA0A6 /* floppy_eject.wav */; }; + 7E5148281CA6B5CE005DA0A6 /* logo_apple2.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148151CA6B5CE005DA0A6 /* logo_apple2.png */; }; + 7E5148291CA6B5CE005DA0A6 /* logo_apple2gs.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148161CA6B5CE005DA0A6 /* logo_apple2gs.png */; }; + 7E51482A1CA6B5CE005DA0A6 /* Search Skip Search 1.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148171CA6B5CE005DA0A6 /* Search Skip Search 1.wav */; }; + 7E51482B1CA6B5CE005DA0A6 /* Search Skip Search 2.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148181CA6B5CE005DA0A6 /* Search Skip Search 2.wav */; }; + 7E51482C1CA6B5CE005DA0A6 /* Search Skip Search 3.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E5148191CA6B5CE005DA0A6 /* Search Skip Search 3.wav */; }; + 7E51482D1CA6B5CE005DA0A6 /* Search Skip Search 4.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E51481A1CA6B5CE005DA0A6 /* Search Skip Search 4.wav */; }; + 7E51482E1CA6B5CE005DA0A6 /* Search Skip Search 5.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E51481B1CA6B5CE005DA0A6 /* Search Skip Search 5.wav */; }; + 7E51482F1CA6B5CE005DA0A6 /* ShastonHi640.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7E51481C1CA6B5CE005DA0A6 /* ShastonHi640.ttf */; }; + 7E5148301CA6B5CE005DA0A6 /* Spin Up Search 1.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E51481D1CA6B5CE005DA0A6 /* Spin Up Search 1.wav */; }; + 7E5148311CA6B5CE005DA0A6 /* Spin Up Search 2.wav in Resources */ = {isa = PBXBuildFile; fileRef = 7E51481E1CA6B5CE005DA0A6 /* Spin Up Search 2.wav */; }; + 7E8EED6B1A7D83C900C6E522 /* Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7E8EED6A1A7D83C900C6E522 /* Entitlements.plist */; }; +/* End PBXBuildFile section */ + +/* Begin PBXBuildRule section */ + 095981511A3E1A2D007C90A8 /* PBXBuildRule */ = { + isa = PBXBuildRule; + compilerSpec = com.apple.compilers.proxy.script; + fileType = pattern.proxy; + isEditable = 1; + outputFiles = ( + ); + }; +/* End PBXBuildRule section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 095F842613AFDD9C009C540E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0902FEC712820467002E7C03 /* Tab2GS.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Tab2GS.png; path = ../Common.iphone/Tab2GS.png; sourceTree = SOURCE_ROOT; }; + 0902FEE612820626002E7C03 /* TabFTA@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "TabFTA@2x.png"; path = "../Common.iphone/TabFTA@2x.png"; sourceTree = SOURCE_ROOT; }; + 0902FEEE12820678002E7C03 /* TabFTA.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TabFTA.png; path = ../Common.iphone/TabFTA.png; sourceTree = SOURCE_ROOT; }; + 09052B4419053C9F00853FAE /* png.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = png.cpp; sourceTree = ""; }; + 09052B4519053C9F00853FAE /* png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = png.h; sourceTree = ""; }; + 09052B4619053C9F00853FAE /* pngconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pngconf.h; sourceTree = ""; }; + 09052B4719053C9F00853FAE /* pngerror.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngerror.cpp; sourceTree = ""; }; + 09052B4819053C9F00853FAE /* pnggccrd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pnggccrd.cpp; sourceTree = ""; }; + 09052B4919053C9F00853FAE /* pngget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngget.cpp; sourceTree = ""; }; + 09052B4A19053C9F00853FAE /* pngmem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngmem.cpp; sourceTree = ""; }; + 09052B4B19053C9F00853FAE /* pngpread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngpread.cpp; sourceTree = ""; }; + 09052B4C19053C9F00853FAE /* pngread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngread.cpp; sourceTree = ""; }; + 09052B4D19053C9F00853FAE /* pngrio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngrio.cpp; sourceTree = ""; }; + 09052B4E19053C9F00853FAE /* pngrtran.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngrtran.cpp; sourceTree = ""; }; + 09052B4F19053C9F00853FAE /* pngrutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngrutil.cpp; sourceTree = ""; }; + 09052B5019053C9F00853FAE /* pngset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngset.cpp; sourceTree = ""; }; + 09052B5119053C9F00853FAE /* pngtrans.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngtrans.cpp; sourceTree = ""; }; + 09052B5219053C9F00853FAE /* pngvcrd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngvcrd.cpp; sourceTree = ""; }; + 09052B5319053C9F00853FAE /* pngwio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngwio.cpp; sourceTree = ""; }; + 09052B5419053C9F00853FAE /* pngwrite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngwrite.cpp; sourceTree = ""; }; + 09052B5519053C9F00853FAE /* pngwtran.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngwtran.cpp; sourceTree = ""; }; + 09052B5619053C9F00853FAE /* pngwutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pngwutil.cpp; sourceTree = ""; }; + 09052B5819053C9F00853FAE /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; }; + 09052B5919053C9F00853FAE /* ioapi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ioapi.cpp; sourceTree = ""; }; + 09052B5A19053C9F00853FAE /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; + 09052B5B19053C9F00853FAE /* iowin32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iowin32.cpp; sourceTree = ""; }; + 09052B5C19053C9F00853FAE /* iowin32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iowin32.h; sourceTree = ""; }; + 09052B5D19053C9F00853FAE /* unzip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unzip.cpp; sourceTree = ""; }; + 09052B5E19053C9F00853FAE /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; }; + 09052B5F19053C9F00853FAE /* zip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zip.cpp; sourceTree = ""; }; + 09052B6019053C9F00853FAE /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = ""; }; + 09052B6219053C9F00853FAE /* adler32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = adler32.cpp; sourceTree = ""; }; + 09052B6319053C9F00853FAE /* compress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compress.cpp; sourceTree = ""; }; + 09052B6419053C9F00853FAE /* crc32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crc32.cpp; sourceTree = ""; }; + 09052B6519053C9F00853FAE /* crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc32.h; sourceTree = ""; }; + 09052B6619053C9F00853FAE /* deflate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = deflate.cpp; sourceTree = ""; }; + 09052B6719053C9F00853FAE /* deflate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deflate.h; sourceTree = ""; }; + 09052B6819053C9F00853FAE /* inffast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inffast.cpp; sourceTree = ""; }; + 09052B6919053C9F00853FAE /* inffast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inffast.h; sourceTree = ""; }; + 09052B6A19053C9F00853FAE /* inffixed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inffixed.h; sourceTree = ""; }; + 09052B6B19053C9F00853FAE /* inflate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inflate.cpp; sourceTree = ""; }; + 09052B6C19053C9F00853FAE /* inflate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inflate.h; sourceTree = ""; }; + 09052B6D19053C9F00853FAE /* inftrees.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inftrees.cpp; sourceTree = ""; }; + 09052B6E19053C9F00853FAE /* inftrees.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inftrees.h; sourceTree = ""; }; + 09052B6F19053C9F00853FAE /* trees.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trees.cpp; sourceTree = ""; }; + 09052B7019053C9F00853FAE /* trees.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trees.h; sourceTree = ""; }; + 09052B7119053C9F00853FAE /* uncompr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uncompr.cpp; sourceTree = ""; }; + 09052B7219053C9F00853FAE /* zconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zconf.h; sourceTree = ""; }; + 09052B7319053C9F00853FAE /* zconf.in.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zconf.in.h; sourceTree = ""; }; + 09052B7419053C9F00853FAE /* zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zlib.h; sourceTree = ""; }; + 09052B7519053C9F00853FAE /* zutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zutil.cpp; sourceTree = ""; }; + 09052B7619053C9F00853FAE /* zutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zutil.h; sourceTree = ""; }; + 0905905113A76C23006E67D7 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 0907BCC7142F567A0051CA0A /* asynccommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asynccommand.h; sourceTree = ""; }; + 0907BCC8142F567A0051CA0A /* asynccommand.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = asynccommand.mm; sourceTree = ""; }; + 09087F2B12244C0500C52D88 /* delta_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_1.png; sourceTree = ""; }; + 09087F2C12244C0500C52D88 /* delta_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_2.png; sourceTree = ""; }; + 09087F2D12244C0500C52D88 /* delta_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_3.png; sourceTree = ""; }; + 09087F2E12244C0500C52D88 /* delta_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_4.png; sourceTree = ""; }; + 09087F2F12244C0500C52D88 /* delta_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_5.png; sourceTree = ""; }; + 09087F3012244C0500C52D88 /* delta_6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_6.png; sourceTree = ""; }; + 09087F3112244C0500C52D88 /* delta_7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delta_7.png; sourceTree = ""; }; + 09087F3412244C0500C52D88 /* photonix_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = photonix_1.png; sourceTree = ""; }; + 09087F3512244C0500C52D88 /* photonix_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = photonix_2.png; sourceTree = ""; }; + 09087F3712244C0500C52D88 /* thumb_delta.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_delta.png; sourceTree = ""; }; + 09087F3812244C0500C52D88 /* thumb_gsos.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_gsos.png; sourceTree = ""; }; + 09087F3912244C0500C52D88 /* thumb_photonix.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_photonix.png; sourceTree = ""; }; + 090A6076163093D800C8FB59 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 090E7BCF123F965F003EE2C3 /* poms_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = poms_1.png; sourceTree = ""; }; + 090E7BD0123F965F003EE2C3 /* poms_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = poms_2.png; sourceTree = ""; }; + 090E7BD1123F965F003EE2C3 /* poms_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = poms_3.png; sourceTree = ""; }; + 090E7BD2123F965F003EE2C3 /* poms_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = poms_4.png; sourceTree = ""; }; + 090E7BD3123F965F003EE2C3 /* poms_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = poms_5.png; sourceTree = ""; }; + 090E7BD4123F965F003EE2C3 /* poms_6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = poms_6.png; sourceTree = ""; }; + 090E7BDD123F966C003EE2C3 /* thumb_poms.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_poms.png; sourceTree = ""; }; + 0913BFCF13033D77004B3039 /* ActiveGS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ActiveGS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0916BB03129473CE001727AF /* infoViewController-ipad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = "infoViewController-ipad.xib"; sourceTree = ""; }; + 0941E66D1670E086003E0411 /* NUCLEUS.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = NUCLEUS.FTA; sourceTree = ""; }; + 0941E66F1670E143003E0411 /* DELTA.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = DELTA.FTA; sourceTree = ""; }; + 0941E6711670E23F003E0411 /* PHOTONIX.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = PHOTONIX.FTA; sourceTree = ""; }; + 0941E6731670E391003E0411 /* BOUNCIN_FERNO.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = BOUNCIN_FERNO.FTA; sourceTree = ""; }; + 0941E6741670E391003E0411 /* MINIPRIX.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = MINIPRIX.FTA; sourceTree = ""; }; + 0941E6A916720840003E0411 /* ActiveGSList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActiveGSList.cpp; sourceTree = ""; }; + 0941E6AA16720840003E0411 /* ActiveGSList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActiveGSList.h; sourceTree = ""; }; + 0941E6AD16720886003E0411 /* simplexml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = simplexml.cpp; sourceTree = ""; }; + 0941E6AE16720886003E0411 /* simplexml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simplexml.h; sourceTree = ""; }; + 095036E419054799006A457A /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 095036E6190547A0006A457A /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; + 095036E8190547BE006A457A /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + 09520D8116AEF8130065E84A /* driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = driver.cpp; sourceTree = ""; }; + 09520D8216AEF8130065E84A /* driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = driver.h; sourceTree = ""; }; + 09520D8616AEF8250065E84A /* activegs_driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = activegs_driver.cpp; sourceTree = ""; }; + 09520D8C16AEF8650065E84A /* apple2e.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apple2e.cpp; sourceTree = ""; }; + 0955429E12836F4D0035AE09 /* Tab2GS@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Tab2GS@2x.png"; path = "../Common.iphone/Tab2GS@2x.png"; sourceTree = SOURCE_ROOT; }; + 095542A6128375C40035AE09 /* Tab][.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Tab][.png"; path = "../Common.iphone/Tab][.png"; sourceTree = SOURCE_ROOT; }; + 095542A7128375C40035AE09 /* Tab][@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Tab][@2x.png"; path = "../Common.iphone/Tab][@2x.png"; sourceTree = SOURCE_ROOT; }; + 096604C819127DB700A22C51 /* activegs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = activegs.plist; sourceTree = ""; }; + 09712D81133B66E4007AAADF /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 09712D85133B66F0007AAADF /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; + 0971D930126E4BE500EEBB1E /* icon72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon72.png; sourceTree = ""; }; + 0972554513CF2232006194F9 /* activegsEmulatorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = activegsEmulatorController.h; sourceTree = ""; }; + 0972554613CF2232006194F9 /* activegsEmulatorController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = activegsEmulatorController.mm; sourceTree = ""; }; + 0982685C124028E00064F134 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = ""; }; + 0982685D124028E00064F134 /* icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon@2x.png"; sourceTree = ""; }; + 099B5B8011F62D4900E597B6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = ""; }; + 099CD904125E6F6E008EFD6C /* detailViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = detailViewController.xib; path = ../Common.iphone/detailViewController.xib; sourceTree = SOURCE_ROOT; }; + 09A5CE5E125D41860018DC22 /* infoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = infoViewController.h; sourceTree = ""; }; + 09A5CE5F125D41860018DC22 /* infoViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = infoViewController.mm; sourceTree = ""; }; + 09A5CE75125D422D0018DC22 /* infoViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = infoViewController.xib; sourceTree = ""; }; + 09AADC76125C560A00654DF1 /* detailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detailViewController.h; sourceTree = ""; }; + 09AADC77125C560A00654DF1 /* detailViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = detailViewController.mm; sourceTree = ""; }; + 09AB6C09123EE1AE00816DB7 /* bouncinferno_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_1.png; sourceTree = ""; }; + 09AB6C0A123EE1AE00816DB7 /* bouncinferno_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_2.png; sourceTree = ""; }; + 09AB6C0B123EE1AE00816DB7 /* bouncinferno_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_3.png; sourceTree = ""; }; + 09AB6C0C123EE1AE00816DB7 /* bouncinferno_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_4.png; sourceTree = ""; }; + 09AB6C0D123EE1AE00816DB7 /* bouncinferno_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_5.png; sourceTree = ""; }; + 09AB6C0E123EE1AE00816DB7 /* bouncinferno_6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_6.png; sourceTree = ""; }; + 09AB6C0F123EE1AE00816DB7 /* bouncinferno_7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bouncinferno_7.png; sourceTree = ""; }; + 09AB6C18123EE1BA00816DB7 /* harrier1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = harrier1.png; sourceTree = ""; }; + 09AB6C1A123EE1CB00816DB7 /* SPACE_HARRIER.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = SPACE_HARRIER.FTA; sourceTree = ""; }; + 09AB6C1B123EE1CB00816DB7 /* thumb_bouncinferno.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_bouncinferno.png; sourceTree = ""; }; + 09AB6C1C123EE1CB00816DB7 /* thumb_harrier.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_harrier.png; sourceTree = ""; }; + 09AB6C24123EE2FA00816DB7 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; + 09AF98041283F0DF00083D60 /* Oil_Landers.fta */ = {isa = PBXFileReference; lastKnownFileType = file; path = Oil_Landers.fta; sourceTree = ""; }; + 09AF98061283F12200083D60 /* StarWizard (2002).fta */ = {isa = PBXFileReference; lastKnownFileType = file; path = "StarWizard (2002).fta"; sourceTree = ""; }; + 09AF98071283F12200083D60 /* starwizard_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = starwizard_2.png; sourceTree = ""; }; + 09AF98081283F12200083D60 /* starwizard_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = starwizard_3.png; sourceTree = ""; }; + 09AF98091283F12200083D60 /* starwizard_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = starwizard_4.png; sourceTree = ""; }; + 09AF980A1283F12200083D60 /* starwizard_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = starwizard_5.png; sourceTree = ""; }; + 09AF980B1283F12200083D60 /* starwizard.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = starwizard.png; sourceTree = ""; }; + 09BB434111D92F65005ADA46 /* ActiveDownloadMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActiveDownloadMac.cpp; sourceTree = ""; }; + 09BB434311D92F65005ADA46 /* CEmulatorCtrlMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CEmulatorCtrlMac.cpp; sourceTree = ""; }; + 09BB434411D92F65005ADA46 /* cemulatorctrlmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cemulatorctrlmac.h; sourceTree = ""; }; + 09BB438111D92F70005ADA46 /* activeconfig.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = activeconfig.cpp; sourceTree = ""; }; + 09BB438211D92F70005ADA46 /* ActiveDownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActiveDownload.cpp; sourceTree = ""; }; + 09BB438311D92F70005ADA46 /* ActiveDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActiveDownload.h; sourceTree = ""; }; + 09BB438411D92F70005ADA46 /* ActiveZip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActiveZip.cpp; sourceTree = ""; }; + 09BB438511D92F70005ADA46 /* CA2Text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CA2Text.cpp; sourceTree = ""; }; + 09BB438611D92F70005ADA46 /* CEmulatorCtrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CEmulatorCtrl.cpp; sourceTree = ""; }; + 09BB438711D92F70005ADA46 /* CEMulatorCtrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CEMulatorCtrl.h; sourceTree = ""; }; + 09BB438811D92F70005ADA46 /* interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interface.cpp; sourceTree = ""; }; + 09BB438911D92F70005ADA46 /* ki.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ki.h; sourceTree = ""; }; + 09BB438A11D92F70005ADA46 /* libpng.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libpng.cpp; sourceTree = ""; }; + 09BB438B11D92F70005ADA46 /* rom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rom.cpp; sourceTree = ""; }; + 09BB438E11D92F70005ADA46 /* svnversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = svnversion.h; sourceTree = ""; }; + 09BB43DB11D93063005ADA46 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; }; + 09BB43E211D93087005ADA46 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 09BCB6271211649D009858DF /* flobynoid (2002).dsk.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "flobynoid (2002).dsk.zip"; sourceTree = ""; }; + 09C81A361657ACAE008539D5 /* 16inst_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 16inst_c.h; sourceTree = ""; }; + 09C81A371657ACAE008539D5 /* 8inst_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 8inst_c.h; sourceTree = ""; }; + 09C81A391657ACAE008539D5 /* adb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = adb.cpp; sourceTree = ""; }; + 09C81A3A1657ACAE008539D5 /* adb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adb.h; sourceTree = ""; }; + 09C81A3B1657ACAE008539D5 /* async_event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = async_event.cpp; sourceTree = ""; }; + 09C81A3C1657ACAE008539D5 /* async_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = async_event.h; sourceTree = ""; }; + 09C81A3D1657ACAE008539D5 /* clock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clock.cpp; sourceTree = ""; }; + 09C81A3E1657ACAE008539D5 /* clock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clock.h; sourceTree = ""; }; + 09C81A3F1657ACAE008539D5 /* compile_time.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compile_time.cpp; sourceTree = ""; }; + 09C81A401657ACAE008539D5 /* compression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compression.cpp; sourceTree = ""; }; + 09C81A411657ACAE008539D5 /* compression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compression.h; sourceTree = ""; }; + 09C81A421657ACAE008539D5 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + 09C81A431657ACAE008539D5 /* config_generic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config_generic.cpp; sourceTree = ""; }; + 09C81A451657ACAE008539D5 /* defc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defc.h; sourceTree = ""; }; + 09C81A461657ACAE008539D5 /* defcomm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defcomm.h; sourceTree = ""; }; + 09C81A471657ACAE008539D5 /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = ""; }; + 09C81A481657ACAE008539D5 /* defs_instr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs_instr.h; sourceTree = ""; }; + 09C81A491657ACAE008539D5 /* dis.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dis.cpp; sourceTree = ""; }; + 09C81A4A1657ACAE008539D5 /* disas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = disas.h; sourceTree = ""; }; + 09C81A4B1657ACAE008539D5 /* engine_c.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = engine_c.cpp; sourceTree = ""; }; + 09C81A4C1657ACAE008539D5 /* GraphCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphCounter.cpp; sourceTree = ""; }; + 09C81A4D1657ACAE008539D5 /* graphcounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graphcounter.h; sourceTree = ""; }; + 09C81A4E1657ACAE008539D5 /* iwm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iwm.cpp; sourceTree = ""; }; + 09C81A4F1657ACAE008539D5 /* iwm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iwm.h; sourceTree = ""; }; + 09C81A501657ACAE008539D5 /* iwm_35_525.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iwm_35_525.h; sourceTree = ""; }; + 09C81A511657ACAE008539D5 /* kegsfont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kegsfont.h; sourceTree = ""; }; + 09C81A521657ACAE008539D5 /* kegsversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kegsversion.h; sourceTree = ""; }; + 09C81A531657ACAE008539D5 /* marinetti.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = marinetti.cpp; sourceTree = ""; }; + 09C81A541657ACAE008539D5 /* marinetti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = marinetti.h; sourceTree = ""; }; + 09C81A551657ACAE008539D5 /* marinetti_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = marinetti_helper.cpp; sourceTree = ""; }; + 09C81A561657ACAE008539D5 /* moremem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moremem.cpp; sourceTree = ""; }; + 09C81A571657ACAE008539D5 /* moremem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moremem.h; sourceTree = ""; }; + 09C81A581657ACAE008539D5 /* op_routs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = op_routs.h; sourceTree = ""; }; + 09C81A591657ACAE008539D5 /* openalasync_snddriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = openalasync_snddriver.cpp; sourceTree = ""; }; + 09C81A5A1657ACAE008539D5 /* paddles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = paddles.cpp; sourceTree = ""; }; + 09C81A5B1657ACAE008539D5 /* paddles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = paddles.h; sourceTree = ""; }; + 09C81A5C1657ACAE008539D5 /* prodos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prodos.h; sourceTree = ""; }; + 09C81A5D1657ACAE008539D5 /* prodos_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prodos_protos.h; sourceTree = ""; }; + 09C81A5E1657ACAE008539D5 /* protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protos.h; sourceTree = ""; }; + 09C81A5F1657ACAE008539D5 /* protos_engine_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protos_engine_c.h; sourceTree = ""; }; + 09C81A601657ACAE008539D5 /* protos_macdriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protos_macdriver.h; sourceTree = ""; }; + 09C81A611657ACAE008539D5 /* protos_macsnd_driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protos_macsnd_driver.h; sourceTree = ""; }; + 09C81A621657ACAE008539D5 /* protos_windriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protos_windriver.h; sourceTree = ""; }; + 09C81A631657ACAE008539D5 /* protos_xdriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protos_xdriver.h; sourceTree = ""; }; + 09C81A641657ACAE008539D5 /* raster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = raster.h; sourceTree = ""; }; + 09C81A651657ACAE008539D5 /* SaveState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SaveState.cpp; sourceTree = ""; }; + 09C81A661657ACAE008539D5 /* SaveState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveState.h; sourceTree = ""; }; + 09C81A671657ACAE008539D5 /* scc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scc.cpp; sourceTree = ""; }; + 09C81A681657ACAE008539D5 /* scc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scc.h; sourceTree = ""; }; + 09C81A691657ACAE008539D5 /* scc_socket_driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scc_socket_driver.cpp; sourceTree = ""; }; + 09C81A6A1657ACAE008539D5 /* sim65816.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sim65816.cpp; sourceTree = ""; }; + 09C81A6B1657ACAE008539D5 /* sim65816.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sim65816.h; sourceTree = ""; }; + 09C81A6C1657ACAE008539D5 /* size_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = size_c.h; sourceTree = ""; }; + 09C81A6E1657ACAE008539D5 /* size_tab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = size_tab.h; sourceTree = ""; }; + 09C81A6F1657ACAE008539D5 /* smartport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = smartport.cpp; sourceTree = ""; }; + 09C81A701657ACAE008539D5 /* sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound.cpp; sourceTree = ""; }; + 09C81A711657ACAE008539D5 /* sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound.h; sourceTree = ""; }; + 09C81A721657ACAE008539D5 /* sound_driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_driver.cpp; sourceTree = ""; }; + 09C81A731657ACAE008539D5 /* StdString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdString.h; sourceTree = ""; }; + 09C81A741657ACAE008539D5 /* superhires.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = superhires.h; sourceTree = ""; }; + 09C81A761657ACAE008539D5 /* video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video.cpp; sourceTree = ""; }; + 09C81A771657ACAE008539D5 /* video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = video.h; sourceTree = ""; }; + 09C81A921657ACDC008539D5 /* 2mg.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = 2mg.icns; sourceTree = ""; }; + 09C81A931657ACDC008539D5 /* 525.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = 525.icns; sourceTree = ""; }; + 09C81A941657ACDC008539D5 /* macdriver_activegs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macdriver_activegs.cpp; sourceTree = ""; }; + 09C81A951657ACDC008539D5 /* macdriver_generic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macdriver_generic.cpp; sourceTree = ""; }; + 09C81A981657ACDC008539D5 /* scc_macdriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scc_macdriver.cpp; sourceTree = ""; }; + 09C81AA11657AD18008539D5 /* emulatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emulatorView.h; sourceTree = ""; }; + 09C81AA21657AD18008539D5 /* emulatorView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = emulatorView.mm; sourceTree = ""; }; + 09C81AA31657AD18008539D5 /* joystick_iphone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = joystick_iphone.cpp; sourceTree = ""; }; + 09C81AA51657AD18008539D5 /* zoomEmulatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zoomEmulatorView.h; sourceTree = ""; }; + 09C81AA61657AD18008539D5 /* zoomEmulatorView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = zoomEmulatorView.mm; sourceTree = ""; }; + 09D8BCF81285EFE900B6D785 /* miniprix_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = miniprix_1.png; sourceTree = ""; }; + 09D8BCFA1285EFFA00B6D785 /* miniprix_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = miniprix_2.png; sourceTree = ""; }; + 09D8BCFB1285EFFA00B6D785 /* miniprix_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = miniprix_3.png; sourceTree = ""; }; + 09D8BCFE1285F00C00B6D785 /* oillanders_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = oillanders_1.png; sourceTree = ""; }; + 09D8BCFF1285F00C00B6D785 /* oillanders_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = oillanders_2.png; sourceTree = ""; }; + 09D8BD001285F00C00B6D785 /* oillanders_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = oillanders_3.png; sourceTree = ""; }; + 09D8BD011285F00C00B6D785 /* oillanders_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = oillanders_4.png; sourceTree = ""; }; + 09D8BD021285F00C00B6D785 /* oillanders_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = oillanders_5.png; sourceTree = ""; }; + 09E7BDE411FC935E00DCCFE7 /* floby1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = floby1.png; sourceTree = ""; }; + 09E7BDE511FC935E00DCCFE7 /* floby2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = floby2.png; sourceTree = ""; }; + 09E7BDE611FC935E00DCCFE7 /* floby3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = floby3.png; sourceTree = ""; }; + 09E7BDE811FC935E00DCCFE7 /* list.activegsxml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = list.activegsxml; sourceTree = ""; }; + 09E7BDE911FC935E00DCCFE7 /* MODULAE.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = MODULAE.FTA; sourceTree = ""; }; + 09E7BDEA11FC935E00DCCFE7 /* modulae_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_1.png; sourceTree = ""; }; + 09E7BDEB11FC935E00DCCFE7 /* modulae_10.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_10.png; sourceTree = ""; }; + 09E7BDEC11FC935E00DCCFE7 /* modulae_11.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_11.png; sourceTree = ""; }; + 09E7BDED11FC935E00DCCFE7 /* modulae_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_2.png; sourceTree = ""; }; + 09E7BDEE11FC935E00DCCFE7 /* modulae_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_3.png; sourceTree = ""; }; + 09E7BDEF11FC935E00DCCFE7 /* modulae_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_4.png; sourceTree = ""; }; + 09E7BDF011FC935E00DCCFE7 /* modulae_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_5.png; sourceTree = ""; }; + 09E7BDF111FC935E00DCCFE7 /* modulae_6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_6.png; sourceTree = ""; }; + 09E7BDF211FC935E00DCCFE7 /* modulae_7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_7.png; sourceTree = ""; }; + 09E7BDF311FC935E00DCCFE7 /* modulae_8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_8.png; sourceTree = ""; }; + 09E7BDF411FC935E00DCCFE7 /* modulae_9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modulae_9.png; sourceTree = ""; }; + 09E7BDF511FC935E00DCCFE7 /* NOISETRACKER.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = NOISETRACKER.FTA; sourceTree = ""; }; + 09E7BDF611FC935E00DCCFE7 /* noisetracker_0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = noisetracker_0.png; sourceTree = ""; }; + 09E7BDF711FC935E00DCCFE7 /* noisetracker_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = noisetracker_1.png; sourceTree = ""; }; + 09E7BDF811FC935E00DCCFE7 /* noisetracker_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = noisetracker_2.png; sourceTree = ""; }; + 09E7BDF911FC935E00DCCFE7 /* noisetracker_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = noisetracker_3.png; sourceTree = ""; }; + 09E7BDFB11FC935E00DCCFE7 /* nucleus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nucleus.png; sourceTree = ""; }; + 09E7BDFC11FC935E00DCCFE7 /* nucleus_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nucleus_2.png; sourceTree = ""; }; + 09E7BDFD11FC935E00DCCFE7 /* nucleus_c.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nucleus_c.png; sourceTree = ""; }; + 09E7BDFE11FC935E00DCCFE7 /* nucleus_t.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nucleus_t.png; sourceTree = ""; }; + 09E7BE0011FC935E00DCCFE7 /* thumb_floby.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_floby.png; sourceTree = ""; }; + 09E7BE0111FC935E00DCCFE7 /* thumb_system6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_system6.png; sourceTree = ""; }; + 09E7BE0211FC935E00DCCFE7 /* thumb_modulae.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_modulae.png; sourceTree = ""; }; + 09E7BE0311FC935E00DCCFE7 /* thumb_noisetracker.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_noisetracker.png; sourceTree = ""; }; + 09E7BE0411FC935E00DCCFE7 /* thumb_nucleus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_nucleus.png; sourceTree = ""; }; + 09E7BE0511FC935E00DCCFE7 /* thumb_xmas.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_xmas.png; sourceTree = ""; }; + 09E7BE0611FC935E00DCCFE7 /* xmas_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_1.png; sourceTree = ""; }; + 09E7BE0711FC935E00DCCFE7 /* xmas_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_2.png; sourceTree = ""; }; + 09E7BE0811FC935E00DCCFE7 /* xmas_3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_3.png; sourceTree = ""; }; + 09E7BE0911FC935E00DCCFE7 /* xmas_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_4.png; sourceTree = ""; }; + 09E7BE0A11FC935E00DCCFE7 /* xmas_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_5.png; sourceTree = ""; }; + 09E7BE0B11FC935E00DCCFE7 /* xmas_6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_6.png; sourceTree = ""; }; + 09E7BE0C11FC935E00DCCFE7 /* xmas_7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_7.png; sourceTree = ""; }; + 09E7BE0D11FC935E00DCCFE7 /* xmas_8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = xmas_8.png; sourceTree = ""; }; + 09E7BE0E11FC935E00DCCFE7 /* XMASDEMO.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = XMASDEMO.FTA; sourceTree = ""; }; + 09FA6079125A7B3E00B07F77 /* activegsAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = activegsAppDelegate.h; sourceTree = ""; }; + 09FA607A125A7B3E00B07F77 /* activegsAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = activegsAppDelegate.mm; sourceTree = ""; }; + 09FA607B125A7B3E00B07F77 /* activegsList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = activegsList.h; sourceTree = ""; }; + 09FA607C125A7B3E00B07F77 /* activegsList.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = activegsList.mm; sourceTree = ""; }; + 09FA607D125A7B3E00B07F77 /* activegsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = activegsViewController.h; sourceTree = ""; }; + 09FA607E125A7B3E00B07F77 /* activegsViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = activegsViewController.mm; sourceTree = ""; }; + 09FA607F125A7B3E00B07F77 /* activegsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = activegsViewController.xib; sourceTree = ""; }; + 09FA6082125A7B3E00B07F77 /* asyncimageview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asyncimageview.h; sourceTree = ""; }; + 09FA6083125A7B3E00B07F77 /* asyncimageview.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = asyncimageview.mm; sourceTree = ""; }; + 09FA6086125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMUIView+SubtreeDescription.h"; sourceTree = ""; }; + 09FA6087125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMUIView+SubtreeDescription.m"; sourceTree = ""; }; + 09FA6088125A7B3E00B07F77 /* icon_APPLE 2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_APPLE 2.png"; sourceTree = ""; }; + 09FA6089125A7B3E00B07F77 /* icon_APPLE 2GS.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_APPLE 2GS.png"; sourceTree = ""; }; + 09FA608A125A7B3E00B07F77 /* KBDController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KBDController.h; sourceTree = ""; }; + 09FA608B125A7B3E00B07F77 /* KBDController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KBDController.mm; sourceTree = ""; }; + 09FD36F01278CCEB009C31AB /* BLUE_HELMET.FTA */ = {isa = PBXFileReference; lastKnownFileType = file; path = BLUE_HELMET.FTA; sourceTree = ""; }; + 09FD36F11278CCEB009C31AB /* bluehelmet_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bluehelmet_1.png; sourceTree = ""; }; + 09FD36F21278CCEB009C31AB /* bluehelmet_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bluehelmet_2.png; sourceTree = ""; }; + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 29B97316FDCFA39411CA2CEA /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* activegs_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = activegs_Prefix.pch; sourceTree = ""; }; + 7E51480C1CA6B5CE005DA0A6 /* ActiveGS.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ActiveGS.png; sourceTree = ""; }; + 7E51480D1CA6B5CE005DA0A6 /* Apple_2_Disk_Drive_Sounds.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Apple_2_Disk_Drive_Sounds.txt; sourceTree = ""; }; + 7E51480E1CA6B5CE005DA0A6 /* disk.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = disk.png; sourceTree = ""; }; + 7E51480F1CA6B5CE005DA0A6 /* disk_35_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = disk_35_1.png; sourceTree = ""; }; + 7E5148101CA6B5CE005DA0A6 /* disk_35_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = disk_35_2.png; sourceTree = ""; }; + 7E5148111CA6B5CE005DA0A6 /* disk_525_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = disk_525_1.png; sourceTree = ""; }; + 7E5148121CA6B5CE005DA0A6 /* disk_525_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = disk_525_2.png; sourceTree = ""; }; + 7E5148131CA6B5CE005DA0A6 /* facebook-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-logo.png"; sourceTree = ""; }; + 7E5148141CA6B5CE005DA0A6 /* floppy_eject.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = floppy_eject.wav; sourceTree = ""; }; + 7E5148151CA6B5CE005DA0A6 /* logo_apple2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo_apple2.png; sourceTree = ""; }; + 7E5148161CA6B5CE005DA0A6 /* logo_apple2gs.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo_apple2gs.png; sourceTree = ""; }; + 7E5148171CA6B5CE005DA0A6 /* Search Skip Search 1.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Search Skip Search 1.wav"; sourceTree = ""; }; + 7E5148181CA6B5CE005DA0A6 /* Search Skip Search 2.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Search Skip Search 2.wav"; sourceTree = ""; }; + 7E5148191CA6B5CE005DA0A6 /* Search Skip Search 3.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Search Skip Search 3.wav"; sourceTree = ""; }; + 7E51481A1CA6B5CE005DA0A6 /* Search Skip Search 4.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Search Skip Search 4.wav"; sourceTree = ""; }; + 7E51481B1CA6B5CE005DA0A6 /* Search Skip Search 5.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Search Skip Search 5.wav"; sourceTree = ""; }; + 7E51481C1CA6B5CE005DA0A6 /* ShastonHi640.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ShastonHi640.ttf; sourceTree = ""; }; + 7E51481D1CA6B5CE005DA0A6 /* Spin Up Search 1.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Spin Up Search 1.wav"; sourceTree = ""; }; + 7E51481E1CA6B5CE005DA0A6 /* Spin Up Search 2.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "Spin Up Search 2.wav"; sourceTree = ""; }; + 7E8EED6A1A7D83C900C6E522 /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 095036E9190547BE006A457A /* CoreLocation.framework in Frameworks */, + 095036E7190547A0006A457A /* AdSupport.framework in Frameworks */, + 095036E519054799006A457A /* CoreData.framework in Frameworks */, + 0905905213A76C23006E67D7 /* AudioToolbox.framework in Frameworks */, + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + 09BB43DC11D93063005ADA46 /* OpenAL.framework in Frameworks */, + 09BB43E311D93087005ADA46 /* CFNetwork.framework in Frameworks */, + 099B5B8111F62D4900E597B6 /* QuartzCore.framework in Frameworks */, + 09712D82133B66E4007AAADF /* SystemConfiguration.framework in Frameworks */, + 09712D86133B66F0007AAADF /* CoreTelephony.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 09052B4219053C9F00853FAE /* Libraries */ = { + isa = PBXGroup; + children = ( + 09052B4319053C9F00853FAE /* libpng */, + 09052B5719053C9F00853FAE /* unzip101e */, + 09052B6119053C9F00853FAE /* zlib123 */, + ); + name = Libraries; + path = ../Libraries; + sourceTree = ""; + }; + 09052B4319053C9F00853FAE /* libpng */ = { + isa = PBXGroup; + children = ( + 09052B4419053C9F00853FAE /* png.cpp */, + 09052B4519053C9F00853FAE /* png.h */, + 09052B4619053C9F00853FAE /* pngconf.h */, + 09052B4719053C9F00853FAE /* pngerror.cpp */, + 09052B4819053C9F00853FAE /* pnggccrd.cpp */, + 09052B4919053C9F00853FAE /* pngget.cpp */, + 09052B4A19053C9F00853FAE /* pngmem.cpp */, + 09052B4B19053C9F00853FAE /* pngpread.cpp */, + 09052B4C19053C9F00853FAE /* pngread.cpp */, + 09052B4D19053C9F00853FAE /* pngrio.cpp */, + 09052B4E19053C9F00853FAE /* pngrtran.cpp */, + 09052B4F19053C9F00853FAE /* pngrutil.cpp */, + 09052B5019053C9F00853FAE /* pngset.cpp */, + 09052B5119053C9F00853FAE /* pngtrans.cpp */, + 09052B5219053C9F00853FAE /* pngvcrd.cpp */, + 09052B5319053C9F00853FAE /* pngwio.cpp */, + 09052B5419053C9F00853FAE /* pngwrite.cpp */, + 09052B5519053C9F00853FAE /* pngwtran.cpp */, + 09052B5619053C9F00853FAE /* pngwutil.cpp */, + ); + path = libpng; + sourceTree = ""; + }; + 09052B5719053C9F00853FAE /* unzip101e */ = { + isa = PBXGroup; + children = ( + 09052B5819053C9F00853FAE /* crypt.h */, + 09052B5919053C9F00853FAE /* ioapi.cpp */, + 09052B5A19053C9F00853FAE /* ioapi.h */, + 09052B5B19053C9F00853FAE /* iowin32.cpp */, + 09052B5C19053C9F00853FAE /* iowin32.h */, + 09052B5D19053C9F00853FAE /* unzip.cpp */, + 09052B5E19053C9F00853FAE /* unzip.h */, + 09052B5F19053C9F00853FAE /* zip.cpp */, + 09052B6019053C9F00853FAE /* zip.h */, + ); + path = unzip101e; + sourceTree = ""; + }; + 09052B6119053C9F00853FAE /* zlib123 */ = { + isa = PBXGroup; + children = ( + 09052B6219053C9F00853FAE /* adler32.cpp */, + 09052B6319053C9F00853FAE /* compress.cpp */, + 09052B6419053C9F00853FAE /* crc32.cpp */, + 09052B6519053C9F00853FAE /* crc32.h */, + 09052B6619053C9F00853FAE /* deflate.cpp */, + 09052B6719053C9F00853FAE /* deflate.h */, + 09052B6819053C9F00853FAE /* inffast.cpp */, + 09052B6919053C9F00853FAE /* inffast.h */, + 09052B6A19053C9F00853FAE /* inffixed.h */, + 09052B6B19053C9F00853FAE /* inflate.cpp */, + 09052B6C19053C9F00853FAE /* inflate.h */, + 09052B6D19053C9F00853FAE /* inftrees.cpp */, + 09052B6E19053C9F00853FAE /* inftrees.h */, + 09052B6F19053C9F00853FAE /* trees.cpp */, + 09052B7019053C9F00853FAE /* trees.h */, + 09052B7119053C9F00853FAE /* uncompr.cpp */, + 09052B7219053C9F00853FAE /* zconf.h */, + 09052B7319053C9F00853FAE /* zconf.in.h */, + 09052B7419053C9F00853FAE /* zlib.h */, + 09052B7519053C9F00853FAE /* zutil.cpp */, + 09052B7619053C9F00853FAE /* zutil.h */, + ); + path = zlib123; + sourceTree = ""; + }; + 0941E6AC16720886003E0411 /* 3rdpartylib */ = { + isa = PBXGroup; + children = ( + 0941E6AD16720886003E0411 /* simplexml.cpp */, + 0941E6AE16720886003E0411 /* simplexml.h */, + ); + path = 3rdpartylib; + sourceTree = ""; + }; + 09520D8516AEF8250065E84A /* Drivers */ = { + isa = PBXGroup; + children = ( + 09520D8616AEF8250065E84A /* activegs_driver.cpp */, + ); + name = Drivers; + path = ../Drivers; + sourceTree = ""; + }; + 09B8EB85163B2C06000A9F6B /* xib */ = { + isa = PBXGroup; + children = ( + 0916BB03129473CE001727AF /* infoViewController-ipad.xib */, + 09A5CE75125D422D0018DC22 /* infoViewController.xib */, + 099CD904125E6F6E008EFD6C /* detailViewController.xib */, + ); + name = xib; + sourceTree = ""; + }; + 09B8EB86163B2F34000A9F6B /* Private Framework */ = { + isa = PBXGroup; + children = ( + ); + name = "Private Framework"; + sourceTree = ""; + }; + 09BB434011D92F65005ADA46 /* Common.osx */ = { + isa = PBXGroup; + children = ( + 09BB434111D92F65005ADA46 /* ActiveDownloadMac.cpp */, + 09BB434311D92F65005ADA46 /* CEmulatorCtrlMac.cpp */, + 09BB434411D92F65005ADA46 /* cemulatorctrlmac.h */, + ); + name = Common.osx; + path = ../Common.osx; + sourceTree = SOURCE_ROOT; + }; + 09BB434811D92F70005ADA46 /* Common */ = { + isa = PBXGroup; + children = ( + 09520D8C16AEF8650065E84A /* apple2e.cpp */, + 0941E6AC16720886003E0411 /* 3rdpartylib */, + 0941E6A916720840003E0411 /* ActiveGSList.cpp */, + 0941E6AA16720840003E0411 /* ActiveGSList.h */, + 09BB438111D92F70005ADA46 /* activeconfig.cpp */, + 09BB438211D92F70005ADA46 /* ActiveDownload.cpp */, + 09BB438311D92F70005ADA46 /* ActiveDownload.h */, + 09BB438411D92F70005ADA46 /* ActiveZip.cpp */, + 09BB438511D92F70005ADA46 /* CA2Text.cpp */, + 09BB438611D92F70005ADA46 /* CEmulatorCtrl.cpp */, + 09BB438711D92F70005ADA46 /* CEMulatorCtrl.h */, + 09BB438811D92F70005ADA46 /* interface.cpp */, + 09BB438911D92F70005ADA46 /* ki.h */, + 09BB438A11D92F70005ADA46 /* libpng.cpp */, + 09BB438B11D92F70005ADA46 /* rom.cpp */, + 09BB438E11D92F70005ADA46 /* svnversion.h */, + ); + name = Common; + path = ../Common; + sourceTree = SOURCE_ROOT; + }; + 09C81A351657ACAE008539D5 /* Src */ = { + isa = PBXGroup; + children = ( + 09520D8116AEF8130065E84A /* driver.cpp */, + 09520D8216AEF8130065E84A /* driver.h */, + 09C81A361657ACAE008539D5 /* 16inst_c.h */, + 09C81A371657ACAE008539D5 /* 8inst_c.h */, + 09C81A391657ACAE008539D5 /* adb.cpp */, + 09C81A3A1657ACAE008539D5 /* adb.h */, + 09C81A3B1657ACAE008539D5 /* async_event.cpp */, + 09C81A3C1657ACAE008539D5 /* async_event.h */, + 09C81A3D1657ACAE008539D5 /* clock.cpp */, + 09C81A3E1657ACAE008539D5 /* clock.h */, + 09C81A3F1657ACAE008539D5 /* compile_time.cpp */, + 09C81A401657ACAE008539D5 /* compression.cpp */, + 09C81A411657ACAE008539D5 /* compression.h */, + 09C81A421657ACAE008539D5 /* config.h */, + 09C81A431657ACAE008539D5 /* config_generic.cpp */, + 09C81A451657ACAE008539D5 /* defc.h */, + 09C81A461657ACAE008539D5 /* defcomm.h */, + 09C81A471657ACAE008539D5 /* defs.h */, + 09C81A481657ACAE008539D5 /* defs_instr.h */, + 09C81A491657ACAE008539D5 /* dis.cpp */, + 09C81A4A1657ACAE008539D5 /* disas.h */, + 09C81A4B1657ACAE008539D5 /* engine_c.cpp */, + 09C81A4C1657ACAE008539D5 /* GraphCounter.cpp */, + 09C81A4D1657ACAE008539D5 /* graphcounter.h */, + 09C81A4E1657ACAE008539D5 /* iwm.cpp */, + 09C81A4F1657ACAE008539D5 /* iwm.h */, + 09C81A501657ACAE008539D5 /* iwm_35_525.h */, + 09C81A511657ACAE008539D5 /* kegsfont.h */, + 09C81A521657ACAE008539D5 /* kegsversion.h */, + 09C81A531657ACAE008539D5 /* marinetti.cpp */, + 09C81A541657ACAE008539D5 /* marinetti.h */, + 09C81A551657ACAE008539D5 /* marinetti_helper.cpp */, + 09C81A561657ACAE008539D5 /* moremem.cpp */, + 09C81A571657ACAE008539D5 /* moremem.h */, + 09C81A581657ACAE008539D5 /* op_routs.h */, + 09C81A591657ACAE008539D5 /* openalasync_snddriver.cpp */, + 09C81A5A1657ACAE008539D5 /* paddles.cpp */, + 09C81A5B1657ACAE008539D5 /* paddles.h */, + 09C81A5C1657ACAE008539D5 /* prodos.h */, + 09C81A5D1657ACAE008539D5 /* prodos_protos.h */, + 09C81A5E1657ACAE008539D5 /* protos.h */, + 09C81A5F1657ACAE008539D5 /* protos_engine_c.h */, + 09C81A601657ACAE008539D5 /* protos_macdriver.h */, + 09C81A611657ACAE008539D5 /* protos_macsnd_driver.h */, + 09C81A621657ACAE008539D5 /* protos_windriver.h */, + 09C81A631657ACAE008539D5 /* protos_xdriver.h */, + 09C81A641657ACAE008539D5 /* raster.h */, + 09C81A651657ACAE008539D5 /* SaveState.cpp */, + 09C81A661657ACAE008539D5 /* SaveState.h */, + 09C81A671657ACAE008539D5 /* scc.cpp */, + 09C81A681657ACAE008539D5 /* scc.h */, + 09C81A691657ACAE008539D5 /* scc_socket_driver.cpp */, + 09C81A6A1657ACAE008539D5 /* sim65816.cpp */, + 09C81A6B1657ACAE008539D5 /* sim65816.h */, + 09C81A6C1657ACAE008539D5 /* size_c.h */, + 09C81A6E1657ACAE008539D5 /* size_tab.h */, + 09C81A6F1657ACAE008539D5 /* smartport.cpp */, + 09C81A701657ACAE008539D5 /* sound.cpp */, + 09C81A711657ACAE008539D5 /* sound.h */, + 09C81A721657ACAE008539D5 /* sound_driver.cpp */, + 09C81A731657ACAE008539D5 /* StdString.h */, + 09C81A741657ACAE008539D5 /* superhires.h */, + 09C81A761657ACAE008539D5 /* video.cpp */, + 09C81A771657ACAE008539D5 /* video.h */, + ); + name = Src; + path = ../kegs/Src; + sourceTree = ""; + }; + 09C81A911657ACDC008539D5 /* OSX */ = { + isa = PBXGroup; + children = ( + 09C81A921657ACDC008539D5 /* 2mg.icns */, + 09C81A931657ACDC008539D5 /* 525.icns */, + 09C81A941657ACDC008539D5 /* macdriver_activegs.cpp */, + 09C81A951657ACDC008539D5 /* macdriver_generic.cpp */, + 09C81A981657ACDC008539D5 /* scc_macdriver.cpp */, + ); + name = OSX; + path = ../kegs/OSX; + sourceTree = ""; + }; + 09C81AA01657AD18008539D5 /* iOS */ = { + isa = PBXGroup; + children = ( + 09C81AA11657AD18008539D5 /* emulatorView.h */, + 09C81AA21657AD18008539D5 /* emulatorView.mm */, + 09C81AA31657AD18008539D5 /* joystick_iphone.cpp */, + 09C81AA51657AD18008539D5 /* zoomEmulatorView.h */, + 09C81AA61657AD18008539D5 /* zoomEmulatorView.mm */, + ); + name = iOS; + path = ../kegs/iOS; + sourceTree = ""; + }; + 09E7BDE311FC935E00DCCFE7 /* DefaultPackage */ = { + isa = PBXGroup; + children = ( + 0941E6731670E391003E0411 /* BOUNCIN_FERNO.FTA */, + 0941E6741670E391003E0411 /* MINIPRIX.FTA */, + 0941E6711670E23F003E0411 /* PHOTONIX.FTA */, + 0941E66F1670E143003E0411 /* DELTA.FTA */, + 0941E66D1670E086003E0411 /* NUCLEUS.FTA */, + 09D8BCFE1285F00C00B6D785 /* oillanders_1.png */, + 09D8BCFF1285F00C00B6D785 /* oillanders_2.png */, + 09D8BD001285F00C00B6D785 /* oillanders_3.png */, + 09D8BD011285F00C00B6D785 /* oillanders_4.png */, + 09D8BD021285F00C00B6D785 /* oillanders_5.png */, + 09D8BCFA1285EFFA00B6D785 /* miniprix_2.png */, + 09D8BCFB1285EFFA00B6D785 /* miniprix_3.png */, + 09D8BCF81285EFE900B6D785 /* miniprix_1.png */, + 09AF98061283F12200083D60 /* StarWizard (2002).fta */, + 09AF98071283F12200083D60 /* starwizard_2.png */, + 09AF98081283F12200083D60 /* starwizard_3.png */, + 09AF98091283F12200083D60 /* starwizard_4.png */, + 09AF980A1283F12200083D60 /* starwizard_5.png */, + 09AF980B1283F12200083D60 /* starwizard.png */, + 09AF98041283F0DF00083D60 /* Oil_Landers.fta */, + 09FD36F01278CCEB009C31AB /* BLUE_HELMET.FTA */, + 09FD36F11278CCEB009C31AB /* bluehelmet_1.png */, + 09FD36F21278CCEB009C31AB /* bluehelmet_2.png */, + 090E7BDD123F966C003EE2C3 /* thumb_poms.png */, + 090E7BCF123F965F003EE2C3 /* poms_1.png */, + 090E7BD0123F965F003EE2C3 /* poms_2.png */, + 090E7BD1123F965F003EE2C3 /* poms_3.png */, + 090E7BD2123F965F003EE2C3 /* poms_4.png */, + 090E7BD3123F965F003EE2C3 /* poms_5.png */, + 090E7BD4123F965F003EE2C3 /* poms_6.png */, + 09AB6C1A123EE1CB00816DB7 /* SPACE_HARRIER.FTA */, + 09AB6C1B123EE1CB00816DB7 /* thumb_bouncinferno.png */, + 09AB6C1C123EE1CB00816DB7 /* thumb_harrier.png */, + 09AB6C18123EE1BA00816DB7 /* harrier1.png */, + 09AB6C09123EE1AE00816DB7 /* bouncinferno_1.png */, + 09AB6C0A123EE1AE00816DB7 /* bouncinferno_2.png */, + 09AB6C0B123EE1AE00816DB7 /* bouncinferno_3.png */, + 09AB6C0C123EE1AE00816DB7 /* bouncinferno_4.png */, + 09AB6C0D123EE1AE00816DB7 /* bouncinferno_5.png */, + 09AB6C0E123EE1AE00816DB7 /* bouncinferno_6.png */, + 09AB6C0F123EE1AE00816DB7 /* bouncinferno_7.png */, + 09087F2B12244C0500C52D88 /* delta_1.png */, + 09087F2C12244C0500C52D88 /* delta_2.png */, + 09087F2D12244C0500C52D88 /* delta_3.png */, + 09087F2E12244C0500C52D88 /* delta_4.png */, + 09087F2F12244C0500C52D88 /* delta_5.png */, + 09087F3012244C0500C52D88 /* delta_6.png */, + 09087F3112244C0500C52D88 /* delta_7.png */, + 09087F3412244C0500C52D88 /* photonix_1.png */, + 09087F3512244C0500C52D88 /* photonix_2.png */, + 09087F3712244C0500C52D88 /* thumb_delta.png */, + 09087F3812244C0500C52D88 /* thumb_gsos.png */, + 09087F3912244C0500C52D88 /* thumb_photonix.png */, + 09BCB6271211649D009858DF /* flobynoid (2002).dsk.zip */, + 09E7BDE411FC935E00DCCFE7 /* floby1.png */, + 09E7BDE511FC935E00DCCFE7 /* floby2.png */, + 09E7BDE611FC935E00DCCFE7 /* floby3.png */, + 09E7BDE811FC935E00DCCFE7 /* list.activegsxml */, + 09E7BDE911FC935E00DCCFE7 /* MODULAE.FTA */, + 09E7BDEA11FC935E00DCCFE7 /* modulae_1.png */, + 09E7BDEB11FC935E00DCCFE7 /* modulae_10.png */, + 09E7BDEC11FC935E00DCCFE7 /* modulae_11.png */, + 09E7BDED11FC935E00DCCFE7 /* modulae_2.png */, + 09E7BDEE11FC935E00DCCFE7 /* modulae_3.png */, + 09E7BDEF11FC935E00DCCFE7 /* modulae_4.png */, + 09E7BDF011FC935E00DCCFE7 /* modulae_5.png */, + 09E7BDF111FC935E00DCCFE7 /* modulae_6.png */, + 09E7BDF211FC935E00DCCFE7 /* modulae_7.png */, + 09E7BDF311FC935E00DCCFE7 /* modulae_8.png */, + 09E7BDF411FC935E00DCCFE7 /* modulae_9.png */, + 09E7BDF511FC935E00DCCFE7 /* NOISETRACKER.FTA */, + 09E7BDF711FC935E00DCCFE7 /* noisetracker_1.png */, + 09E7BDF611FC935E00DCCFE7 /* noisetracker_0.png */, + 09E7BDF811FC935E00DCCFE7 /* noisetracker_2.png */, + 09E7BDF911FC935E00DCCFE7 /* noisetracker_3.png */, + 09E7BDFB11FC935E00DCCFE7 /* nucleus.png */, + 09E7BDFC11FC935E00DCCFE7 /* nucleus_2.png */, + 09E7BDFD11FC935E00DCCFE7 /* nucleus_c.png */, + 09E7BDFE11FC935E00DCCFE7 /* nucleus_t.png */, + 09E7BE0011FC935E00DCCFE7 /* thumb_floby.png */, + 09E7BE0111FC935E00DCCFE7 /* thumb_system6.png */, + 09E7BE0211FC935E00DCCFE7 /* thumb_modulae.png */, + 09E7BE0311FC935E00DCCFE7 /* thumb_noisetracker.png */, + 09E7BE0411FC935E00DCCFE7 /* thumb_nucleus.png */, + 09E7BE0511FC935E00DCCFE7 /* thumb_xmas.png */, + 09E7BE0611FC935E00DCCFE7 /* xmas_1.png */, + 09E7BE0711FC935E00DCCFE7 /* xmas_2.png */, + 09E7BE0811FC935E00DCCFE7 /* xmas_3.png */, + 09E7BE0911FC935E00DCCFE7 /* xmas_4.png */, + 09E7BE0A11FC935E00DCCFE7 /* xmas_5.png */, + 09E7BE0B11FC935E00DCCFE7 /* xmas_6.png */, + 09E7BE0C11FC935E00DCCFE7 /* xmas_7.png */, + 09E7BE0D11FC935E00DCCFE7 /* xmas_8.png */, + 09E7BE0E11FC935E00DCCFE7 /* XMASDEMO.FTA */, + ); + name = DefaultPackage; + path = ../DefaultPackage; + sourceTree = SOURCE_ROOT; + }; + 09FA6078125A7B3E00B07F77 /* Common.iphone */ = { + isa = PBXGroup; + children = ( + 0907BCC7142F567A0051CA0A /* asynccommand.h */, + 0907BCC8142F567A0051CA0A /* asynccommand.mm */, + 0972554513CF2232006194F9 /* activegsEmulatorController.h */, + 0972554613CF2232006194F9 /* activegsEmulatorController.mm */, + 09A5CE5E125D41860018DC22 /* infoViewController.h */, + 09A5CE5F125D41860018DC22 /* infoViewController.mm */, + 09AADC76125C560A00654DF1 /* detailViewController.h */, + 09AADC77125C560A00654DF1 /* detailViewController.mm */, + 09FA6079125A7B3E00B07F77 /* activegsAppDelegate.h */, + 09FA607A125A7B3E00B07F77 /* activegsAppDelegate.mm */, + 09FA607B125A7B3E00B07F77 /* activegsList.h */, + 09FA607C125A7B3E00B07F77 /* activegsList.mm */, + 09FA607D125A7B3E00B07F77 /* activegsViewController.h */, + 09FA607E125A7B3E00B07F77 /* activegsViewController.mm */, + 09FA607F125A7B3E00B07F77 /* activegsViewController.xib */, + 09FA6082125A7B3E00B07F77 /* asyncimageview.h */, + 09FA6083125A7B3E00B07F77 /* asyncimageview.mm */, + 09FA6086125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.h */, + 09FA6087125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.m */, + 09FA6088125A7B3E00B07F77 /* icon_APPLE 2.png */, + 09FA6089125A7B3E00B07F77 /* icon_APPLE 2GS.png */, + 09FA608A125A7B3E00B07F77 /* KBDController.h */, + 09FA608B125A7B3E00B07F77 /* KBDController.mm */, + ); + name = Common.iphone; + path = ../Common.iphone; + sourceTree = SOURCE_ROOT; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 0913BFCF13033D77004B3039 /* ActiveGS.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 7E8EED6A1A7D83C900C6E522 /* Entitlements.plist */, + 096604C819127DB700A22C51 /* activegs.plist */, + 09052B4219053C9F00853FAE /* Libraries */, + 09520D8516AEF8250065E84A /* Drivers */, + 09C81AA01657AD18008539D5 /* iOS */, + 09C81A911657ACDC008539D5 /* OSX */, + 09C81A351657ACAE008539D5 /* Src */, + 09B8EB85163B2C06000A9F6B /* xib */, + 09FA6078125A7B3E00B07F77 /* Common.iphone */, + 7E51480B1CA6B5CE005DA0A6 /* Common.res */, + 09BB434811D92F70005ADA46 /* Common */, + 09BB434011D92F65005ADA46 /* Common.osx */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 09B8EB86163B2F34000A9F6B /* Private Framework */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* activegs_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.mm */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 090A6076163093D800C8FB59 /* Default-568h@2x.png */, + 095542A6128375C40035AE09 /* Tab][.png */, + 095542A7128375C40035AE09 /* Tab][@2x.png */, + 0902FEC712820467002E7C03 /* Tab2GS.png */, + 0955429E12836F4D0035AE09 /* Tab2GS@2x.png */, + 0902FEEE12820678002E7C03 /* TabFTA.png */, + 0902FEE612820626002E7C03 /* TabFTA@2x.png */, + 0971D930126E4BE500EEBB1E /* icon72.png */, + 0982685C124028E00064F134 /* icon.png */, + 0982685D124028E00064F134 /* icon@2x.png */, + 09AB6C24123EE2FA00816DB7 /* Default.png */, + 09E7BDE311FC935E00DCCFE7 /* DefaultPackage */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 095036E8190547BE006A457A /* CoreLocation.framework */, + 095036E6190547A0006A457A /* AdSupport.framework */, + 095036E419054799006A457A /* CoreData.framework */, + 0905905113A76C23006E67D7 /* AudioToolbox.framework */, + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + 09BB43DB11D93063005ADA46 /* OpenAL.framework */, + 09BB43E211D93087005ADA46 /* CFNetwork.framework */, + 099B5B8011F62D4900E597B6 /* QuartzCore.framework */, + 09712D81133B66E4007AAADF /* SystemConfiguration.framework */, + 09712D85133B66F0007AAADF /* CoreTelephony.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 7E51480B1CA6B5CE005DA0A6 /* Common.res */ = { + isa = PBXGroup; + children = ( + 7E51480C1CA6B5CE005DA0A6 /* ActiveGS.png */, + 7E51480D1CA6B5CE005DA0A6 /* Apple_2_Disk_Drive_Sounds.txt */, + 7E51480E1CA6B5CE005DA0A6 /* disk.png */, + 7E51480F1CA6B5CE005DA0A6 /* disk_35_1.png */, + 7E5148101CA6B5CE005DA0A6 /* disk_35_2.png */, + 7E5148111CA6B5CE005DA0A6 /* disk_525_1.png */, + 7E5148121CA6B5CE005DA0A6 /* disk_525_2.png */, + 7E5148131CA6B5CE005DA0A6 /* facebook-logo.png */, + 7E5148141CA6B5CE005DA0A6 /* floppy_eject.wav */, + 7E5148151CA6B5CE005DA0A6 /* logo_apple2.png */, + 7E5148161CA6B5CE005DA0A6 /* logo_apple2gs.png */, + 7E5148171CA6B5CE005DA0A6 /* Search Skip Search 1.wav */, + 7E5148181CA6B5CE005DA0A6 /* Search Skip Search 2.wav */, + 7E5148191CA6B5CE005DA0A6 /* Search Skip Search 3.wav */, + 7E51481A1CA6B5CE005DA0A6 /* Search Skip Search 4.wav */, + 7E51481B1CA6B5CE005DA0A6 /* Search Skip Search 5.wav */, + 7E51481C1CA6B5CE005DA0A6 /* ShastonHi640.ttf */, + 7E51481D1CA6B5CE005DA0A6 /* Spin Up Search 1.wav */, + 7E51481E1CA6B5CE005DA0A6 /* Spin Up Search 2.wav */, + ); + name = Common.res; + path = /Users/ogoguel/Code/ActiveGS/Common.res; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* ActiveGS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ActiveGS" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + 095F842613AFDD9C009C540E /* CopyFiles */, + 095981521A3E1A76007C90A8 /* ShellScript */, + ); + buildRules = ( + 095981511A3E1A2D007C90A8 /* PBXBuildRule */, + ); + dependencies = ( + ); + name = ActiveGS; + productName = activegs; + productReference = 0913BFCF13033D77004B3039 /* ActiveGS.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + TargetAttributes = { + 1D6058900D05DD3D006BFB54 = { + DevelopmentTeam = SQ9T3Q7RV4; + SystemCapabilities = { + com.apple.DataProtection = { + enabled = 0; + }; + }; + }; + }; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "activegs" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* ActiveGS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E5148201CA6B5CE005DA0A6 /* Apple_2_Disk_Drive_Sounds.txt in Resources */, + 09E7BE0F11FC935E00DCCFE7 /* floby1.png in Resources */, + 09E7BE1011FC935E00DCCFE7 /* floby2.png in Resources */, + 09E7BE1111FC935E00DCCFE7 /* floby3.png in Resources */, + 09E7BE1311FC935E00DCCFE7 /* list.activegsxml in Resources */, + 09E7BE1411FC935E00DCCFE7 /* MODULAE.FTA in Resources */, + 09E7BE1511FC935E00DCCFE7 /* modulae_1.png in Resources */, + 09E7BE1611FC935E00DCCFE7 /* modulae_10.png in Resources */, + 7E5148231CA6B5CE005DA0A6 /* disk_35_2.png in Resources */, + 09E7BE1711FC935E00DCCFE7 /* modulae_11.png in Resources */, + 09E7BE1811FC935E00DCCFE7 /* modulae_2.png in Resources */, + 09E7BE1911FC935E00DCCFE7 /* modulae_3.png in Resources */, + 09E7BE1A11FC935E00DCCFE7 /* modulae_4.png in Resources */, + 09E7BE1B11FC935E00DCCFE7 /* modulae_5.png in Resources */, + 09E7BE1C11FC935E00DCCFE7 /* modulae_6.png in Resources */, + 09E7BE1D11FC935E00DCCFE7 /* modulae_7.png in Resources */, + 09E7BE1E11FC935E00DCCFE7 /* modulae_8.png in Resources */, + 09E7BE1F11FC935E00DCCFE7 /* modulae_9.png in Resources */, + 09E7BE2011FC935E00DCCFE7 /* NOISETRACKER.FTA in Resources */, + 09E7BE2111FC935E00DCCFE7 /* noisetracker_0.png in Resources */, + 09E7BE2211FC935E00DCCFE7 /* noisetracker_1.png in Resources */, + 09E7BE2311FC935E00DCCFE7 /* noisetracker_2.png in Resources */, + 09E7BE2411FC935E00DCCFE7 /* noisetracker_3.png in Resources */, + 7E51482B1CA6B5CE005DA0A6 /* Search Skip Search 2.wav in Resources */, + 09E7BE2611FC935E00DCCFE7 /* nucleus.png in Resources */, + 09E7BE2711FC935E00DCCFE7 /* nucleus_2.png in Resources */, + 09E7BE2811FC935E00DCCFE7 /* nucleus_c.png in Resources */, + 09E7BE2911FC935E00DCCFE7 /* nucleus_t.png in Resources */, + 09E7BE2B11FC935E00DCCFE7 /* thumb_floby.png in Resources */, + 09E7BE2C11FC935E00DCCFE7 /* thumb_system6.png in Resources */, + 09E7BE2D11FC935E00DCCFE7 /* thumb_modulae.png in Resources */, + 09E7BE2E11FC935E00DCCFE7 /* thumb_noisetracker.png in Resources */, + 7E5148291CA6B5CE005DA0A6 /* logo_apple2gs.png in Resources */, + 09E7BE2F11FC935E00DCCFE7 /* thumb_nucleus.png in Resources */, + 09E7BE3011FC935E00DCCFE7 /* thumb_xmas.png in Resources */, + 09E7BE3111FC935E00DCCFE7 /* xmas_1.png in Resources */, + 09E7BE3211FC935E00DCCFE7 /* xmas_2.png in Resources */, + 09E7BE3311FC935E00DCCFE7 /* xmas_3.png in Resources */, + 09E7BE3411FC935E00DCCFE7 /* xmas_4.png in Resources */, + 09E7BE3511FC935E00DCCFE7 /* xmas_5.png in Resources */, + 09E7BE3611FC935E00DCCFE7 /* xmas_6.png in Resources */, + 7E5148211CA6B5CE005DA0A6 /* disk.png in Resources */, + 09E7BE3711FC935E00DCCFE7 /* xmas_7.png in Resources */, + 09E7BE3811FC935E00DCCFE7 /* xmas_8.png in Resources */, + 09E7BE3911FC935E00DCCFE7 /* XMASDEMO.FTA in Resources */, + 09BCB6281211649D009858DF /* flobynoid (2002).dsk.zip in Resources */, + 09087F3A12244C0500C52D88 /* delta_1.png in Resources */, + 09087F3B12244C0500C52D88 /* delta_2.png in Resources */, + 09087F3C12244C0500C52D88 /* delta_3.png in Resources */, + 09087F3D12244C0500C52D88 /* delta_4.png in Resources */, + 09087F3E12244C0500C52D88 /* delta_5.png in Resources */, + 09087F3F12244C0500C52D88 /* delta_6.png in Resources */, + 7E5148311CA6B5CE005DA0A6 /* Spin Up Search 2.wav in Resources */, + 09087F4012244C0500C52D88 /* delta_7.png in Resources */, + 09087F4312244C0500C52D88 /* photonix_1.png in Resources */, + 09087F4412244C0500C52D88 /* photonix_2.png in Resources */, + 09087F4612244C0500C52D88 /* thumb_delta.png in Resources */, + 7E51482E1CA6B5CE005DA0A6 /* Search Skip Search 5.wav in Resources */, + 09087F4712244C0500C52D88 /* thumb_gsos.png in Resources */, + 09087F4812244C0500C52D88 /* thumb_photonix.png in Resources */, + 09AB6C11123EE1AE00816DB7 /* bouncinferno_1.png in Resources */, + 7E5148251CA6B5CE005DA0A6 /* disk_525_2.png in Resources */, + 09AB6C12123EE1AE00816DB7 /* bouncinferno_2.png in Resources */, + 09AB6C13123EE1AE00816DB7 /* bouncinferno_3.png in Resources */, + 09AB6C14123EE1AE00816DB7 /* bouncinferno_4.png in Resources */, + 09AB6C15123EE1AE00816DB7 /* bouncinferno_5.png in Resources */, + 09AB6C16123EE1AE00816DB7 /* bouncinferno_6.png in Resources */, + 7E51482A1CA6B5CE005DA0A6 /* Search Skip Search 1.wav in Resources */, + 09AB6C17123EE1AE00816DB7 /* bouncinferno_7.png in Resources */, + 09AB6C19123EE1BA00816DB7 /* harrier1.png in Resources */, + 09AB6C1D123EE1CB00816DB7 /* SPACE_HARRIER.FTA in Resources */, + 09AB6C1E123EE1CB00816DB7 /* thumb_bouncinferno.png in Resources */, + 09AB6C1F123EE1CB00816DB7 /* thumb_harrier.png in Resources */, + 09AB6C25123EE2FA00816DB7 /* Default.png in Resources */, + 7E51482F1CA6B5CE005DA0A6 /* ShastonHi640.ttf in Resources */, + 7E5148301CA6B5CE005DA0A6 /* Spin Up Search 1.wav in Resources */, + 090E7BD6123F965F003EE2C3 /* poms_1.png in Resources */, + 7E51482D1CA6B5CE005DA0A6 /* Search Skip Search 4.wav in Resources */, + 090E7BD7123F965F003EE2C3 /* poms_2.png in Resources */, + 090E7BD8123F965F003EE2C3 /* poms_3.png in Resources */, + 090E7BD9123F965F003EE2C3 /* poms_4.png in Resources */, + 090E7BDA123F965F003EE2C3 /* poms_5.png in Resources */, + 090E7BDB123F965F003EE2C3 /* poms_6.png in Resources */, + 090E7BDE123F966C003EE2C3 /* thumb_poms.png in Resources */, + 0982685E124028E00064F134 /* icon.png in Resources */, + 0982685F124028E00064F134 /* icon@2x.png in Resources */, + 09FA6098125A7B3E00B07F77 /* activegsViewController.xib in Resources */, + 09FA609D125A7B3E00B07F77 /* icon_APPLE 2.png in Resources */, + 09FA609E125A7B3E00B07F77 /* icon_APPLE 2GS.png in Resources */, + 09A5CE76125D422D0018DC22 /* infoViewController.xib in Resources */, + 7E5148261CA6B5CE005DA0A6 /* facebook-logo.png in Resources */, + 099CD905125E6F6E008EFD6C /* detailViewController.xib in Resources */, + 0971D931126E4BE500EEBB1E /* icon72.png in Resources */, + 09FD36F31278CCEB009C31AB /* BLUE_HELMET.FTA in Resources */, + 09FD36F41278CCEB009C31AB /* bluehelmet_1.png in Resources */, + 09FD36F51278CCEB009C31AB /* bluehelmet_2.png in Resources */, + 0902FEC812820467002E7C03 /* Tab2GS.png in Resources */, + 0902FEE712820626002E7C03 /* TabFTA@2x.png in Resources */, + 0902FEEF12820678002E7C03 /* TabFTA.png in Resources */, + 0955429F12836F4D0035AE09 /* Tab2GS@2x.png in Resources */, + 095542A8128375C40035AE09 /* Tab][.png in Resources */, + 095542A9128375C40035AE09 /* Tab][@2x.png in Resources */, + 7E8EED6B1A7D83C900C6E522 /* Entitlements.plist in Resources */, + 09AF98051283F0DF00083D60 /* Oil_Landers.fta in Resources */, + 09AF980C1283F12200083D60 /* StarWizard (2002).fta in Resources */, + 09AF980D1283F12200083D60 /* starwizard_2.png in Resources */, + 09AF980E1283F12200083D60 /* starwizard_3.png in Resources */, + 7E5148271CA6B5CE005DA0A6 /* floppy_eject.wav in Resources */, + 09AF980F1283F12200083D60 /* starwizard_4.png in Resources */, + 09AF98101283F12200083D60 /* starwizard_5.png in Resources */, + 09AF98111283F12200083D60 /* starwizard.png in Resources */, + 7E51482C1CA6B5CE005DA0A6 /* Search Skip Search 3.wav in Resources */, + 09D8BCF91285EFE900B6D785 /* miniprix_1.png in Resources */, + 09D8BCFC1285EFFA00B6D785 /* miniprix_2.png in Resources */, + 09D8BCFD1285EFFA00B6D785 /* miniprix_3.png in Resources */, + 09D8BD031285F00C00B6D785 /* oillanders_1.png in Resources */, + 09D8BD041285F00C00B6D785 /* oillanders_2.png in Resources */, + 09D8BD051285F00C00B6D785 /* oillanders_3.png in Resources */, + 09D8BD061285F00C00B6D785 /* oillanders_4.png in Resources */, + 7E5148281CA6B5CE005DA0A6 /* logo_apple2.png in Resources */, + 09D8BD071285F00C00B6D785 /* oillanders_5.png in Resources */, + 0916BB04129473CE001727AF /* infoViewController-ipad.xib in Resources */, + 090A6077163093D800C8FB59 /* Default-568h@2x.png in Resources */, + 09C81A991657ACDD008539D5 /* 2mg.icns in Resources */, + 7E5148221CA6B5CE005DA0A6 /* disk_35_1.png in Resources */, + 09C81A9A1657ACDD008539D5 /* 525.icns in Resources */, + 0941E66E1670E086003E0411 /* NUCLEUS.FTA in Resources */, + 7E51481F1CA6B5CE005DA0A6 /* ActiveGS.png in Resources */, + 0941E6701670E143003E0411 /* DELTA.FTA in Resources */, + 0941E6721670E23F003E0411 /* PHOTONIX.FTA in Resources */, + 0941E6751670E391003E0411 /* BOUNCIN_FERNO.FTA in Resources */, + 0941E6761670E391003E0411 /* MINIPRIX.FTA in Resources */, + 7E5148241CA6B5CE005DA0A6 /* disk_525_1.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 095981521A3E1A76007C90A8 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "sh ~/Code/ActiveGS/xcodebuild.sh"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589B0D05DD56006BFB54 /* main.mm in Sources */, + 09BB434511D92F65005ADA46 /* ActiveDownloadMac.cpp in Sources */, + 09BB434711D92F65005ADA46 /* CEmulatorCtrlMac.cpp in Sources */, + 09BB43B011D92F70005ADA46 /* activeconfig.cpp in Sources */, + 09BB43B111D92F70005ADA46 /* ActiveDownload.cpp in Sources */, + 09052B9419053C9F00853FAE /* uncompr.cpp in Sources */, + 09BB43B211D92F70005ADA46 /* ActiveZip.cpp in Sources */, + 09052B8619053C9F00853FAE /* pngwtran.cpp in Sources */, + 09052B8B19053C9F00853FAE /* zip.cpp in Sources */, + 09BB43B311D92F70005ADA46 /* CA2Text.cpp in Sources */, + 09BB43B411D92F70005ADA46 /* CEmulatorCtrl.cpp in Sources */, + 09BB43B511D92F70005ADA46 /* interface.cpp in Sources */, + 09BB43B611D92F70005ADA46 /* libpng.cpp in Sources */, + 09BB43B711D92F70005ADA46 /* rom.cpp in Sources */, + 09FA6095125A7B3E00B07F77 /* activegsAppDelegate.mm in Sources */, + 09052B8119053C9F00853FAE /* pngset.cpp in Sources */, + 09FA6096125A7B3E00B07F77 /* activegsList.mm in Sources */, + 09FA6097125A7B3E00B07F77 /* activegsViewController.mm in Sources */, + 09052B8D19053C9F00853FAE /* compress.cpp in Sources */, + 09052B8E19053C9F00853FAE /* crc32.cpp in Sources */, + 09FA609A125A7B3E00B07F77 /* asyncimageview.mm in Sources */, + 09FA609C125A7B3E00B07F77 /* GTMUIView+SubtreeDescription.m in Sources */, + 09052B8F19053C9F00853FAE /* deflate.cpp in Sources */, + 09FA609F125A7B3E00B07F77 /* KBDController.mm in Sources */, + 09AADC78125C560A00654DF1 /* detailViewController.mm in Sources */, + 09A5CE60125D41860018DC22 /* infoViewController.mm in Sources */, + 0972554713CF2232006194F9 /* activegsEmulatorController.mm in Sources */, + 0907BCC9142F567A0051CA0A /* asynccommand.mm in Sources */, + 09052B7D19053C9F00853FAE /* pngread.cpp in Sources */, + 09C81A781657ACAE008539D5 /* adb.cpp in Sources */, + 09C81A791657ACAE008539D5 /* async_event.cpp in Sources */, + 09C81A7A1657ACAE008539D5 /* clock.cpp in Sources */, + 09052B9119053C9F00853FAE /* inflate.cpp in Sources */, + 09C81A7B1657ACAE008539D5 /* compile_time.cpp in Sources */, + 09C81A7C1657ACAE008539D5 /* compression.cpp in Sources */, + 09C81A7D1657ACAE008539D5 /* config_generic.cpp in Sources */, + 09052B8C19053C9F00853FAE /* adler32.cpp in Sources */, + 09C81A7F1657ACAE008539D5 /* dis.cpp in Sources */, + 09C81A801657ACAE008539D5 /* engine_c.cpp in Sources */, + 09C81A811657ACAE008539D5 /* GraphCounter.cpp in Sources */, + 09C81A821657ACAE008539D5 /* iwm.cpp in Sources */, + 09C81A831657ACAE008539D5 /* marinetti.cpp in Sources */, + 09052B9319053C9F00853FAE /* trees.cpp in Sources */, + 09C81A841657ACAE008539D5 /* marinetti_helper.cpp in Sources */, + 09C81A851657ACAE008539D5 /* moremem.cpp in Sources */, + 09C81A861657ACAE008539D5 /* openalasync_snddriver.cpp in Sources */, + 09052B8219053C9F00853FAE /* pngtrans.cpp in Sources */, + 09C81A871657ACAE008539D5 /* paddles.cpp in Sources */, + 09C81A881657ACAE008539D5 /* SaveState.cpp in Sources */, + 09C81A891657ACAE008539D5 /* scc.cpp in Sources */, + 09C81A8A1657ACAE008539D5 /* scc_socket_driver.cpp in Sources */, + 09052B8319053C9F00853FAE /* pngvcrd.cpp in Sources */, + 09C81A8B1657ACAE008539D5 /* sim65816.cpp in Sources */, + 09C81A8C1657ACAE008539D5 /* smartport.cpp in Sources */, + 09052B9019053C9F00853FAE /* inffast.cpp in Sources */, + 09C81A8D1657ACAE008539D5 /* sound.cpp in Sources */, + 09052B7819053C9F00853FAE /* pngerror.cpp in Sources */, + 09052B7B19053C9F00853FAE /* pngmem.cpp in Sources */, + 09C81A8E1657ACAE008539D5 /* sound_driver.cpp in Sources */, + 09052B7719053C9F00853FAE /* png.cpp in Sources */, + 09C81A901657ACAE008539D5 /* video.cpp in Sources */, + 09052B7E19053C9F00853FAE /* pngrio.cpp in Sources */, + 09C81A9B1657ACDD008539D5 /* macdriver_activegs.cpp in Sources */, + 09C81A9C1657ACDD008539D5 /* macdriver_generic.cpp in Sources */, + 09052B8919053C9F00853FAE /* iowin32.cpp in Sources */, + 09C81A9F1657ACDD008539D5 /* scc_macdriver.cpp in Sources */, + 09C81AA71657AD18008539D5 /* emulatorView.mm in Sources */, + 09C81AA81657AD18008539D5 /* joystick_iphone.cpp in Sources */, + 09C81AA91657AD18008539D5 /* zoomEmulatorView.mm in Sources */, + 09052B7F19053C9F00853FAE /* pngrtran.cpp in Sources */, + 09052B7A19053C9F00853FAE /* pngget.cpp in Sources */, + 09052B7919053C9F00853FAE /* pnggccrd.cpp in Sources */, + 09052B9219053C9F00853FAE /* inftrees.cpp in Sources */, + 09052B8819053C9F00853FAE /* ioapi.cpp in Sources */, + 09052B7C19053C9F00853FAE /* pngpread.cpp in Sources */, + 09052B8419053C9F00853FAE /* pngwio.cpp in Sources */, + 09052B8719053C9F00853FAE /* pngwutil.cpp in Sources */, + 09052B8A19053C9F00853FAE /* unzip.cpp in Sources */, + 09052B9519053C9F00853FAE /* zutil.cpp in Sources */, + 09052B8519053C9F00853FAE /* pngwrite.cpp in Sources */, + 09052B8019053C9F00853FAE /* pngrutil.cpp in Sources */, + 0941E6AB16720840003E0411 /* ActiveGSList.cpp in Sources */, + 0941E6AF16720886003E0411 /* simplexml.cpp in Sources */, + 09520D8316AEF8130065E84A /* driver.cpp in Sources */, + 09520D8916AEF8250065E84A /* activegs_driver.cpp in Sources */, + 09520D8E16AEF8650065E84A /* apple2e.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 09A284A112383EE600EA12DF /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_THUMB_SUPPORT = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + }; + name = Distribution; + }; + 09A284A212383EE600EA12DF /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_ENTITLEMENTS = Entitlements.plist; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = activegs_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + USE_RASTER, + ACTIVEGSPLUGIN, + ACTIVEGS, + KEGS91, + KEGS_LITTLE_ENDIAN, + VIDEO_SINGLEVLINE, + DRIVER_IOS, + ); + GCC_THUMB_SUPPORT = NO; + GCC_VERSION = ""; + INFOPLIST_FILE = activegs.plist; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/GraphicsServices.framework\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.freetoolsassociation.activegs; + PRODUCT_NAME = ActiveGS; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Distribution; + }; + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_ENTITLEMENTS = Entitlements.plist; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = activegs_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + USE_RASTER, + _DEBUG, + ACTIVEGSPLUGIN, + ACTIVEGS, + KEGS_LITTLE_ENDIAN, + VIDEO_SINGLEVLINE, + DRIVER_IOS, + ); + GCC_THUMB_SUPPORT = NO; + GCC_VERSION = ""; + INFOPLIST_FILE = activegs.plist; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/GraphicsServices.framework\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.freetoolsassociation.activegs; + PRODUCT_NAME = ActiveGS; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_ENTITLEMENTS = Entitlements.plist; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = activegs_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + USE_RASTER, + ACTIVEGSPLUGIN, + ACTIVEGS, + KEGS_LITTLE_ENDIAN, + VIDEO_SINGLEVLINE, + DRIVER_IOS, + ); + GCC_THUMB_SUPPORT = NO; + GCC_VERSION = ""; + INFOPLIST_FILE = activegs.plist; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/GraphicsServices.framework\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.freetoolsassociation.activegs; + PRODUCT_NAME = ActiveGS; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_THUMB_SUPPORT = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + ONLY_ACTIVE_ARCH = YES; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_THUMB_SUPPORT = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ActiveGS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + 09A284A212383EE600EA12DF /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Distribution; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "activegs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + 09A284A112383EE600EA12DF /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Distribution; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/ActiveGS_iOS/activegs.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ActiveGS_iOS/activegs.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..d25ed1f --- /dev/null +++ b/ActiveGS_iOS/activegs.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ActiveGS_iOS/activegs_Prefix.pch b/ActiveGS_iOS/activegs_Prefix.pch new file mode 100644 index 0000000..6fb9a91 --- /dev/null +++ b/ActiveGS_iOS/activegs_Prefix.pch @@ -0,0 +1,8 @@ +// +// Prefix header for all source files of the 'activegs' target in the 'activegs' project +// + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/ActiveGS_iOS/iTunesArtwork b/ActiveGS_iOS/iTunesArtwork new file mode 100644 index 0000000..b79aa88 Binary files /dev/null and b/ActiveGS_iOS/iTunesArtwork differ diff --git a/ActiveGS_iOS/icon.png b/ActiveGS_iOS/icon.png new file mode 100644 index 0000000..d00eed7 Binary files /dev/null and b/ActiveGS_iOS/icon.png differ diff --git a/ActiveGS_iOS/icon72.png b/ActiveGS_iOS/icon72.png new file mode 100644 index 0000000..a0a0d21 Binary files /dev/null and b/ActiveGS_iOS/icon72.png differ diff --git a/ActiveGS_iOS/icon@2x.png b/ActiveGS_iOS/icon@2x.png new file mode 100644 index 0000000..ee861ff Binary files /dev/null and b/ActiveGS_iOS/icon@2x.png differ diff --git a/ActiveGS_iOS/icon_APPLE 2.png b/ActiveGS_iOS/icon_APPLE 2.png new file mode 100644 index 0000000..b940348 Binary files /dev/null and b/ActiveGS_iOS/icon_APPLE 2.png differ diff --git a/ActiveGS_iOS/icon_APPLE 2GS.png b/ActiveGS_iOS/icon_APPLE 2GS.png new file mode 100644 index 0000000..d1469d4 Binary files /dev/null and b/ActiveGS_iOS/icon_APPLE 2GS.png differ diff --git a/ActiveGS_iOS/icone72.png b/ActiveGS_iOS/icone72.png new file mode 100644 index 0000000..a0a0d21 Binary files /dev/null and b/ActiveGS_iOS/icone72.png differ diff --git a/ActiveGS_iOS/infoViewController-ipad.xib b/ActiveGS_iOS/infoViewController-ipad.xib new file mode 100644 index 0000000..9b83ab1 --- /dev/null +++ b/ActiveGS_iOS/infoViewController-ipad.xib @@ -0,0 +1,923 @@ + + + + 1552 + 13F34 + 6254 + 1265.21 + 698.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 6247 + + + IBProxyObject + IBUIButton + IBUIImageView + IBUILabel + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + + + 293 + {{344, 336}, {80, 77}} + + + + NO + YES + 4 + YES + IBCocoaTouchFramework + + NSImage + ActiveGS.png + + + + + 269 + {{333, 727}, {101, 37}} + + + + NO + IBCocoaTouchFramework + 0 + 0 + 1 + + 1 + MC4xOTYwNzg0MzE0IDAuMzA5ODAzOTIxNiAwLjUyMTU2ODYyNzUAA + + + 3 + MQA + + I'm Happy! + + 3 + MC41AA + + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + + + + + 293 + {{224, 297}, {320, 44}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + ActiveGS + + 1 + MCAwIDAAA + darkTextColor + + + + {2, 2} + 1 + 10 + 1 + + Helvetica-Bold + Helvetica + 2 + 36 + + + Helvetica-Bold + 36 + 16 + + YES + + + + 293 + {{270, 416}, {228, 25}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (version) + + + 1 + 10 + 1 + + 1 + 17 + + + HelveticaNeue + 17 + 16 + + YES + + + + 269 + {{274, 789}, {219, 30}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + For support and/or feedback, please visit + + + 1 + 10 + 3 + 1 + + Helvetica + Helvetica + 0 + 12 + + + Helvetica + 12 + 16 + + 219 + + + + 317 + {{244, 533}, {280, 132}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + c3dpcGUgZG93biBmb3IgcnVuLXRpbWUgbWVudQpzd2lwZSB1cCBmb3Iga2V5Ym9hcmQKc3dpcGUgdXAg +Zm9yIGpveXBhZCAod2hpbGUga2V5Ym9hcmQgaXMgc2hvd24pCmRvdWJsZSB0YXAgZm9yIG1vdXNlIGNs +aWNrCnRyaXBsZSB0YXAgZm9yIG1vdXNlIGRvdWJsZS1jbGljawpzd2lwZSBsZWZ0L3JpZ2h0IG9uIHRv +cCBzY3JlZW4gZm9yIHNob3J0Y3V0IHRvIGJyb3dzZQo + + + {0, 0} + 1 + 4 + 0 + 1 + 2 + + + 280 + + + + 317 + {{303, 506}, {162, 57}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + Commands: + + + 1 + 10 + 3 + 1 + + Helvetica-Bold + Helvetica + 2 + 17 + + + Helvetica-Bold + 17 + 16 + + 162 + + + + 269 + {{368, 819}, {32, 32}} + + + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + Facebook + + + NSImage + facebook-logo.png + + + + + + + 269 + {{233, 876}, {311, 30}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (Dedicated to Benzebut, ActiveGS chief bug hunter!) + + + 1 + 3 + 1 + + + 311 + + + {768, 1024} + + + + + 3 + MQA + + 2 + + + + IBUISimulatedFreeformSizeMetricsSentinel + Freeform + + IBCocoaTouchFramework + + + + 274 + + + + 293 + {{472, 237}, {80, 77}} + + NO + YES + 4 + YES + IBCocoaTouchFramework + + + + + 265 + {{461, 544}, {101, 37}} + + NO + IBCocoaTouchFramework + 0 + 0 + 1 + + + I'm Happy! + + + + + + + 293 + {{379, 191}, {265, 38}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + ActiveGS + + + + {2, 2} + 1 + 10 + 1 + + + YES + + + + 293 + {{397, 322}, {228, 25}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + (version) + + + 1 + 10 + 1 + + + YES + + + + 268 + {{406, 598}, {219, 30}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + For support and/or feedback, please visit + + + 1 + 10 + 3 + 1 + + + 219 + + + + 317 + {{371, 389}, {280, 134}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + c3dpcGUgZG93biBmb3IgcnVuLXRpbWUgbWVudQpzd2lwZSB1cCBmb3Iga2V5Ym9hcmQKc3dpcGUgdXAg +Zm9yIGpveXBhZCAod2hpbGUga2V5Ym9hcmQgaXMgc2hvd24pCmRvdWJsZSB0YXAgZm9yIG1vdXNlIGNs +aWNrCnRyaXBsZSB0YXAgZm9yIG1vdXNlIGRvdWJsZS1jbGljawpzd2lwZSBsZWZ0L3JpZ2h0IG9uIHRv +cCBzY3JlZW4gZm9yIHNob3J0Y3V0IHRvIGJyb3dzZQo + + + {0, 0} + 1 + 4 + 0 + 1 + 2 + + + 280 + + + + 317 + {{431, 389}, {162, 17}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Commands: + + + 1 + 10 + 3 + 1 + + + 162 + + + + 269 + {{495, 628}, {32, 32}} + + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + Facebook + + + + + + + + 269 + {{353, 676}, {317, 30}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + (Dedicated to Benzebut, ActiveGS chief bug hunter!) + + + 1 + 3 + 1 + + + 317 + + + {1024, 768} + + 3 + MQA + + + + 3 + 3 + + + IBCocoaTouchFramework + + + + + + + view + + + + 3 + + + + versionUI + + + + 12 + + + + landscapeView + + + + 33 + + + + portraitView + + + + 34 + + + + versionUILandscape + + + + 35 + + + + doneButton: + + + 7 + + 9 + + + + doneButton: + + + 7 + + 31 + + + + emailButton: + + + 1 + + 42 + + + + emailButton: + + + 1 + + 45 + + + + + + 0 + + + + + + 1 + + + + + + + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + 5 + + + + + 10 + + + + + 11 + + + + + 13 + + + + + 23 + + + + + + + + + + + + + + ViewLandscape + + + 24 + + + + + 25 + + + + + 27 + + + + + 28 + + + + + 29 + + + + + 36 + + + + + 37 + + + + + 38 + + + + + 39 + + + + + 40 + + + + + 41 + + + + + 43 + + + + + 44 + + + + + + + infoViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 45 + + + + + infoViewController + UIVIEWCONTROLLERROOT + + id + id + id + + + + doneButton: + id + + + emailButton: + id + + + parametersButton: + id + + + + UIView + UIView + UILabel + UILabel + + + + landscapeView + UIView + + + portraitView + UIView + + + versionUI + UILabel + + + versionUILandscape + UILabel + + + + IBProjectSource + ../../Common.iphone/infoViewController.h + + + + infoViewController + + id + id + id + + + + doneButton: + id + + + emailButton: + id + + + parametersButton: + id + + + + IBProjectSource + ../../Common.iphone/infoViewController.mm + + + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UIGestureRecognizer + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIGestureRecognizer.h + + + + UIImageView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIImageView.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UIResponder + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + + 0 + IBCocoaTouchFramework + NO + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + + {80, 80} + {128, 128} + + + diff --git a/ActiveGS_iOS/infoViewController.xib b/ActiveGS_iOS/infoViewController.xib new file mode 100644 index 0000000..1950059 --- /dev/null +++ b/ActiveGS_iOS/infoViewController.xib @@ -0,0 +1,931 @@ + + + + 1552 + 13F34 + 6254 + 1265.21 + 698.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 6247 + + + IBProxyObject + IBUIButton + IBUIImageView + IBUILabel + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + + + 293 + {{120, 59}, {80, 77}} + + + + NO + YES + 4 + YES + IBCocoaTouchFramework + + NSImage + ActiveGS.png + + + + + 269 + {{109, 339}, {101, 37}} + + + + NO + IBCocoaTouchFramework + 0 + 0 + 1 + + 1 + MC4xOTYwNzg0MzE0IDAuMzA5ODAzOTIxNiAwLjUyMTU2ODYyNzUAA + + + 3 + MQA + + I'm Happy! + + 3 + MC41AA + + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + + + + + 293 + {{0, 20}, {320, 43}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + ActiveGS + + 1 + MCAwIDAAA + darkTextColor + + + + {2, 2} + 1 + 10 + 1 + + Helvetica-Bold + Helvetica + 2 + 36 + + + Helvetica-Bold + 36 + 16 + + YES + + + + 293 + {{46, 139}, {228, 25}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (version) + + + 1 + 10 + 1 + + 1 + 17 + + + HelveticaNeue + 17 + 16 + + YES + + + + 269 + {{76, 392}, {180, 30}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + For support and/or feedback, visit + + + 1 + 10 + 3 + 1 + + Helvetica + Helvetica + 0 + 12 + + + Helvetica + 12 + 16 + + 180 + + + + 317 + {{23, 191}, {280, 134}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + c3dpcGUgZG93biBmb3IgcnVuLXRpbWUgbWVudQpzd2lwZSB1cCBmb3Iga2V5Ym9hcmQKc3dpcGUgdXAg +Zm9yIGpveXBhZCAod2hpbGUga2V5Ym9hcmQgaXMgc2hvd24pCmRvdWJsZSB0YXAgZm9yIG1vdXNlIGNs +aWNrCnRyaXBsZSB0YXAgZm9yIG1vdXNlIGRvdWJsZS1jbGljawpzd2lwZSBsZWZ0L3JpZ2h0IG9uIHRv +cCBzY3JlZW4gZm9yIHNob3J0Y3V0IHRvIGJyb3dzZQo + + + {0, 0} + 1 + 4 + 0 + 1 + 2 + + + 280 + + + + 317 + {{79, 186}, {162, 17}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + Commands: + + + 1 + 10 + 3 + 1 + + Helvetica-Bold + Helvetica + 2 + 17 + + + Helvetica-Bold + 17 + 16 + + 162 + + + + 269 + {{143, 417}, {32, 32}} + + + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + Facebook + + + NSImage + facebook-logo.png + + + + + + + 269 + {{15, 444}, {290, 30}} + + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (Dedicated to Benzebut, ActiveGS chief bug hunter!) + + + 1 + 3 + 1 + + + 290 + + + {320, 480} + + + + + 3 + MQA + + 2 + + + + IBUISimulatedFreeformSizeMetricsSentinel + Freeform + + IBCocoaTouchFramework + + + + 274 + + + + 293 + {{120, 20}, {80, 77}} + + + NO + YES + 4 + YES + IBCocoaTouchFramework + + + + + 265 + {{359, 256}, {101, 37}} + + NO + IBCocoaTouchFramework + 0 + 0 + 1 + + + I'm Happy! + + + + + + + 293 + {{208, 52}, {265, 38}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + ActiveGS + + + + {2, 2} + 1 + 10 + + + YES + + + + 293 + {{126, 93}, {228, 25}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (version) + + + 1 + 10 + 1 + + + YES + + + + 268 + {{20, 261}, {180, 30}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + For support and/or feedback, visit + + + 1 + 10 + 3 + 1 + + + 180 + + + + 317 + {{100, 131}, {280, 134}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + c3dpcGUgZG93biBmb3IgcnVuLXRpbWUgbWVudQpzd2lwZSB1cCBmb3Iga2V5Ym9hcmQKc3dpcGUgdXAg +Zm9yIGpveXBhZCAod2hpbGUga2V5Ym9hcmQgaXMgc2hvd24pCmRvdWJsZSB0YXAgZm9yIG1vdXNlIGNs +aWNrCnRyaXBsZSB0YXAgZm9yIG1vdXNlIGRvdWJsZS1jbGljawpzd2lwZSBsZWZ0L3JpZ2h0IG9uIHRv +cCBzY3JlZW4gZm9yIHNob3J0Y3V0IHRvIGJyb3dzZQo + + + {0, 0} + 1 + 4 + 0 + 1 + 2 + + + 280 + + + + 317 + {{159, 131}, {162, 17}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + Commands: + + + 1 + 10 + 3 + 1 + + + 162 + + + + 269 + {{213, 259}, {32, 32}} + + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + Facebook + + + + + + + + 269 + {{93, 290}, {294, 30}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (Dedicated to Benzebut, ActiveGS chief bug hunter!) + + + 1 + 3 + 1 + + + 294 + + + {480, 320} + + + 3 + MQA + + + + 3 + 3 + + + IBCocoaTouchFramework + + + + + + + view + + + + 3 + + + + versionUI + + + + 12 + + + + landscapeView + + + + 33 + + + + portraitView + + + + 34 + + + + versionUILandscape + + + + 35 + + + + doneButton: + + + 7 + + 9 + + + + doneButton: + + + 7 + + 31 + + + + emailButton: + + + 1 + + 50 + + + + emailButton: + + + 1 + + 51 + + + + + + 0 + + + + + + 1 + + + + + + + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + 5 + + + + + 10 + + + + + 11 + + + + + 13 + + + + + 23 + + + + + + + + + + + + + + ViewLandscape + + + 24 + + + + + 25 + + + + + 27 + + + + + 28 + + + + + 29 + + + + + 36 + + + + + 37 + + + + + 38 + + + + + 39 + + + + + 44 + + + + + 45 + + + + + 47 + + + + + 48 + + + + + + + infoViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 51 + + + + + infoViewController + UIVIEWCONTROLLERROOT + + id + id + id + + + + doneButton: + id + + + emailButton: + id + + + parametersButton: + id + + + + UIView + UIView + UILabel + UILabel + + + + landscapeView + UIView + + + portraitView + UIView + + + versionUI + UILabel + + + versionUILandscape + UILabel + + + + IBProjectSource + ../../Common.iphone/infoViewController.h + + + + infoViewController + + id + id + id + + + + doneButton: + id + + + emailButton: + id + + + parametersButton: + id + + + + IBProjectSource + ../../Common.iphone/infoViewController.mm + + + + + + UIButton + UIControl + + IBFrameworkSource + UIKit.framework/Headers/UIButton.h + + + + UIControl + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIControl.h + + + + UIGestureRecognizer + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIGestureRecognizer.h + + + + UIImageView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIImageView.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UIResponder + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + + 0 + IBCocoaTouchFramework + NO + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + + {80, 80} + {128, 128} + + + diff --git a/ActiveGS_iOS/main.mm b/ActiveGS_iOS/main.mm new file mode 100644 index 0000000..5d42a70 --- /dev/null +++ b/ActiveGS_iOS/main.mm @@ -0,0 +1,17 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#import "activegsAppDelegate.h" + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + // int retVal = UIApplicationMain(argc, argv, nil, nil); + int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([activegsAppDelegate class])); + [pool release]; + return retVal; +} diff --git a/ActiveGS_iOS/mainViewController.xib b/ActiveGS_iOS/mainViewController.xib new file mode 100644 index 0000000..39131e6 --- /dev/null +++ b/ActiveGS_iOS/mainViewController.xib @@ -0,0 +1,893 @@ + + + + 1056 + 10F569 + 823 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 132 + + + YES + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 293 + {{120, 59}, {80, 77}} + + NO + YES + 4 + YES + IBCocoaTouchFramework + + NSImage + ActiveGS.png + + + + + 269 + {{112, 392}, {96, 37}} + + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Bold + 15 + 16 + + 1 + I'm Happy + + 3 + MQA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MC41AA + + + + + 293 + {{0, 20}, {320, 43}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + ActiveGS + + Helvetica-Bold + 36 + 16 + + + 1 + MCAwIDAAA + + + + {2, 2} + 1 + 10 + 1 + + + + 293 + {{46, 139}, {228, 25}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + (version) + + + 1 + 10 + 1 + + + + 269 + {{88, 425}, {150, 30}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Please, send feedback to + + Helvetica + 12 + 16 + + + + 1 + 10 + 3 + 1 + + + + 269 + {{73, 452}, {180, 18}} + + + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Oblique + 10 + 16 + + 1 + activegs@freetoolsassociation.com + + + 1 + MC4xOTYwNzg0MzE0IDAuMzA5ODAzOTIxNiAwLjUyMTU2ODYyNzUAA + + + + + + 317 + {{23, 208}, {280, 134}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + c3dpcGUgZG93biBmb3IgcnVuLXRpbWUgbWVudQpzd2lwZSB1cCBmb3Iga2V5Ym9hcmQKc3dpcGUgdXAg +Zm9yIGpveXBhZCAod2hpbGUga2V5Ym9hcmQgaXMgc2hvd24pCmRvdWJsZSB0YXAgZm9yIG1vdXNlIGNs +aWNrCnRyaXBsZSB0YXAgZm9yIG1vdXNlIGRvdWJsZS1jbGljawpzd2lwZSBsZWZ0L3JpZ2h0IG9uIHRv +cCBzY3JlZW4gZm9yIHNob3J0Y3V0IHRvIGJyb3dzZQo + + + + {0, 0} + 1 + 4 + 0 + 1 + 2 + + + + 317 + {{79, 203}, {162, 17}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Commands: + + Helvetica-Bold + 17 + 16 + + + + 1 + 10 + 3 + 1 + + + {320, 480} + + 3 + MQA + + 2 + + + IBCocoaTouchFramework + + + + 274 + + YES + + + 293 + {{120, 20}, {80, 77}} + + + NO + YES + 4 + YES + IBCocoaTouchFramework + + + + + 265 + {{364, 263}, {96, 37}} + + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + I'm Happy + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + 293 + {{208, 52}, {265, 38}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + ActiveGS + + + + + {2, 2} + 1 + 10 + + + + 293 + {{126, 93}, {228, 25}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + (version) + + + 1 + 10 + 1 + + + + 268 + {{35, 255}, {150, 30}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + Please, send feedback to + + + + 1 + 10 + 3 + 1 + + + + 268 + {{20, 282}, {180, 18}} + + + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + activegs@freetoolsassociation.com + + + 1 + MC4xOTYwNzg0MzE0IDAuMzA5ODAzOTIxNiAwLjUyMTU2ODYyNzUAA + + + + + + 317 + {{100, 131}, {280, 134}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + c3dpcGUgZG93biBmb3IgcnVuLXRpbWUgbWVudQpzd2lwZSB1cCBmb3Iga2V5Ym9hcmQKc3dpcGUgdXAg +Zm9yIGpveXBhZCAod2hpbGUga2V5Ym9hcmQgaXMgc2hvd24pCmRvdWJsZSB0YXAgZm9yIG1vdXNlIGNs +aWNrCnRyaXBsZSB0YXAgZm9yIG1vdXNlIGRvdWJsZS1jbGljawpzd2lwZSBsZWZ0L3JpZ2h0IG9uIHRv +cCBzY3JlZW4gZm9yIHNob3J0Y3V0IHRvIGJyb3dzZQo + + + + {0, 0} + 1 + 4 + 0 + 1 + 2 + + + + 317 + {{159, 131}, {162, 17}} + + + NO + YES + 7 + NO + IBCocoaTouchFramework + Commands: + + + + 1 + 10 + 3 + 1 + + + {480, 320} + + + + 3 + MQA + + + + 3 + + IBCocoaTouchFramework + + + + + YES + + + view + + + + 3 + + + + doneButton: + + + 7 + + 9 + + + + versionUI + + + + 12 + + + + emailButton: + + + 7 + + 22 + + + + doneButton: + + + 7 + + 31 + + + + emailButton: + + + 7 + + 32 + + + + landscapeView + + + + 33 + + + + portraitView + + + + 34 + + + + versionUILandscape + + + + 35 + + + + + YES + + 0 + + + + + + 1 + + + YES + + + + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + 5 + + + + + 10 + + + + + 11 + + + + + 13 + + + + + 21 + + + + + 23 + + + YES + + + + + + + + + + + ViewLandscape + + + 24 + + + + + 25 + + + + + 27 + + + + + 28 + + + + + 29 + + + + + 30 + + + + + 36 + + + + + 37 + + + + + 38 + + + + + 39 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 1.IBViewBoundsToFrameTransform + 10.IBPluginDependency + 11.IBPluginDependency + 11.IBViewBoundsToFrameTransform + 13.IBPluginDependency + 21.IBPluginDependency + 23.IBEditorWindowLastContentRect + 23.IBPluginDependency + 23.IBViewBoundsToFrameTransform + 24.IBPluginDependency + 24.IBViewBoundsToFrameTransform + 25.IBPluginDependency + 25.IBViewBoundsToFrameTransform + 27.IBPluginDependency + 27.IBViewBoundsToFrameTransform + 28.IBPluginDependency + 28.IBViewBoundsToFrameTransform + 29.IBViewBoundsToFrameTransform + 30.IBPluginDependency + 30.IBViewBoundsToFrameTransform + 36.IBPluginDependency + 36.IBViewBoundsToFrameTransform + 37.IBPluginDependency + 37.IBViewBoundsToFrameTransform + 38.IBPluginDependency + 38.IBViewBoundsToFrameTransform + 39.IBPluginDependency + 39.IBViewBoundsToFrameTransform + 4.IBViewBoundsToFrameTransform + 5.IBPluginDependency + + + YES + infoViewController + UIResponder + {{403, 267}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAAAAAAAAw+8AAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCOAAAww4AAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{549, 358}, {480, 320}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAAAAAAAAw+8AAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABC/AAAwtQAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDuYAAw5UAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDHgAAwrAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCDAAAw42AAA + + + P4AAAL+AAABDSAAAwpYAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDHAAAw5oAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAADCaAAAwykAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAADClgAAw3AAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAADBwAAAwwQAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAADCGAAAwrgAAA + + + P4AAAL+AAABC8AAAwvAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 39 + + + + YES + + UIView + + IBProjectSource + ../Common.iphone/GTMUIView+SubtreeDescription.h + + + + infoViewController + UIViewController + + YES + + YES + doneButton: + emailButton: + + + YES + id + id + + + + YES + + YES + doneButton: + emailButton: + + + YES + + doneButton: + id + + + emailButton: + id + + + + + YES + + YES + landscapeView + portraitView + versionUI + versionUILandscape + + + YES + UIView + UIView + UILabel + UILabel + + + + YES + + YES + landscapeView + portraitView + versionUI + versionUILandscape + + + YES + + landscapeView + UIView + + + portraitView + UIView + + + versionUI + UILabel + + + versionUILandscape + UILabel + + + + + IBProjectSource + ../Common.iphone/infoViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + activegs.xcodeproj + 3 + + ActiveGS.png + {80, 80} + + 132 + + diff --git a/Common.iphone/ActiveGSZoomEmulatorView.h b/Common.iphone/ActiveGSZoomEmulatorView.h new file mode 100644 index 0000000..67c3bd7 --- /dev/null +++ b/Common.iphone/ActiveGSZoomEmulatorView.h @@ -0,0 +1,61 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#import "emulatorView.h" + + struct orientationVar +{ + float scale; + CGPoint p; +} ; + +typedef struct orientationVar orientationVar; + +@interface zoomEmulatorView : UIScrollView +{ + + float dpiRatio; + CGSize viewSize; + + CGPoint initialPoint; + double initialTimer; + int mouseDown; + int zoomDisabled; + orientationVar orientationVars[4]; + + float kbdScale; + + UIPanGestureRecognizer* panGR; + UIPinchGestureRecognizer* pinchGR; + CGPoint lastMousePos; + BOOL allowInput; + BOOL startNewPhase; +@public + UIImageView* _crt ; + emulatorView * _ew ; + UITouch* _useTouch; + UITouch* _secondTouch; + int curOrientation; +} +@property (retain,nonatomic) emulatorView* ew ; +@property (retain,nonatomic) UIImageView* crt ; +@property (retain,nonatomic) UITouch* useTouch ; +@property (retain,nonatomic) UITouch* secondTouch ; + +-(void)updateFrame:(CGRect)frame kbdRect:(CGRect)kbdRect; +-(void)updateScreen:(CGRect)frame ratio:(float)ratio; +- (void)switchOrientation:(int)orientation; +-(void)disableZoom; +-(void)enableZoom; +-(void)enableInput; +-(void)disableInput; +-(void)mouseUp; +-(void)mouseDown; +-(void)setRatioToOne; +-(CGPoint)rotateTouch:(UITouch*) _touch; +- (id)initWithFrame:(CGRect)frame ratio:(float)ratio; +@end diff --git a/Common.iphone/ActiveGSZoomEmulatorView.mm b/Common.iphone/ActiveGSZoomEmulatorView.mm new file mode 100644 index 0000000..b4f195a --- /dev/null +++ b/Common.iphone/ActiveGSZoomEmulatorView.mm @@ -0,0 +1,870 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Src/defc.h" +#include "../Src/sim65816.h" +#include "../Src/adb.h" +#import "zoomEmulatorView.h" +/* +#import "../../common.iphone/activegsAppDelegate.h" +#endif +*/ + + + +#if defined(VIDEO_DOUBLEVLINE) +# define HEIGHT_MULTIPLY 1 +#else +# define HEIGHT_MULTIPLY 2 +#endif + +#undef debug_printf +#define debug_printf(...) +//#define debug_printf printf +//#define SHOW_COLOR + +@implementation zoomEmulatorView +@synthesize ew = _ew; +@synthesize crt = _crt; +@synthesize useTouch = _useTouch; +@synthesize secondTouch = _secondTouch; + +- (id)initWithFrame:(CGRect)frame ratio:(float)ratio +{ + + if (self = [super initWithFrame:frame]) + { + + self->dpiRatio = ratio; + self->viewSize = frame.size; + + debug_printf("ratio:%f width:%f height:%f",self->dpiRatio,self->viewSize.width,self->viewSize.height); + + CGRect r = CGRectMake(0.0,0.0,X_A2_WINDOW_WIDTH/self->dpiRatio ,X_A2_WINDOW_HEIGHT/self->dpiRatio ); + + self.contentSize = CGSizeMake(r.size.width,r.size.height); + + self.ew = [[[emulatorView alloc] initWithFrame:r] autorelease]; + [self.ew setUserInteractionEnabled:TRUE]; + + CGColorSpaceRef innerColorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef icontext = CGBitmapContextCreate(nil, X_A2_WINDOW_WIDTH,X_A2_WINDOW_HEIGHT*2, 8, X_A2_WINDOW_WIDTH*4,innerColorSpace,kCGImageAlphaPremultipliedLast); + + CGContextSetRGBFillColor(icontext,0,0,0,0.0); // transparent + CGContextFillRect(icontext,CGRectMake(0,0,X_A2_WINDOW_WIDTH,X_A2_WINDOW_HEIGHT*2)); + for(int h=0;hviewSize = frame.size; + self->dpiRatio = ratio; + + CGRect r = CGRectMake(0.0,0.0,X_A2_WINDOW_WIDTH/self->dpiRatio ,X_A2_WINDOW_HEIGHT/self->dpiRatio ); + + self.contentSize = CGSizeMake(r.size.width,r.size.height); + [self.ew setFrame:r]; + + [self.crt setFrame:CGRectMake(0,0,r.size.width,r.size.height)]; + [self.crt setBounds:CGRectMake(0,0,r.size.width,r.size.height*2)]; + + [self setRatioToOne]; +} + +-(void)updateFrame:(CGRect)frame kbdRect:(CGRect)kbdRect +{ + + // adapte la vue pour que le clavier ne cache pas l'écran + CGRect scrollSize = self.bounds ; + + + float ref = kbdRect.size.height; + + if ( (-scrollSize.origin.y) < ref) + { + // centre par rapport à la hauteur restante + float hremaining = frame.size.height - ref; + frame.origin.y = - kbdRect.size.height- ( hremaining - scrollSize.size.height*HEIGHT_MULTIPLY ) /2 ; + // TODO : ajuster le zoom! + } + + // NSLog(@"Frame %f,%f %f,%f",frame.origin.x,frame.origin.y,frame.size.width,frame.size.height); + + [self setFrame:frame]; +} + + + + +-(void)setRatioToOne +{ + + int w = (int)viewSize.width; + int h = (int)viewSize.height; + + debug_printf("apprect %d x %d\n",w,h); + +#define ZOOM_CLAMP 0.25 // calcul un zoom par multiple *.25 + + + for(int i=0;i<4;i++) + { + if (!(i&1)) + { + + + + // prend le plus petit des zooms possible + + float r = w*dpiRatio / A2_WINDOW_WIDTH; + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + int ir = (int)r; + float zoomw = (float)ir*ZOOM_CLAMP; + + r = h*dpiRatio / (A2_WINDOW_HEIGHT*HEIGHT_MULTIPLY); + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + ir = (int)r; + float zoomh = (float)ir*ZOOM_CLAMP; + + float zoom = zoomh < zoomw ? zoomh : zoomw ; + + orientationVars[i].scale = zoom; + + + float realew =(X_A2_WINDOW_WIDTH - A2_WINDOW_WIDTH)*zoom; + float realw = w*dpiRatio; + float posw = realw - A2_WINDOW_WIDTH*zoom; + float x = (posw - realew)/2; // pour centrer + + + float realeh =(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT)*HEIGHT_MULTIPLY*zoom; + float realh = h*dpiRatio; + float posh = realh - A2_WINDOW_HEIGHT*HEIGHT_MULTIPLY*zoom; + float y = (posh - realeh)/2; // pour centrer + + orientationVars[i].p = CGPointMake(-x/dpiRatio,-y/dpiRatio/HEIGHT_MULTIPLY); + + + } + else + { + + + float r = h*dpiRatio / A2_WINDOW_WIDTH; + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + int ir = (int)r; + float zoomw = (float)ir*ZOOM_CLAMP; + + r = w*dpiRatio / ( A2_WINDOW_HEIGHT * HEIGHT_MULTIPLY ); + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + ir = (int)r; + float zoomh = (float)ir*ZOOM_CLAMP; + + float zoom = zoomh < zoomw ? zoomh : zoomw ; + + float realew =(X_A2_WINDOW_WIDTH - A2_WINDOW_WIDTH)*zoom; + float realw = h*dpiRatio; + float posw = realw - A2_WINDOW_WIDTH*zoom; + float x = (posw - realew)/2; + + + float realeh =(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT)*HEIGHT_MULTIPLY*zoom; + float realh = w*dpiRatio; + float posh = realh - A2_WINDOW_HEIGHT*HEIGHT_MULTIPLY*zoom; + float y = (posh - realeh)/2; // pour centrer + + orientationVars[i].scale = zoom; + orientationVars[i].p = CGPointMake(-x/dpiRatio,-y/dpiRatio/2); + + + } + + debug_printf("orientation:%d = %f , p = %f,%f\n",i, orientationVars[i].scale,orientationVars[i].p.x,orientationVars[i].p.y); + + } + + mouseDown = 0; + allowInput = TRUE; + zoomDisabled = FALSE; + refScalePortrait = orientationVars[0].scale; + refScaleLandscape = orientationVars[1].scale; + + +} + + +- (void)switchOrientation:(int)orientation +{ + + curOrientation = -1; + float s = orientationVars[orientation].scale; + CGPoint p = orientationVars[orientation].p; + debug_printf("**** about to switchOrientation: (%d) scale:%f offset %f,%f\n",orientation,s,p.x,p.y); + + self.zoomScale = s ; + [self setContentOffset:p]; + curOrientation = orientation; + + s = orientationVars[orientation].scale; + p = orientationVars[orientation].p; + debug_printf("**** done switching (%d) scale:%f offset %f,%f\n",orientation,s,p.x,p.y); + + inCran = false; + + if (orientation & 1) + refScale = refScaleLandscape; + else + refScale = refScalePortrait; + +} + +-(void)setContentOffset:(CGPoint)p /*animated:(BOOL)animated*/ +{ + if (p.x == 0.0f || p.y == 0.0) + { + debug_printf("ignoring %f,%f\n",p.x,p.y); + return ; + } + // appelé par [super initWithFrame:frame] alors que ew n'est pas encore initialisé + if(self.ew != nil ) + { + + CGSize vs = self.ew.frame.size; + CGSize scrollSize = self.bounds.size; + + static float realScale=0.0f; + + + if (!inCran) + { + if ( fabs(self.zoomScale - refScale) < 0.05 ) + { + inCran = true; + realScale = self.zoomScale; + self.zoomScale = refScale; + } + } + else + { + realScale += self.zoomScale - refScale; + if (fabs(realScale - refScale) > 0.10 ) + { + // à faire avant le sef.zoomScale= sinon on tombe dans une boucle infinie! + inCran = false; + self.zoomScale = realScale; + } + else + self.zoomScale = refScale; + } + + + // recentre la fenetre si elle tient totalement en hauteur ou en largeur + + + if (scrollSize.width >= vs.width || inCran ) + p.x = - (scrollSize.width - abs(vs.width)) / 2.0; + if (scrollSize.height >= vs.height || inCran ) + p.y = - (scrollSize.height - abs(vs.height)) / 2.0; + + + if (curOrientation!=-1) + { + debug_printf("saving scale (%d) %f %f,%f\n",curOrientation,self.zoomScale,p.x,p.y); + orientationVars[curOrientation].scale = self.zoomScale ; // / kbdScale; + orientationVars[curOrientation].p = p; + } + + + } + debug_printf("********** offset : %f %f\n",p.x,p.y); + [super setContentOffset:p]; +} + + + +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView +{ + return self.ew; + } + +- (void)drawRect:(CGRect)rect { + + // Drawing code + CGContextRef g = UIGraphicsGetCurrentContext(); + + //fill background with blue +#ifdef SHOW_COLOR + CGContextSetFillColorWithColor(g, [UIColor blueColor].CGColor); +#else + CGContextSetFillColorWithColor(g, [UIColor blackColor].CGColor); +#endif + + CGContextFillRect(g, rect); + + +} + + +-(CGPoint)rotateTouch:(UITouch*) _touch +{ + CGPoint pt; +// float scale = [pManager dpiRatio]/self.zoomScale; + float scale = self->dpiRatio/self.zoomScale; + + if (g_adb.g_warp_pointer==WARP_TOUCHSCREEN) + { + pt = [_touch locationInView:self.ew]; + pt.x *= self->dpiRatio; //[pManager dpiRatio]; + pt.y *= self->dpiRatio; //[pManager dpiRatio]; + + pt.y = (X_A2_WINDOW_HEIGHT - pt.y); + pt.y *=2; + pt.x -= BASE_MARGIN_LEFT; + pt.y -= BASE_MARGIN_TOP*2; + + return pt; + } + + + pt = [_touch locationInView:self]; + int height = self.contentSize.height; + + if (r_sim65816.is_emulator_in_640mode()) + { + // current scale for 640 mode + } + else + { + // otherwise reduce the speed of the mouse + scale /= 2; + } + + pt.y = (height - pt.y)*scale; + pt.x *= scale; + + return pt; + +} + + +-(BOOL)touchesShouldCancelInContentView:(UIView *)view +{ + debug_printf("touchesShouldCancelInContentView\n"); + return !zoomDisabled; +} + +-(void)enableInput +{ + allowInput = TRUE; +} + +-(void)disableInput +{ + allowInput = FALSE; + if (self.useTouch) + self.useTouch = nil; + + if (self.secondTouch) + { + self.secondTouch = nil; + printf("*** secondtouch set in disableinput --- should never appear"); + } +} + + +-(void)disableZoom +{ + + debug_printf("disableZoom\n"); + + // BUG!!!! + // Sometimes, offset is being reset when gestures are disabled! + // Workaround = save the former offset and restore it afterwards + CGPoint offset = self.contentOffset; + + pinchGR.enabled = FALSE; + panGR.enabled = FALSE; + self.scrollEnabled = FALSE; + zoomDisabled= TRUE; + + // REstoring the offset + self.contentOffset = offset; + +} + +-(void)enableZoom +{ + + debug_printf("enableZoom\n"); + + pinchGR.enabled = TRUE; + panGR.enabled = TRUE; + + self.scrollEnabled = TRUE; + + zoomDisabled = FALSE; +} + + +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view +{ + debug_printf("scrollViewWillBeginZooming\n"); +#ifdef ACTIVEGS + // le zoom a démarré : anule les timers pour que le zoom ne soit pas interrompu + [[pManager getEmulatorView].contentView disableGestures:(MODE_ALL + MODE_EMULATOR & ~MODE_ZOOM)]; + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_ZOOM color:[UIColor grayColor]]; +#endif +} + + +- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale +{ + debug_printf("scrollViewDidEndZooming\n"); +#ifdef ACTIVEGS + // zoom terminé => on peut réactiver les gestures immédiatement + [[pManager getEmulatorView].contentView reenableAllGestures]; +#endif +} + + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + // NSLog(@" Offset = %@ ",NSStringFromCGPoint(scrollView.contentOffset)); +} + + +- (void)scrollViewDidZoom:(UIScrollView *)scrollView +{ +// printf("scrollViewDidZoom"); +// [ew directDraw:nil]; +} + +- (void) mouseDown +{ + if (!mouseDown) + { + + debug_printf("mouseDown %f %f\n",lastMousePos.x,lastMousePos.y); + mouseDown = 1; + add_event_mouse(lastMousePos.x,lastMousePos.y,1,1); +#ifdef ACTIVEGS + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_MOUSEBUTTON color:[UIColor redColor]]; +#endif + } +} + +- (void) mouseUp +{ + if (mouseDown) + { + add_event_mouse(lastMousePos.x,lastMousePos.y,0,1); + mouseDown = 0; +#ifdef ACTIVEGS + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_MOUSEBUTTON color:[UIColor greenColor]]; +#endif + } +} + +- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ +#ifdef ACTIVEGS + if ([[pManager getEmulatorView].kbdc myTouchesBegan:touches]) + { + debug_printf("pad activated"); + + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_PAD color:[UIColor grayColor]]; + [[pManager getEmulatorView].contentView disableGestures:(MODE_ALL+MODE_EMULATOR & ~MODE_PAD)]; + return ; + } +#endif + + // prend la première touche + UITouch *touch = [[touches allObjects] objectAtIndex:0]; + + +// if (!runningOnIOS_3_2) + { + // simule les swipes + initialPoint = [touch locationInView:nil]; + initialTimer = [[NSDate date] timeIntervalSince1970]; + } + + + + if (!allowInput) + { + debug_printf("input disabled"); + return ; + } + + if ([touches count] > 1) + { + debug_printf("multiple - disabling input"); +#ifdef ACTIVEGS + [[pManager getEmulatorView].contentView disableGestures:MODE_EMULATOR]; +#endif + return ; + } + + + if (self.useTouch) + { + if (!self.secondTouch && zoomDisabled) + { + if (!mouseDown) + { + debug_printf("second touch mouse Down\n"); + [self mouseDown]; + } + else + { + debug_printf("second touch\n"); + + } + + self.secondTouch = touch; + } + else + { + if (zoomDisabled) + { + debug_printf("third or more touch ignore"); + } + else + { + debug_printf("ignoring second touch - too soon, must be a gestures"); +#ifdef ACTIVEGS + [[pManager getEmulatorView].contentView disableGestures:MODE_EMULATOR]; +#endif + } + } + return ; + + } + + + + self.useTouch = touch; + + lastMousePos = [self rotateTouch:touch]; + + add_event_mouse(lastMousePos.x,lastMousePos.y,0,-1); + + if (self.secondTouch) + { + // mouseDown déjà enclenchée -> on a fini + return ; + } + + int nbtap = [touch tapCount]; + if (nbtap==1) + { + // prépare la désactivation des gestures + //[[pManager getEmulatorView].contentView scheduleDisableAllGestures]; + startNewPhase=TRUE; + + } + +#if !defined(DRIVER_DONTSIMULATESPACE) + if (nbtap==2) + { + extern void simulate_space_event(); + simulate_space_event(); + } +#endif + + if (nbtap>=2 || g_adb.g_warp_pointer==WARP_TOUCHSCREEN) + { + + debug_printf("*** multi-tap\n"); + + [self mouseUp]; + + [self mouseDown]; + + // Désactive immédiatement les gestures +#ifdef ACTIVEGS + if (g_adb.g_warp_pointer!=WARP_TOUCHSCREEN) + [[pManager getEmulatorView].contentView disableGestures:MODE_ALL]; +#endif + } +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + + debug_printf("touchesEnded : %d",[touches count]); + +#ifdef ACTIVEGS + if (! [[pManager getEmulatorView].kbdc myTouchesEnded:touches]) + { + // le pad n'est plus actif - reactive les input si elles étaient disabled + if (!allowInput) + [[pManager getEmulatorView].contentView reenableAllGestures]; + } +#endif + + /* + if (!runningOnIOS_3_2) + { + // simule les swipes + + // prend la première touche + UITouch *touch = [[touches allObjects] objectAtIndex:0]; + + + CGPoint point = [touch locationInView:nil]; + double t = [[NSDate date] timeIntervalSince1970] - initialTimer ; + debug_printf("swipe time:%f",t); + if (t < 1.0) + { + float diffX = point.x - initialPoint.x; + float diffY = point.y - initialPoint.y; + printf("diffX: %f diffY: %f",diffX,diffY); + + int angle = [pManager getAngle]; + BOOL isPortrait = ( abs(angle) == 90 ) ; + if (!isPortrait) + { + double swap = diffX; + diffX = diffY; + diffY = swap; + } + if (angle>0) diffY = -diffY; + + if (abs(diffX) < 40.0 && abs(diffY)> 150.0) + { + // swipeY + if (diffY<0) + // swipe up + [[pManager getEmulatorView].kbdc swipeUp]; + else + [[pManager getEmulatorView].kbdc swipeDown]; + } + } + + } + */ + + if (!allowInput) + return ; + + if ( [touches containsObject:self.useTouch] + && [touches containsObject:self.secondTouch]) + { + debug_printf("both keys ended at the sametime"); + + [self mouseUp]; + + self.useTouch = nil; + self.secondTouch = nil; + + #ifdef ACTIVEGS + // vérifie les gestures + customView* cv = [pManager getEmulatorView].contentView; + [cv processGesturesOnTouchesEnded]; +#endif + return ; + } + + if ([touches containsObject:self.useTouch]) + { + debug_printf("contains useTouch"); + + if (self.secondTouch) + { + // libère useTouch mais ne fait rien d'autre - maintien la touche enclenchée + + debug_printf("maintaining mouseDown - secondTouch "); + self.useTouch = nil; + return; + } + else + { + debug_printf("touchesEnded\n"); + + [self mouseUp]; + self.useTouch = nil; +#ifdef ACTIVEGS + // vérifie les gestures + customView* cv = [pManager getEmulatorView].contentView; + [cv processGesturesOnTouchesEnded]; +#endif + } + } + + if ([touches containsObject:self.secondTouch]) + { + // correspond à un mouseUp + [self mouseUp]; + self.secondTouch = nil; + debug_printf("secondTouch ended"); + + if (!self.useTouch) + { +#ifdef ACTIVEGS + // aucune touche n'est plus appuyée : réactive les gestures + [[pManager getEmulatorView].contentView scheduleEnableAllGestures]; +#endif + } + } + +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + + // on est ici car lez zoom a démarré => théoriquement, il ne doit y avoir aucun useTouch, secondTouch, ou mouseDown + + if ([touches containsObject:self.useTouch]) + { + debug_printf("touchesCancelled useTouch\n"); + self.useTouch = nil; + } + if ([touches containsObject:self.secondTouch]) + { + debug_printf("touchesCancelled secondTouch\n"); + self.secondTouch = nil; + } + + // DEBUG INFO + if (mouseDown) + { + printf("mouseDown in touchesCancelled***"); + [self mouseUp]; + } + + //[[pManager getEmulatorView].contentView reenableAllGestures]; +} + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + +#ifdef ACTIVEGS + if ([[pManager getEmulatorView].kbdc myTouchesMoved:touches]) + return ; +#endif + if (!allowInput) + return ; + + if (startNewPhase) + { + debug_printf("first finger moved"); + startNewPhase = FALSE; +#ifdef ACTIVEGS + [[pManager getEmulatorView].contentView disableGestures:MODE_ZOOM]; // à faire avant le schedule + [[pManager getEmulatorView].contentView scheduleDisableAllGestures]; +#endif + } + + if (!self.useTouch) return ; + if ([touches containsObject:self.useTouch]) + { + /* + CGPoint pt = [useTouch locationInView:self]; + lastMousePos = rotateTouch(self,pt,[pManager getAngle]); + */ + lastMousePos = [self rotateTouch:self.useTouch]; + add_event_mouse(lastMousePos.x,lastMousePos.y,mouseDown,1); + } +} + + +- (void)dealloc { + + self.delegate = nil; + [super dealloc]; +} + + +@end diff --git a/Common.iphone/GTMUIView+SubtreeDescription.h b/Common.iphone/GTMUIView+SubtreeDescription.h new file mode 100644 index 0000000..627298a --- /dev/null +++ b/Common.iphone/GTMUIView+SubtreeDescription.h @@ -0,0 +1,53 @@ +// +// GTMUIView+SubtreeDescription.h +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +#import + +// This entire file, and the corresponding .m is DEBUG only. +// But you can define INCLUDE_UIVIEW_SUBTREE_DESCRIPTION to no-zero to override. +#if DEBUG || INCLUDE_UIVIEW_SUBTREE_DESCRIPTION + +// Example, in debugger, pause the program, then type: +// po [[[UIApplication sharedApplication] keyWindow] subtreeDescription] + +@interface UIView (SubtreeDescription) + +// Returns one line, without leading indent, but with a trailing newline, +// describing the view. +// If you define a |myViewDescriptionLine| method in your own UIView classes, +// this will append that result to its description. +- (NSString *)gtm_subtreeDescriptionLine; + +// For debugging. Returns a nicely indented representation of this view's +// subview hierarchy, each with frame and isHidden. +- (NSString *)subtreeDescription; + +// For debugging. Returns a nicely indented representation of this view's +// layer hierarchy, with frames and isHidden. +// Requires QuartzCore to be useful, but your app will still link without it. +// TODO: should there be an analog of myViewDescriptionLine for layers? +- (NSString *)sublayersDescription; + +@end + +@protocol GTMUIViewSubtreeDescription +// A UIView can implement this and it can add it's own custom description +// in gtm_subtreeDescriptionLine. +- (NSString *)myViewDescriptionLine; +@end + +#endif // DEBUG diff --git a/Common.iphone/GTMUIView+SubtreeDescription.m b/Common.iphone/GTMUIView+SubtreeDescription.m new file mode 100644 index 0000000..978159d --- /dev/null +++ b/Common.iphone/GTMUIView+SubtreeDescription.m @@ -0,0 +1,184 @@ +// +// GTMUIView+SubtreeDescription.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +#import "GTMUIView+SubtreeDescription.h" + +#if 1 +static void AppendLabelFloat(NSMutableString *s, NSString *label, float f) { + [s appendString:label]; + // Respects gcc warning about using == with floats. + if (fabs(f - floor(f)) < 1.0e-8) { // Essentially integer. + int d = f; + // Respects gcc warning about casting floats to ints. + [s appendFormat:@"%d", d]; + } else { + [s appendFormat:@"%3.1f", f]; + } +} + +static NSMutableString *SublayerDescriptionLine(CALayer *layer) { + NSMutableString *result = [NSMutableString string]; + [result appendFormat:@"%@ %p {", [layer class], layer]; + CGRect frame = [layer frame]; + if (!CGRectIsEmpty(frame)) { + AppendLabelFloat(result, @"x:", frame.origin.x); + AppendLabelFloat(result, @" y:", frame.origin.y); + AppendLabelFloat(result, @" w:", frame.size.width); + AppendLabelFloat(result, @" h:", frame.size.height); + } + CGRect bounds = [layer bounds]; + if (!CGRectIsEmpty(bounds)) + { + AppendLabelFloat(result, @"bounds x:", bounds.origin.x); + AppendLabelFloat(result, @" y:", bounds.origin.y); + AppendLabelFloat(result, @" w:", bounds.size.width); + AppendLabelFloat(result, @" h:", bounds.size.height); + } + [result appendFormat:@"}"]; + if ([layer isHidden]) { + [result appendString:@" hid"]; + } + [result appendString:@"\n"]; + return result; +} + +// |sublayersDescription| has a guard so we'll only call this if it is safe +// to call. +static NSMutableString *SublayerDescriptionAtLevel(CALayer *layer, int level) { + NSMutableString *result = [NSMutableString string]; + for (int i = 0; i < level; ++i) { + [result appendString:@" "]; + } + [result appendString:SublayerDescriptionLine(layer)]; + // |sublayers| is defined in the QuartzCore framework, which isn't guaranteed + // to be linked to this program. (So we don't include the header.) + NSArray *layers = [layer performSelector:NSSelectorFromString(@"sublayers")]; + for (CALayer *l in layers) { + [result appendString:SublayerDescriptionAtLevel(l, level+1)]; + } + return result; +} + +@implementation UIView (SubtreeDescription) + +// TODO: Consider flagging things which might help in debugging: +// - alpha < 10% +// - origin not zero +// - non-opaque +// - transform if not identity +// - view not entirely within ancestor views +// - (possibly) tag==0 +- (NSString *)gtm_subtreeDescriptionLine { + NSMutableString *result = [NSMutableString string]; + [result appendFormat:@"%@ %p {", [self class], self]; + CGRect frame = [self frame]; + + + if (!CGRectIsEmpty(frame)) { + AppendLabelFloat(result, @"x:", frame.origin.x); + AppendLabelFloat(result, @" y:", frame.origin.y); + AppendLabelFloat(result, @" w:", frame.size.width); + AppendLabelFloat(result, @" h:", frame.size.height); + } + CGRect bounds = [self bounds]; + if (!CGRectIsEmpty(bounds)) + { + AppendLabelFloat(result, @"-- bounds x:", bounds.origin.x); + AppendLabelFloat(result, @" y:", bounds.origin.y); + AppendLabelFloat(result, @" w:", bounds.size.width); + AppendLabelFloat(result, @" h:", bounds.size.height); + } + [result appendString:@"}"]; + + CGAffineTransform t = [self transform]; + if (!CGAffineTransformIsIdentity(t)) + { + AppendLabelFloat(result, @"-- matrix 11:", t.a); + AppendLabelFloat(result, @" 12:", t.b); + AppendLabelFloat(result, @" 21:", t.c); + AppendLabelFloat(result, @" 22:", t.d); + AppendLabelFloat(result, @" tx:", t.tx); + AppendLabelFloat(result, @" ty:", t.ty); + + } + + if ([self isKindOfClass:[UIScrollView class]]) + { + UIScrollView* sv = (UIScrollView*)self; + float scale = sv.zoomScale; + AppendLabelFloat(result, @" scale:", scale); + } + + + AppendLabelFloat(result, @" alpha:", self.alpha); + if ([self isHidden]) { + [result appendString:@" hid"]; + } + + if ([self respondsToSelector:@selector(myViewDescriptionLine)]) { + NSString *customDescription = + [self performSelector:@selector(myViewDescriptionLine)]; + if (customDescription != nil) { + [result appendFormat:@" %@", customDescription]; + } + } + + [result appendString:@"\n"]; + return result; +} + +- (NSString *)gtm_subtreeDescriptionAtLevel:(int)level { + NSMutableString *result = [NSMutableString string]; + for (int i = 0; i < level; ++i) { + [result appendString:@" "]; + } + [result appendString:[self gtm_subtreeDescriptionLine]]; + for (UIView *v in [self subviews]) { + [result appendString:[v gtm_subtreeDescriptionAtLevel:level+1]]; + } + return result; +} + +- (NSString *)subtreeDescription { + NSMutableString *result = + [[[self gtm_subtreeDescriptionLine] mutableCopy] autorelease]; + for (UIView *v in [self subviews]) { + [result appendString:[v gtm_subtreeDescriptionAtLevel:1]]; + } + return result; +} + +// for debugging dump the layer hierarchy, frames and isHidden. +- (NSString *)sublayersDescription { + CALayer *layer = [self layer]; + SEL sublayers = NSSelectorFromString(@"sublayers"); + if (![layer respondsToSelector:sublayers]) { + return @"*** Sorry: This app is not linked with the QuartzCore framework."; + } + NSMutableString *result = SublayerDescriptionLine(layer); + NSArray *layers = [layer performSelector:sublayers]; + for (CALayer *l in layers) { + [result appendString:SublayerDescriptionAtLevel(l, 1)]; + } + return result; +} + +@end + +#endif // DEBUG + + diff --git a/Common.iphone/KBDController.h b/Common.iphone/KBDController.h new file mode 100644 index 0000000..211631b --- /dev/null +++ b/Common.iphone/KBDController.h @@ -0,0 +1,187 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + +enum +{ + LOCKZOOM_AUTO=0, + LOCKZOOM_ON=1, + LOCKZOOM_ARCADE=2 +}; + +@interface KBDController : UIViewController +{ + + CGRect keyboardDelta; + float keyboardScale; + BOOL bMenuBarVisibility; + BOOL bLoading; + BOOL padEnabled; + CGPoint posPad; + float diskAngle ; + + + + int inputMode; + + UITextField* _textField; + UIButton* _menuButton; + UIBarButtonItem* _optionButton ; + UIImageView* _diskView; + UIImageView* _diskLoadingView; + NSMutableArray* _diskIcons; + UILabel* _loaderLabel; + UILabel* _debugIndicator; + UILabel* _swipeIndicator; + UILabel* _zoomIndicator; + UILabel* _padIndicator; + UILabel* _mouseButtonIndicator; + UILabel* _inputIndicator; + + UIActivityIndicatorView* _loader; + NSTimer* _loaderTimer; +#ifdef GRAPHICAL_PAD + UIImageView* _padBackground; + UIImageView* _padButton1Down; + UIImageView* _padButton2Down; + UIImageView* _padStick; +#endif + UIImageView* _padCircleOutter; + UIImageView* _padCircleInner; + UIImageView* _oaButtonView; + UIImageView* _caButtonView; + UITouch* _padTouch; + UITouch* _oaButtonTouch; + UITouch* _caButtonTouch; + UINavigationItem* _emulatorNavItem; + UINavigationBar* _runtimeView; + UIView* _interfaceView; + NSTimer* _hardwarekbdDetectionTimer; + NSTimer* _animateDiskTimer; + + UIImageView* _runtimeControls; + UIView* _runtimeControlsOptions; + + UIImageView* _diskSelection; + UIView* _diskSelectionOptions; + UIScrollView* _uit; + UIScrollView* _uitb; + UIView* _accessView; + UIButton* _leftAccessView; + UIButton* _rightAccessView; + UINavigationBar* _barView; + UINavigationBar* _specialView; + + +} + +@property (nonatomic,retain) UITextField* textField; + +@property (nonatomic,retain) UIButton *menuButton; +@property (nonatomic,retain) UIBarButtonItem* optionButton ; +@property (nonatomic,retain) UIImageView* diskView; +@property (nonatomic,retain) UIImageView* diskLoadingView; +@property (nonatomic,retain) NSMutableArray* diskIcons; +@property (nonatomic,retain) UILabel * loaderLabel; +@property (nonatomic,retain) UILabel* debugIndicator; +@property (nonatomic,retain) UILabel* swipeIndicator; +@property (nonatomic,retain) UILabel* zoomIndicator; +@property (nonatomic,retain) UILabel* padIndicator; +@property (nonatomic,retain) UILabel* mouseButtonIndicator; +@property (nonatomic,retain) UILabel* inputIndicator; +@property (nonatomic,retain) UIActivityIndicatorView* loader; +@property (nonatomic,retain) NSTimer* loaderTimer; +#ifdef GRAPHICAL_PAD +@property (nonatomic,retain) UIImageView* padBackground; +@property (nonatomic,retain) UIImageView* padButton1Down; +@property (nonatomic,retain) UIImageView* padButton2Down; +@property (nonatomic,retain) UIImageView* padStick; +#endif +@property (nonatomic,retain) UIImageView* padCircleOutter; +@property (nonatomic,retain) UIImageView* padCircleInner; +@property (nonatomic,retain) UIImageView* oaButtonView; +@property (nonatomic,retain) UIImageView* caButtonView; +@property (nonatomic,retain) UITouch* padTouch; +@property (nonatomic,retain) UITouch* oaButtonTouch; +@property (nonatomic,retain) UITouch* caButtonTouch; +@property (nonatomic,retain) UINavigationItem* emulatorNavItem; +@property (nonatomic,retain) UINavigationBar* runtimeView; +@property (nonatomic,retain) UIView* interfaceView; +@property (nonatomic,retain) NSTimer* animateDiskTimer; +@property (nonatomic,retain) NSTimer* hardwarekbdDetectionTimer; +@property (nonatomic,retain) UIImageView* runtimeControls; +@property (nonatomic,retain) UIView* runtimeControlsOptions; +@property (nonatomic,retain) UIImageView* diskSelection; +@property (nonatomic,retain) UIView* diskSelectionOptions; +@property (nonatomic,retain) UIScrollView* uit; +@property (nonatomic,retain) UIScrollView* uitb; +@property (nonatomic,retain) UIView* accessView; +@property (nonatomic,retain) UIButton* leftAccessView; +@property (nonatomic,retain) UIButton* rightAccessView; +@property (nonatomic,retain) UINavigationBar* barView; +@property (nonatomic,retain) UINavigationBar* specialView; +//@property (assign,getter=inputMode) int inputMode; + + +-(void)updateSpecialButtonView:(UIButton*)_b state:(int)_state; +-(void)addSpecialKeys; +-(void)addRuntimeControls; +-(void)resetSpecialKeys; +-(void)unloadSpecialKeys; +- (void) animateDisk:(id)_id ; +-(void)refreshControls:(id)sender; +- (void) detectHardwareKeyboard:(id)_id ; +- (void)setLoading:(NSNumber*)_nsvisible; +-(void)setiCadeMode:(BOOL)_mode; +-(void)OnScreenKeyboard:(BOOL)_enabled; +-(void)enableKeyboard:(int)_enable; +-(void)restoreInput; + +//#define INPUTMODE_NONE 0 +#define INPUTMODE_PAD 1 +#define INPUTMODE_KBD 2 +#define INPUTMODE_ACCESS 4 +#define INPUTMODE_MINIACCESS 8 +#define INPUTMODE_ARCADE 16 +#define INPUTMODE_CUSTOMKEYS 32 +#define INPUTMODE_KBDFORCED 64 + +#define INPUTMODE_ALL (INPUTMODE_KBD + INPUTMODE_PAD + INPUTMODE_ACCESS) +#define INPUTMODE_HIDDEN 128 + + +-(int)isInputVisible:(int) _im; +-(void)hideInput; +-(void)cycleInput; +-(void) updateSpecialKey:(CGRect)rv3; +- (void)setInputMode:(int)_mode; +- (void)setMenuBarVisibility:(int)_visible; +//- (void)toggleMenuBarVisibility ; +- (void)setEmulatorTitle:(const char*)_name ; +- (void)swapButton:(id)sender; +- (void)updateView:(CGRect)_rect; +- (void)swipeUp; +- (void)swipeDown; +-(void)setGestureIndicatorVisibility:(int)_mode color:(UIColor*)_color; +-(void)setDebugIndicatorText:(const char*)_text; +-(void)showDebug:(BOOL)_visible; +- (void)hideLoader:(id)_id; +-(void)updatePadView; +-(void)centerPad:(id)center; + +-(void)enablePad:(BOOL)_enable; +-(UIImageView*)createCircle:(float)_radius red:(float)_red green:(float)_green blue:(float)_blue alpha:(float)_alpha; +- (BOOL) myTouchesBegan:(NSSet *)touches ; +- (BOOL) myTouchesMoved:(NSSet *)touches ; +- (BOOL) myTouchesEnded:(NSSet *)touches ; +-(CGFloat) getEmulatorScale; +-(CGRect) getEmulatorDelta; +- (void)updateViewForKeyboard:(int)_height; + + @end + + diff --git a/Common.iphone/KBDController.mm b/Common.iphone/KBDController.mm new file mode 100644 index 0000000..f98f702 --- /dev/null +++ b/Common.iphone/KBDController.mm @@ -0,0 +1,2789 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "KBDController.h" +#include "../kegs/src/defc.h" +#include "../kegs/src/protos_macdriver.h" +#include "../kegs/src/sim65816.h" +#include "../kegs/src/moremem.h" +#include "../kegs/src/adb.h" +#include "../kegs/src/sound.h" +#include "../kegs/src/async_event.h" +#include "../Common/svnversion.h" +#import "activegsAppDelegate.h" +#import "activegsViewController.h" +#import +#import +#include "../kegs/src/paddles.h" +#import "../kegs/iOS/emulatorView.h" + +#ifdef ACTIVEGS_CUSTOMKEYS + #include "UICustomKey.h" +#endif + +#ifndef ACTIVEGS_NOHARDWAREKEYBOARDETECTION +extern "C" void GSEventSetHardwareKeyboardAttached(Boolean); +extern "C" void UIKeyboardOrderInAutomatic(); +extern "C" void UIKeyboardOrderOutAutomatic(); +extern "C" BOOL UIKeyboardAutomaticIsOnScreen(); +#endif + +#undef debug_printf +#define debug_printf printf + +float joyX=0.0f,joyY=0.0f; +int oaButton=FALSE,caButton=FALSE; +int padEnabled=FALSE; +int externalKeyboard=FALSE; +int iCadeDetected=FALSE; +int bForceOnScreenKeyboard = FALSE; + + +enum runtimeKeysAction +{ +// RT_PAUSE, + RT_COLOR, + RT_FX, + RT_SPEED, + RT_CAPTURE, + RT_RESTORE, + RT_ZOOM +}; + + +typedef struct { + const char* label; + enum runtimeKeysAction action; + UIButton* hButton; +} rkey; + +rkey runtimeKeysList[]= +{ +// { "Pause", RT_PAUSE, nil }, + { "Color", RT_COLOR, nil }, + { "F/X", RT_FX, nil }, + { "Speed", RT_SPEED, nil }, + { "Save", RT_CAPTURE, nil }, + { "Restore", RT_RESTORE, nil }, +// { "Zoom", RT_ZOOM, nil } +}; + + +#define NBBUTTONLOOP 2 + +typedef struct { + const char* label; + int code; + int modifier; + int state; + int shiftxxx; + UIButton* hButton[NBBUTTONLOOP]; +} skey; + + +#define UITB_BUTTON_WIDTH 20 +#define UITB_BUTTON_PADDING 4 +#define ACCESS_HEIGHT 36 + +skey buttonList[] = { + + { "SHIFT",0x38,0,0,0,nil}, + { "ESC", 0x35 , 0, -1, 0,nil}, + { "TAB",0x30,0,-1,0,nil }, + { "CTRL",0x36,0,0,0,nil }, + { "",0x37,0,0,0,nil}, + { "OPT",0x3A,0,0,0,nil}, + { "RESET",0x7F,0,-1,0,nil}, + + { "←", 0x3B,0, -1,0,nil}, + { "→",0x3C,0,-1,0,nil}, + { "↑",0x3E,0,-1,0,nil}, + { "↓",0x3D,0,-1,0,nil}, + + + { "J",0x26+shiftKey,0,-1,1,nil}, + { "K",0x28+shiftKey,0,-1,1,nil}, + { "SPC",0x31,0,-1,0,nil}, + { "RET",0x24,0,-1,0,nil}, + { "1",0x12,0,-1,0,nil}, + { "2",0x13,0,-1,0,nil}, + { "3",0x14,0,-1,0,nil}, + { "4",0x15,0,-1,0,nil}, + { NULL,0,0,0 } }; + +#define KBDWIDTH 22 +#define KBDWIDTHTAB 25 +#define KBDWIDTHCTRL 30 +#define KBDWIDTHRET 30 +#define KBDWIDTHSHIFT 42 +#define KBDWIDTHAPPLE 30 +#define KBDWIDTHSPACE 100 + + +struct kbdDefinition +{ + int w; + const char* k1; + int code1; + const char* k2; + int code2; + int posx,posy; +}; + +struct kbdDefinition kbdDefinitions[]= +{ + { KBDWIDTH,"esc",0x35,0,0 }, + { KBDWIDTH,"1",0x12,"!",0 }, + { KBDWIDTH,"2",0x13,"@",0 }, + { KBDWIDTH,"3",0x14,"#",0 }, + { KBDWIDTH,"4",0x15,"$",0 }, + { KBDWIDTH,"5",0x17,"%",0 }, + { KBDWIDTH,"6",0x16,"^",0 }, + { KBDWIDTH,"7",0x1A,"&",0 }, + { KBDWIDTH,"8",0x1C,"*",0 }, + { KBDWIDTH,"9",0x19,"(",0 }, + { KBDWIDTH,"0",0x1D,")",0 }, + { KBDWIDTH,"-",0x1B,"_",0 }, + { KBDWIDTH,"=",0x18,"+",0 }, + { KBDWIDTHTAB,"delete",0x33,0,0 }, + { -1,0,0,0,0 }, + { KBDWIDTHTAB,"tab",0x30,0,0 }, + { KBDWIDTH,"q",0x0C,"Q",0 }, + { KBDWIDTH,"w",0x0D,"W",0 }, + { KBDWIDTH,"e",0x0E,"E",0 }, + { KBDWIDTH,"r",0x0F,"R",0 }, + { KBDWIDTH,"t",0x11,"T",0 }, + { KBDWIDTH,"y",0x10,"Y",0 }, + { KBDWIDTH,"u",0x20,"U",0 }, + { KBDWIDTH,"i",0x22,"I",0 }, + { KBDWIDTH,"o",0x1F,"O",0 }, + { KBDWIDTH,"p",0x23,"P",0 }, + { KBDWIDTH,"[",0x21,"{",0 }, + { KBDWIDTH,"]",0x1E,"}",0 }, + { KBDWIDTHTAB,"menu",-1,0,0 }, + { -1,0,0,0,0 }, + { KBDWIDTHCTRL,"control",0x36,0,0 }, + { KBDWIDTH,"a",0x00,"A",0 }, + { KBDWIDTH,"s",0x01,"S",0 }, + { KBDWIDTH,"d",0x02,"D",0 }, + { KBDWIDTH,"f",0x03,"F",0 }, + { KBDWIDTH,"g",0x05,"G",0 }, + { KBDWIDTH,"h",0x04,"H",0 }, + { KBDWIDTH,"j",0x26,"J",0 }, + { KBDWIDTH,"k",0x28,"K",0 }, + { KBDWIDTH,"l",0x25,"L",0 }, + { KBDWIDTH,";",0x29,":",0 }, + { KBDWIDTH,"'",0x27,"\"",0 }, + { KBDWIDTHRET,"return",0x24,0,0 }, + { -1,0,0,0,0 }, + { KBDWIDTHSHIFT,"shift",0x38,0,0 }, + { KBDWIDTH,"z",0x06,"Z",0 }, + { KBDWIDTH,"x",0x07,"X",0 }, + { KBDWIDTH,"c",0x08,"C",0 }, + { KBDWIDTH,"v",0x09,"V",0 }, + { KBDWIDTH,"b",0x0B,"B",0 }, + { KBDWIDTH,"n",0x2D,"N",0 }, + { KBDWIDTH,"m",0x2E,"M",0 }, + { KBDWIDTH,",",0x2B,"<",0 }, + { KBDWIDTH,".",0x2F,">",0 }, + { KBDWIDTH,"/",0x2C,"?",0 }, + { KBDWIDTHSHIFT,"shift",0x38,0,0 }, + { -1,0,0,0,0 }, + { KBDWIDTH,"caps",0x39,0,0 }, + { KBDWIDTH,"option",0x37,0,0 }, + { KBDWIDTHAPPLE,"",0x3A,0,0 }, + { KBDWIDTH,"`",0x12,0,0 }, + { KBDWIDTHSPACE," ",0x31,0,0 }, + { KBDWIDTH,"x",0x13,0,0 }, + { KBDWIDTH,"->",0x3C,0,0 }, + { KBDWIDTH,"<-",0x3B,0,0 }, + { KBDWIDTH,"^",0x5B,0,0 }, + { KBDWIDTH,"v",0x13,0,0 }, + + { 0,0,0,0,0 } + +}; + +int findCode(const char* _s) +{ + int i =0; + while(kbdDefinitions[i].w) + { + if (kbdDefinitions[i].k1 && !strcmp(kbdDefinitions[i].k1,_s)) + return kbdDefinitions[i].code1; + if (kbdDefinitions[i].k2 && !strcmp(kbdDefinitions[i].k2,_s)) + return (kbdDefinitions[i].code1 + shiftKey); + i++; + } + return -1; + +} + + +#define INNER_SIZE 64 +#define OUTTER_SIZE 128 +#define BUTTON_SIZE 80 +#define BUTTON_PADDING 32 + +static float innerSize,outterSize,buttonSize; +static const char* disk_names[] = { "disk_35_1", "disk_35_2", "disk_525_1","disk_525_2" , "disk" }; + + +UIImageView* loadImage(NSString* _name) +{ + + NSString *imgSource = [[NSBundle mainBundle] pathForResource:_name ofType:@"png"]; + UIImage* img = [[UIImage imageWithContentsOfFile: imgSource] retain]; + UIImageView* view = [[UIImageView alloc] initWithImage:img]; + return view; + +} + + +int isHardwareKeyboard() +{ + + + if (bForceOnScreenKeyboard) + return 1; + + +#ifdef ACTIVEGS_NOHARDWAREKEYBOARDDETECTION + // ppour la soumission appstore! + return option.getIntValue(OPTION_EXTERNALKBD); +#else + int isHardware=0; + @try + { + Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl"); + id activeInstance = [UIKeyboardImpl performSelector:@selector(sharedInstance)]; + id v = [activeInstance valueForKey:@"isInHardwareKeyboardMode"]; + isHardware = [(NSNumber*)v intValue]; + } + @catch (NSException *exception) + { + NSLog(@"Exception %@", exception); + } + + return isHardware; +#endif + +} + +@implementation KBDController + +@synthesize textField = _textField; +//@synthesize inputMode = _inputMode; +@synthesize menuButton = _menuButton; +@synthesize optionButton = _optionButton; +@synthesize diskView = _diskView; +@synthesize diskLoadingView = _diskLoadingView; +@synthesize diskIcons = _diskIcons; +@synthesize loaderLabel = _loaderLabel; +@synthesize debugIndicator = _debugIndicator; +@synthesize swipeIndicator = _swipeIndicator; +@synthesize zoomIndicator = _zoomIndicator; +@synthesize padIndicator = _padIndicator; +@synthesize mouseButtonIndicator = _mouseButtonIndicator; +@synthesize inputIndicator = _inputIndicator; +@synthesize loader = _loader; +@synthesize loaderTimer = _loaderTimer; +#ifdef GRAPHICAL_PAD +@synthesize padBackground = _padBackground; +@synthesize padButton1Down = _padButton1Down; +@synthesize padButton2Down = _padButton2Down; +@synthesize padStick = _padStick; +#endif +@synthesize padCircleOutter = _padCircleOutter; +@synthesize padCircleInner = _padCircleInner; +@synthesize oaButtonView = _oaButtonView; +@synthesize caButtonView = _caButtonView; +@synthesize padTouch = _padTouch; +@synthesize oaButtonTouch = _oaButtonTouch; +@synthesize caButtonTouch = _caButtonTouch; +@synthesize emulatorNavItem = _emulatorNavItem; +@synthesize runtimeView = _runtimeView; +@synthesize interfaceView = _interfaceView; +@synthesize hardwarekbdDetectionTimer = _hardwarekbdDetectionTimer; +@synthesize animateDiskTimer = _animateDiskTimer; +@synthesize runtimeControls = _runtimeControls; +@synthesize runtimeControlsOptions = _runtimeControlsOptions; +@synthesize diskSelection = _diskSelection; +@synthesize diskSelectionOptions = _diskSelectionOptions; +@synthesize uit = _uit; +@synthesize uitb = uitb; +@synthesize accessView = _accessView; +@synthesize leftAccessView = _leftAccessView; +@synthesize rightAccessView = _rightAccessView; +@synthesize barView = _barView; +@synthesize specialView = _specialView; + +extern int findCode(const char* _s); + + +- (void)loadView +{ + + NSLog(@"---kbd loadView"); + + CGRect r = [UIScreen mainScreen].applicationFrame; + self.interfaceView = [ [UIView alloc] initWithFrame:r] ; + + [self.interfaceView setUserInteractionEnabled:TRUE]; + self.interfaceView.multipleTouchEnabled = 1; + + float s = [pManager resolutionRatio]; + + self.barView = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, r.size.width, BARVIEW_HEIGHT)]; + self.barView.barStyle = UIBarStyleBlack; + self.barView.translucent = TRUE; +#ifdef ACTIVEGS_NOAPPLEBRANDING + self.emulatorNavItem = [[UINavigationItem alloc] initWithTitle:@"ActiveGS"]; +#else + self.emulatorNavItem = [[UINavigationItem alloc] initWithTitle:@"Apple IIGS™"]; +#endif + + [self.barView pushNavigationItem:self.emulatorNavItem animated:FALSE]; + + // left Arrow + UIButton* backButton = [UIButton buttonWithType:(UIButtonType)101]; // left-pointing shape! + [backButton addTarget:self action:@selector(menuButton:) forControlEvents:UIControlEventTouchUpInside]; + [backButton setTitle:@"Browse" forState:UIControlStateNormal]; + + // create button item -- possible because UIButton subclasses UIView! + UIBarButtonItem* browseItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; + + self.emulatorNavItem.leftBarButtonItem = browseItem; + + self.optionButton = [[UIBarButtonItem alloc] initWithTitle:@"Options" style:UIBarButtonItemStylePlain + target:self + action:@selector(optionsButton:)]; + + self.emulatorNavItem.rightBarButtonItem = self.optionButton; + + [self.interfaceView addSubview:self.barView]; + + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil]; + [nc addObserver:self selector:@selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil]; + [nc addObserver:self selector:@selector(keyboardDidShow:) name: UIKeyboardDidShowNotification object:nil]; + [nc addObserver:self selector:@selector(keyboardDidHide:) name: UIKeyboardDidHideNotification object:nil]; + + + // charge toutes les icones disks + + self.diskIcons = [[NSMutableArray alloc] init]; + + for(int i=0;i<5;i++) + { + + NSString *imgSource = [[NSBundle mainBundle] pathForResource:[NSString stringWithUTF8String:disk_names[i]] ofType:@"png"]; + NSLog(@"loading %@",imgSource); + [self.diskIcons addObject:[UIImage imageWithContentsOfFile: imgSource]]; + } + + CGSize ds = [[self.diskIcons objectAtIndex:4] size]; + ds.width *=s; + ds.height*=s; + self.diskView = [[UIImageView alloc] initWithFrame:CGRectMake(0,BARVIEW_HEIGHT+4*s,ds.width,ds.height)]; + self.diskView.image = [self.diskIcons objectAtIndex:4]; + self.diskView.hidden = TRUE; + self.diskView.alpha=0.8; + + + self.diskLoadingView = [[UIImageView alloc] initWithFrame:CGRectMake(0,BARVIEW_HEIGHT+4*s,ds.width,ds.height)]; + self.diskLoadingView.image = [self.diskIcons objectAtIndex:0]; + self.diskLoadingView.hidden = FALSE; + self.diskLoadingView.alpha=0.0; // hidden by default + + + [self.interfaceView addSubview:self.diskView]; + [self.interfaceView addSubview:self.diskLoadingView]; + +#define WHEELSIZE 50 + self.loader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + CGRect lr = self.loader.frame; + lr.origin.x = 8; + lr.origin.y = 32; + [self.loader setFrame:lr]; + [self.interfaceView addSubview:self.loader]; + [self.loader stopAnimating]; + self.loader.hidden = TRUE; + + + self.swipeIndicator = [[UILabel alloc] initWithFrame:CGRectMake(8,64,16,16)]; + self.swipeIndicator.backgroundColor = [UIColor redColor]; + self.swipeIndicator.text = @"S"; + [self.interfaceView addSubview:self.swipeIndicator]; + + self.zoomIndicator = [[UILabel alloc] initWithFrame:CGRectMake(8+20,64,16,16)]; + self.zoomIndicator.backgroundColor = [UIColor redColor]; + self.zoomIndicator.text = @"Z"; + [self.interfaceView addSubview:self.zoomIndicator]; + + self.padIndicator = [[UILabel alloc] initWithFrame:CGRectMake(8+40,64,16,16)]; + self.padIndicator.backgroundColor = [UIColor redColor]; + self.padIndicator.text = @"P"; + [self.interfaceView addSubview:self.padIndicator]; + + self.mouseButtonIndicator = [[UILabel alloc] initWithFrame:CGRectMake(8+60,64,16,16)]; + self.mouseButtonIndicator.backgroundColor = [UIColor greenColor]; + self.mouseButtonIndicator.text = @"B"; + [self.interfaceView addSubview:self.mouseButtonIndicator]; + + + self.inputIndicator = [[UILabel alloc] initWithFrame:CGRectMake(8+80,64,16,16)]; + self.inputIndicator.backgroundColor = [UIColor greenColor]; + self.inputIndicator.text = @"I"; + [self.interfaceView addSubview:self.inputIndicator]; + + self.debugIndicator = [[UILabel alloc] initWithFrame:CGRectMake(8+120,64,150,16)]; + self.debugIndicator.hidden = TRUE; + self.debugIndicator.backgroundColor = [UIColor lightGrayColor]; + self.debugIndicator.font = [UIFont systemFontOfSize:(CGFloat)12.0]; + self.debugIndicator.lineBreakMode=UILineBreakModeClip; + [self.interfaceView addSubview:self.debugIndicator]; + + [self showDebug:FALSE]; + + CGRect lrl = CGRectMake(lr.origin.x,lr.origin.y+lr.size.height,50,10); + + self.loaderLabel = [[UILabel alloc] initWithFrame:lrl]; + self.loaderLabel.text=@"100pc"; + [self.interfaceView addSubview:self.loaderLabel]; + self.loaderLabel.hidden = TRUE; + + + self.textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; + self.textField.delegate = self; + self.textField.autocapitalizationType= UITextAutocapitalizationTypeAllCharacters; + self.textField.text= @"*"; // Put a default value to capture del key + [self.interfaceView addSubview:self.textField]; + + self.view = self.interfaceView; + + keyboardScale = 1.0; + + + float rr = [pManager resolutionRatio]; + innerSize = INNER_SIZE * rr; + outterSize = OUTTER_SIZE * rr; + buttonSize = BUTTON_SIZE * rr; + + self.padCircleOutter = [self createCircle:outterSize red:1.0 green:1.0 blue:1.0 alpha:0.3]; + self.padCircleOutter.frame = CGRectMake(0,r.size.height-outterSize,outterSize,outterSize); + [self.interfaceView addSubview:self.padCircleOutter]; + + self.padCircleInner = [self createCircle:innerSize red:0.8 green:0.8 blue:0.8 alpha:1.0]; + + [self.padCircleOutter addSubview:self.padCircleInner]; + + self.oaButtonView = [self createCircle:buttonSize red:1.0 green:1.0 blue:1.0 alpha:1.0]; + self.oaButtonView.frame = CGRectMake(r.size.width-buttonSize,r.size.height-buttonSize*2,buttonSize,buttonSize); + [self.interfaceView addSubview:self.oaButtonView]; + + self.caButtonView = [self createCircle:buttonSize red:1.0 green:1.0 blue:1.0 alpha:1.0]; + self.caButtonView.frame = CGRectMake(r.size.width-buttonSize,r.size.height-buttonSize,buttonSize,buttonSize); + [self.interfaceView addSubview:self.caButtonView]; + +#ifdef GRAPHICAL_PAD + self.padBackground = loadImage(@"pad_up"); + + // resize la view + CGSize rgpad = self.padBackground.image.size; + float gratio = 320.0 / rgpad.width ; + float hpad = gratio * rgpad.height ; + self.padBackground.frame = CGRectMake(0,480-hpad,320,hpad); + + self.padButton1Down = loadImage(@"pad_button1_down"); + + // 42,28 + + // resize la view + rgpad = self.padButton1Down.image.size; + self.padButton1Down.frame = CGRectMake(42/2,480-hpad+28/2,gratio * rgpad.width,gratio * rgpad.height); + + self.padButton2Down = loadImage(@"pad_button2_down"); + + // 42,226 + + // resize la view + rgpad = self.padButton2Down.image.size; + self.padButton2Down.frame = CGRectMake(42/2,480-hpad+226/2,gratio * rgpad.width,gratio * rgpad.height); + + self.padStick = loadImage(@"pad_stick"); + + // 42,226 + + // resize la view + rgpad = self.padStick.image.size; + self.padStick.frame = CGRectMake(200,480-hpad+200/2,gratio * rgpad.width,gratio * rgpad.height); + + + [self.interfaceView addSubview:self.padBackground]; + [self.interfaceView addSubview:self.padButton1Down]; + [self.interfaceView addSubview:self.padButton2Down]; + [self.interfaceView addSubview:self.padStick]; + + +#endif + + [self addRuntimeControls]; + [self addDiskSelection]; + + [self addSpecialKeys]; + +#if 0 + [self addRuntimeKeys]; +#endif + +#ifdef ACTIVEGS_CUSTOMKEYS + init_custom_keys(); +#endif + + iCadeDetected = FALSE; + externalKeyboard = FALSE; + + [self detectHardwareKeyboard:nil]; + + + [self setInputMode:INPUTMODE_ACCESS+INPUTMODE_HIDDEN]; + [self setMenuBarVisibility:TRUE]; // So First time users are not lost! + +} + +int hardwarekeyboard= 0; + +-(void)detectHardwareKeyboard:(id)_obj +{ + + if (bForceOnScreenKeyboard) + return ; + + int d = isHardwareKeyboard(); + if (d == hardwarekeyboard) return ; + hardwarekeyboard = d; + if ( d ) + { + [pManager setNotificationText:@"External keyboard enabled"]; + [self enableKeyboard:TRUE]; + } + else + { + [pManager setNotificationText:@"External keyboard disabled"]; + + [self setiCadeMode:FALSE]; + } + + +} + + +-(void)setiCadeMode:(BOOL)_mode +{ + if (iCadeDetected == _mode) + return ; + + iCadeDetected = _mode; + NSLog(@"setting iCadeMode to %d",_mode); + + if (_mode==TRUE) + { + option.setIntValue(OPTION_JOYSTICKMODE,JOYSTICK_TYPE_ICADE); + [self setInputMode:inputMode&INPUTMODE_PAD]; + [pManager setNotificationText:@"iCade activated"]; + } + else + { + option.setIntValue(OPTION_JOYSTICKMODE,JOYSTICK_TYPE_KEYPAD); + [pManager setNotificationText:@"iCade de-activated"]; + + } + + [self refreshControls:nil]; + +} + + +typedef struct { + int cid; + const char* name; + const char* options[5]; + int optionValues[5]; + UISegmentedControl* hControl; +} scontrol; + + +enum runtimeControlEnum +{ + RC_LOCKZOOM=100, + RC_JOYSTICK, + RC_DISPLAY, + RC_TYPE, + RC_SPEED, + RC_FPS, + RC_KBD, + RC_MOUSE, + RC_DISKSOUND, + RC_AUDIO, + RC_MEMORY, + RC_END=-1 + +}; + + + +scontrol runtimeControlDefs[]={ + + { + RC_SPEED, + "Speed", + { "1Mhz", "2GS", "ZIP",NULL } , + { (int)SPEED_1MHZ, (int)SPEED_GS, (int)SPEED_ZIP }, + nil + }, + { + RC_FPS, + "Frames per second", + { "15", "20","30", "60",NULL } , + { 15, 20,30, 60 }, + nil + }, + + { + RC_AUDIO, + "Audio", + { "None", "22KHz", "44KHz",NULL } , + { 0, 22050, 44100 }, + nil + }, + { + RC_MEMORY, + "Memory Size", + { "1MB", "2MB", "4MB",NULL } , + { 1, 2, 4 }, + nil + }, + { + RC_DISPLAY, + "Display" , + { "CRT", "LCD", NULL }, + { (int)VIDEOFX_CRT, (int)VIDEOFX_LCD }, + nil + }, + { + RC_TYPE, + "Screen", + { "B&W", "Green" ,"Colors", NULL }, + { (int)COLORMODE_BW, (int)COLORMODE_GREEN,(int)COLORMODE_AUTO, }, + nil + }, + + + + { + RC_LOCKZOOM, + "Zoom Control" , + { "Auto", "Lock", "Arcade",NULL }, + { LOCKZOOM_AUTO,LOCKZOOM_ON, LOCKZOOM_ARCADE}, + nil + }, +/* +#if 0 + { + RC_JOYSTICK, + "Pad Input" , + { "iDevice", "iCade",NULL }, + { JOYSTICK_TYPE_NATIVE_1,JOYSTICK_TYPE_ICADE}, + nil + }, +#endif + */ +#ifdef ACTIVEGS_NOHARDWAREKEYBOARDDETECTION + { + RC_KBD, + "External Keyboard", + { "Disable", "Enable",NULL } , + { 0, 1 }, + nil + }, +#endif + { + RC_MOUSE, + "Mouse Control", + { "Warp", "Touch",NULL } , + { (int)WARP_POINTER, WARP_TOUCHSCREEN,0 }, + nil + }, + { + RC_DISKSOUND, + "Disk Drive Sounds", + { "Enable", "Disable",NULL } , + { (int)1, 0,0 }, + nil + }, + { + RC_END, + NULL, + NULL, + NULL, + nil + } + +}; + + +scontrol* findControlByID(int _controlId) +{ + int i=0; + while(runtimeControlDefs[i].cid!=RC_END) + { + if (runtimeControlDefs[i].cid==_controlId) + return &runtimeControlDefs[i]; + i++; + } + return NULL; +} + +void setControlValue(int _control,int _v) +{ + scontrol* s = findControlByID(_control); + if (!s) return ; + + int i =0; + while(s->options[i]) + { + if (s->optionValues[i]==_v) + { + if (s->hControl) + s->hControl.selectedSegmentIndex = i; + return; + } + i++; + } + printf("value %d not found for controlerid:%d\n",_v,_control); +} + +extern int x_lock_zoom ; +extern int x_frame_rate ; + +-(void)refreshControls:(id)sender +{ + + setControlValue(RC_LOCKZOOM, x_lock_zoom); + setControlValue(RC_DISPLAY, r_sim65816.get_video_fx()); + setControlValue(RC_TYPE, r_sim65816.get_color_mode()); + setControlValue(RC_SPEED, g_sim65816.get_limit_speed()); + setControlValue(RC_FPS, x_frame_rate); + setControlValue(RC_MOUSE, g_adb.g_warp_pointer); + setControlValue(RC_DISKSOUND, option.getIntValue(OPTION_DISKSOUND)); + setControlValue(RC_AUDIO, option.getIntValue(OPTION_AUDIORATE)); + setControlValue(RC_MEMORY, option.getIntValue(OPTION_MEMORYSIZE)); + setControlValue(RC_KBD, option.getIntValue(OPTION_EXTERNALKBD)); + setControlValue(RC_JOYSTICK, option.getIntValue(OPTION_JOYSTICKMODE)); + +} + +- (void)ctrlChanged:(id)sender +{ + + int i = 0; + while (runtimeControlDefs[i].cid!=RC_END) + { + if (sender == runtimeControlDefs[i].hControl ) + { + int sel = runtimeControlDefs[i].hControl.selectedSegmentIndex; + int v = runtimeControlDefs[i].optionValues[sel]; + //CEmulator* p = CEmulator::theEmulator; + switch(runtimeControlDefs[i].cid) + { + case RC_LOCKZOOM: + option.setIntValue(OPTION_LOCKZOOM,v); + x_lock_zoom = v; + if ( (v==LOCKZOOM_ON) || (v==LOCKZOOM_ARCADE) ) + [[pManager getEmulatorView].contentView enableGestures:MODE_ZOOM]; + else + [[pManager getEmulatorView].contentView disableGestures:MODE_ZOOM]; + break; + case RC_JOYSTICK: + option.setIntValue(OPTION_JOYSTICKMODE,v); + g_joystick_type = v; + break; + case RC_DISPLAY: + // monitor + { + extern void x_set_video_fx(videofxenum _vfx); + option.setIntValue(OPTION_VIDEOFX,v); + x_set_video_fx((videofxenum)v); + } + // [pManager getEmulatorView].zv.crt.hidden = (v==VIDEOFX_CRT?0:1); + break; + case RC_TYPE: + // color + option.setIntValue(OPTION_COLORMODE,v); + break; + case RC_SPEED: + // speed + option.setIntValue(OPTION_SPEED,v); + // g_sim65816.set_limit_speed((speedenum)v); + break; + case RC_FPS: + // frame rate + option.setIntValue(OPTION_FRAMERATE,v); + x_frame_rate = v; + [[pManager getEmulatorView].zv.ew activateEmulatorRefresh:v]; + break; + case RC_MOUSE: + // warp + g_adb.g_warp_pointer = (warpmode)v; + break; + case RC_AUDIO: + // audiorate + option.setIntValue(OPTION_AUDIORATE,v); + break; + case RC_DISKSOUND: + // audiorate + option.setIntValue(OPTION_DISKSOUND,v); + break; + + case RC_MEMORY: + // memorysize + option.setIntValue(OPTION_MEMORYSIZE,v); + break; + case RC_KBD: + // external kbd + option.setIntValue(OPTION_EXTERNALKBD,v); + [self setInputMode:inputMode]; // pour forcer un refresh! + break; + default: + break; + } + option.saveOptions(1); + r_sim65816.request_update_emulator_runtime_config(); + return ; + + } + i++; + } + printf("control not found\n"); + +} +// +-(void)addRuntimeControls +{ + + +// CGSize s = self.view.frame.size; + + + float res = [pManager resolutionRatio]; + float OPTIONWIDTH = 200* res; + float OPTIONMARGIN = 20* res; + float LINEHEIGHT = 20*res; + + + self.runtimeControlsOptions = [[UIView alloc] initWithFrame:CGRectZero]; + self.runtimeControlsOptions.userInteractionEnabled=TRUE; // NOT SET BY DEFAULT ON UIIMAGEVIEW + + int l = 0; + int i=0; + int nbs=0; + while (runtimeControlDefs[i].cid!=RC_END) + { + + + UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(OPTIONMARGIN,l,OPTIONWIDTH,LINEHEIGHT)]; + label.text = [NSString stringWithUTF8String:runtimeControlDefs[i].name]; + label.textAlignment = UITextAlignmentCenter; + label.font = [UIFont systemFontOfSize:12*res]; + label.backgroundColor = [UIColor clearColor]; + [self.runtimeControlsOptions addSubview:label]; + l+=LINEHEIGHT; + + CGRect segrect = CGRectMake(OPTIONMARGIN,l,OPTIONWIDTH,LINEHEIGHT); + UISegmentedControl* seg = [[UISegmentedControl alloc ] initWithFrame:segrect]; + // [seg setSegmentedControlStyle:UISegmentedControlStyleBar]; + const char** nameptr = runtimeControlDefs[i].options; + + int j=0; + while(*nameptr) + { + [seg insertSegmentWithTitle:[NSString stringWithUTF8String:*nameptr] atIndex:j++ animated:FALSE]; + nameptr++; + } + + [seg addTarget:self action:@selector(ctrlChanged:) forControlEvents:UIControlEventValueChanged]; + + runtimeControlDefs[i].hControl = seg; + [self.runtimeControlsOptions addSubview:seg]; + + + l+=LINEHEIGHT; + i++; + nbs++; + + } + + float w = OPTIONWIDTH+OPTIONMARGIN*2; + + // resize la vue correctement + [self.runtimeControlsOptions setFrame:CGRectMake(0,0,w,l)]; + + float ho = nbs*(LINEHEIGHT+OPTIONMARGIN) + (LINEHEIGHT+OPTIONMARGIN) + OPTIONMARGIN*2 ; + if (ho>280*res) + ho = 280*res; + + CGRect r = CGRectMake(0,0,w,ho); + self.runtimeControls = [[UIImageView alloc] initWithFrame:r]; + self.runtimeControls.userInteractionEnabled=TRUE; // NOT SET BY DEFAULT ON UIIMAGEVIEW + self.runtimeControls.alpha = 0.0; + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(nil, (int)r.size.width,(int)r.size.height, 8, (int)r.size.width*4,colorSpace,kCGImageAlphaPremultipliedLast); + + float ovalWidth=14,ovalHeight=14; + CGContextSaveGState(context); + CGContextTranslateCTM (context, CGRectGetMinX(r), CGRectGetMinY(r)); + CGContextScaleCTM (context, ovalWidth, ovalHeight); + float fw = CGRectGetWidth (r) / ovalWidth; + float fh = CGRectGetHeight (r) / ovalHeight; + CGContextMoveToPoint(context, fw, fh/2); + CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); + CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); + CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); + CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); + CGContextClosePath(context); + CGContextRestoreGState(context); + CGContextClip(context); + + const CGFloat* col = CGColorGetComponents( [[UIColor colorWithWhite:1.0 alpha:0.8] CGColor]); + CGContextSetFillColor(context,col); + CGContextFillRect(context,r); + + // TODO RAJOUTER UNE OMBRE + + CGImageRef imageRef = CGBitmapContextCreateImage(context); + UIImage* newImage = [UIImage imageWithCGImage:imageRef]; + self.runtimeControls.image = newImage; + + // cleanup + CGContextRelease(context); + CGColorSpaceRelease(colorSpace); + + const float lb = ho - LINEHEIGHT - OPTIONMARGIN; + const float WB = 50 * res; + + UIButton* button = [UIButton buttonWithType:(UIButtonType)100]; + [button addTarget:self action:@selector(optionsButton:) forControlEvents:UIControlEventTouchUpInside]; + [button setTitle:@"Done" forState:UIControlStateNormal]; + + + + button.frame = CGRectMake((w-WB-OPTIONMARGIN),lb,WB,LINEHEIGHT); + + [self.runtimeControls addSubview:button]; + + UIButton* buttonrestore = [UIButton buttonWithType:(UIButtonType)100]; + [buttonrestore addTarget:self action:@selector(restoreButton:) forControlEvents:UIControlEventTouchUpInside]; + [buttonrestore setTitle:@"Default" forState:UIControlStateNormal]; + + buttonrestore.frame = CGRectMake(OPTIONMARGIN,lb,WB,LINEHEIGHT); + + [self.runtimeControls addSubview:buttonrestore]; + + + + // ajoute le scrollView + + self.uit = [[UIScrollView alloc]initWithFrame:CGRectMake(0,OPTIONMARGIN,w,-OPTIONMARGIN+ho-OPTIONMARGIN-LINEHEIGHT*2)]; + self.uit.userInteractionEnabled=TRUE; // NOT SET BY DEFAULT ON UIIMAGEVIEW + self.uit.showsHorizontalScrollIndicator = NO; + self.uit.showsVerticalScrollIndicator = YES; + self.uit.maximumZoomScale = 1.0; + self.uit.minimumZoomScale = 1.0; + self.uit.contentSize = CGSizeMake(self.runtimeControlsOptions.frame.size.width,self.runtimeControlsOptions.frame.size.height); + [self.uit addSubview:self.runtimeControlsOptions]; + [self.runtimeControls addSubview:self.uit]; + + /* + [[runtimeControls layer] setCornerRadius:8]; + [[runtimeControls layer] setMasksToBounds:NO]; + [[runtimeControls layer] setShadowColor:[UIColor blackColor].CGColor]; + [[runtimeControls layer] setShadowOpacity:1.0f]; + [[runtimeControls layer] setShadowRadius:6.0f]; + [[runtimeControls layer] setShadowOffset:CGSizeMake(0, 3)]; + */ + + [self.view addSubview:self.runtimeControls]; + + +} + + + +-(void)addDiskSelection +{ + + [self.diskSelectionOptions release]; + [self.diskSelection release]; + + self.diskSelectionOptions = nil; + self.diskSelection = nil; + + if (!pMac) + return ; + int swap = pMac->getSmartSwap(); + if (!swap) + return ; + + int slot = swap/10; + int disk = swap%10; + + + // CActiveImage& active = pMac->config->getActiveImage(slot,disk); + + // CGSize s = self.view.frame.size; + + + float res = [pManager resolutionRatio]; + float SELECTIONWIDTH = 200* res; + float OPTIONMARGIN = 10* res; + float LINEHEIGHT = 20*res; + float MOUNTWIDTH = 64*res; + + self.diskSelectionOptions = [[UIView alloc] initWithFrame:CGRectZero]; + self.diskSelectionOptions.userInteractionEnabled=TRUE; // NOT SET BY DEFAULT ON UIIMAGEVIEW + + int l = 0; +// int i=0; + int nbs=0; +// while (runtimeControlDefs[i].cid!=RC_END) + for(int i=0;iconfig->localImages[slot-5][disk-1][i]; + if (info.status==UNDEFINED) + continue ; + UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(OPTIONMARGIN,l,SELECTIONWIDTH-MOUNTWIDTH,LINEHEIGHT)]; + MyString l8; + l8.Format("#%d %s",i,info.shortname); + label.text = [NSString stringWithUTF8String:l8.c_str()]; + NSLog(@"adding %@",label.text); + label.textAlignment = UITextAlignmentLeft; + label.font = [UIFont systemFontOfSize:12*res]; + label.backgroundColor = [UIColor clearColor]; + [self.diskSelectionOptions addSubview:label]; + + if( info.status!=MOUNTED) + { + UIButton* button = [UIButton buttonWithType:(UIButtonType)100]; + button.tag = slot+disk*10+i*100; + [button addTarget:self action:@selector(mountButton:) forControlEvents:UIControlEventTouchUpInside]; + [button setTitle:@"Mount" forState:UIControlStateNormal]; + [button setFrame:CGRectMake(OPTIONMARGIN+SELECTIONWIDTH,l,MOUNTWIDTH,LINEHEIGHT)]; + [self.diskSelectionOptions addSubview:button]; + } + + + + + + nbs++; + l+=LINEHEIGHT; + // i++; + } + + float w = MOUNTWIDTH+SELECTIONWIDTH+OPTIONMARGIN*2; + + // resize la vue correctement + [self.diskSelectionOptions setFrame:CGRectMake(0,0,w,l)]; + + float ho = nbs*(LINEHEIGHT+OPTIONMARGIN) + (LINEHEIGHT+OPTIONMARGIN) + OPTIONMARGIN*2 ; + if (ho>280*res) + ho = 280*res; + + CGRect r = CGRectMake(0,0,w,ho); + self.diskSelection= [[UIImageView alloc] initWithFrame:r]; + self.diskSelection.userInteractionEnabled=TRUE; // NOT SET BY DEFAULT ON UIIMAGEVIEW + self.diskSelection.alpha = 0.0; + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(nil, (int)r.size.width,(int)r.size.height, 8, (int)r.size.width*4,colorSpace,kCGImageAlphaPremultipliedLast); + + float ovalWidth=14,ovalHeight=14; + CGContextSaveGState(context); + CGContextTranslateCTM (context, CGRectGetMinX(r), CGRectGetMinY(r)); + CGContextScaleCTM (context, ovalWidth, ovalHeight); + float fw = CGRectGetWidth (r) / ovalWidth; + float fh = CGRectGetHeight (r) / ovalHeight; + CGContextMoveToPoint(context, fw, fh/2); + CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); + CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); + CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); + CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); + CGContextClosePath(context); + CGContextRestoreGState(context); + CGContextClip(context); + + const CGFloat* col = CGColorGetComponents( [[UIColor colorWithWhite:1.0 alpha:0.8] CGColor]); + CGContextSetFillColor(context,col); + CGContextFillRect(context,r); + + // TODO RAJOUTER UNE OMBRE + + CGImageRef imageRef = CGBitmapContextCreateImage(context); + UIImage* newImage = [UIImage imageWithCGImage:imageRef]; + self.diskSelection.image = newImage; + + // cleanup + CGContextRelease(context); + CGColorSpaceRelease(colorSpace); + + const float lb = ho - LINEHEIGHT - OPTIONMARGIN; + const float WB = 50 * res; + + UIButton* button = [UIButton buttonWithType:(UIButtonType)100]; + [button addTarget:self action:@selector(diskSelectionButton:) forControlEvents:UIControlEventTouchUpInside]; + [button setTitle:@"Close" forState:UIControlStateNormal]; + + + + button.frame = CGRectMake((w-WB-OPTIONMARGIN),lb,WB,LINEHEIGHT); + + [self.diskSelection addSubview:button]; + /* + UIButton* buttonrestore = [UIButton buttonWithType:(UIButtonType)100]; + [buttonrestore addTarget:self action:@selector(restoreButton:) forControlEvents:UIControlEventTouchUpInside]; + [buttonrestore setTitle:@"Default" forState:UIControlStateNormal]; + + buttonrestore.frame = CGRectMake(OPTIONMARGIN,lb,WB,LINEHEIGHT); + + [self.runtimeControls addSubview:buttonrestore]; + */ + + + // ajoute le scrollView + + UIScrollView* sw = [[UIScrollView alloc]initWithFrame:CGRectMake(0,OPTIONMARGIN,w,-OPTIONMARGIN+ho-OPTIONMARGIN-LINEHEIGHT*2)]; + sw.userInteractionEnabled=TRUE; // NOT SET BY DEFAULT ON UIIMAGEVIEW + sw.showsHorizontalScrollIndicator = NO; + sw.showsVerticalScrollIndicator = YES; + sw.maximumZoomScale = 1.0; + sw.minimumZoomScale = 1.0; + sw.contentSize = CGSizeMake(self.diskSelectionOptions.frame.size.width,self.diskSelectionOptions.frame.size.height); + [sw addSubview:self.diskSelectionOptions]; + [self.diskSelection addSubview:sw]; + + /* + [[runtimeControls layer] setCornerRadius:8]; + [[runtimeControls layer] setMasksToBounds:NO]; + [[runtimeControls layer] setShadowColor:[UIColor blackColor].CGColor]; + [[runtimeControls layer] setShadowOpacity:1.0f]; + [[runtimeControls layer] setShadowRadius:6.0f]; + [[runtimeControls layer] setShadowOffset:CGSizeMake(0, 3)]; + */ + + [self.view addSubview:self.diskSelection]; + + +} + + + + +// Ajoute les modifiers au clavier + +-(void)addRuntimeKeys +{ + + if (self.runtimeView) + { + printf("removing RuntimeView"); + [self.runtimeView removeFromSuperview]; + [self.runtimeView release]; + } + + // position par défault + CGRect rv3 = [UIScreen mainScreen].applicationFrame; + + self.runtimeView = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 40, rv3.size.width, 36.0)]; + self.runtimeView.barStyle = UIBarStyleBlack; + self.runtimeView.translucent = TRUE; + + + int pos = 2; + int nbkey = sizeof(runtimeKeysList)/sizeof(rkey); + + for(int i=0;iself.specialView.frame.size.width/2) + { + p.x -= self.specialView.frame.size.width/2; + } + /* + // A UTILISER AVEC BOUNCES=NO : NE MARCHE PAS! + if (p.xgetSmartSwap(); + if (bMenuBarVisibility && sw) + { + rotationAndPerspectiveTransform.m34 = 1.0 / -200; + rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, diskAngle * M_PI / 180.0f, 0.0f, 1.0f, 0.0f); + self.diskView.hidden = false; + } + else + self.diskView.hidden = true; + } + else + self.diskView.hidden = true; + + self.diskView.layer.transform = rotationAndPerspectiveTransform; + diskAngle += 10; + +} + +- (void) keyup:(NSTimer*)theTimer +{ + NSNumber* ui = [theTimer userInfo]; + int c = [ui intValue]; + if (c & shiftKey) + add_event_modifier(0); + add_event_key(c&0xFF,1); + + + if (c!=0x36 && c!=0x37 && c!=0x3a) + [self clearSpecialKeys]; +} + + + +const char* iCadeDetectString="zexwzexw"; +int iCadeDetectPos=0; + +int keypad_x = 0; +int keypad_y = 0; + + +void paddle_trigger_icade(double dcycs) +{ + g_paddles.g_paddle_val[0] = keypad_x; + g_paddles.g_paddle_val[1] = keypad_y; + g_paddles.g_paddle_val[2] = 32767; + g_paddles.g_paddle_val[3] = 32767; + g_moremem.g_paddle_buttons |= 0xc; + paddle_update_trigger_dcycs(dcycs); +} + + +int x_adb_get_keypad_x() +{ + return keypad_x; +} + +int x_adb_get_keypad_y() +{ + return keypad_y; +} + + + + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + const char* s = [string UTF8String]; + // printf("input:%s\n",s); + if (!iCadeDetected || bForceOnScreenKeyboard) + { + if (*s == iCadeDetectString[iCadeDetectPos]) + iCadeDetectPos++; + else + iCadeDetectPos=0; + + if (!iCadeDetectString[iCadeDetectPos]) + { + NSLog(@"icade activated"); + iCadeDetectPos=0; + if (bForceOnScreenKeyboard) + { + [self OnScreenKeyboard:FALSE]; + } + + else + [self setiCadeMode:TRUE]; + return NO; + /* + option.setIntValue(OPTION_JOYSTICKMODE,JOYSTICK_TYPE_ICADE); + [self setInputMode:inputMode&INPUTMODE_PAD]; + [self refreshControls:nil]; + */ + } + } + else + if (!bForceOnScreenKeyboard) + { + + char c; + int i=0; + while( (c = s[i++]) != 0) + { + switch(c) + { + case 'z': // up + keypad_y = -32767; + break; + case 'e': + case 'w': // !verti + keypad_y = 0; + break; + case 'x': // down + keypad_y = 32767; + break; + case 'q': // left + keypad_x = -32767; + break; + case 'a': // !hori + case 'c': + keypad_x = 0; + break; + case 'd': // right + keypad_x = 32767; + break; + case 'y': // button 1 pressed + add_event_key(0x37, 0); + break; + case 't': // button 1 depressed + add_event_key(0x37, 1); + break; + case 'h': // button 2 pressed + add_event_key(0x3a, 0); + break; + case 'r': // button 2 depressed + add_event_key(0x3a, 1); + break; + case 'g': //à faire sur un keydepressed + // display keyboard + printf("*** forcing on-screeen keyboard"); + [self OnScreenKeyboard:TRUE]; + break; + case 'v': //à faire sur un keydepressed + // toggle la menu bar + [self setMenuBarVisibility:!bMenuBarVisibility]; + break; + default: + break; + } + + } + return NO; // + + } + + if (!*s) + s = "delete"; + else + if (!strcmp(s,"\n")) + s = "return"; + + + + int c = findCode(s); + debug_printf("text: %s code:%d\n",s,c); + if (c>=0) + { + if (c & shiftKey) + add_event_modifier(shiftKey); + add_event_key(c&0xFF,0); + NSNumber* ui = [[NSNumber alloc ]initWithInt:c]; + [NSTimer scheduledTimerWithTimeInterval:1.0/20.0 target:self selector:@selector(keyup:) userInfo:ui repeats:NO]; + } + + return NO; +} + + +- (BOOL) myTouchesBegan:(NSSet *)touches +{ + + UITouch* touch =[touches anyObject]; + CGPoint p = [touch locationInView:self.view]; + CGRect r = self.diskView.frame; + if (CGRectContainsPoint(r,p) && pMac->getSmartSwap() && !bLoading) + { + // [self swapButton:self]; + [self addDiskSelection]; + [self diskSelectionButton:self]; + + } + +#ifdef ACTIVEGS_CUSTOMKEYS + if (inputMode & INPUTMODE_CUSTOMKEYS) + touch_begin_custom_key(p); +#endif + + if (!padEnabled || !([self isInputVisible:INPUTMODE_PAD])) + return FALSE; + + // regarde si on touche le pad + CGRect ro = self.padCircleOutter.frame; + if (CGRectContainsPoint(ro,p) && !self.padTouch) + { + self.padTouch = touch; + posPad = [touch locationInView:self.view]; + self.padCircleInner.alpha = 1.0; + } + + // ca button + CGRect ca = self.caButtonView.frame; + if (CGRectContainsPoint(ca,p) && !self.caButtonTouch) + { + add_event_key(0x3A, 0); + + for(int i=0;i<20;i++) + add_event_delay(); + caButton = TRUE; + self.caButtonTouch = [touch retain];; + self.caButtonView.alpha = 1.0; +#ifdef GRAPHICAL_PAD + self.padButton2Down.hidden = FALSE; +#endif + + } + + // oa button + CGRect oa = self.oaButtonView.frame; + if (CGRectContainsPoint(oa,p) && !self.oaButtonTouch) + { + add_event_key(0x37, 0); + for(int i=0;i<20;i++) + add_event_delay(); + oaButton = TRUE; + self.oaButtonTouch = touch; + self.oaButtonView.alpha = 1.0; +#ifdef GRAPHICAL_PAD + self.padButton1Down.hidden = FALSE; +#endif + + } + + + + return self.padTouch || caButton || oaButton ; +} + +-(void)centerPad:(id)center +{ +#define CENTER_STEP 0.01 + + if (joyX == 0.0 && joyY == 0.0) return ; + if (joyX < 0) joyX+=CENTER_STEP; + if (joyX > 0) joyX-=CENTER_STEP; + if (joyY < 0) joyY+=CENTER_STEP; + if (joyY > 0) joyY-=CENTER_STEP; + if (abs(joyX)1.0) joyX=1.0; + if (joyY<-1.0) joyY=-1.0; + if (joyY>1.0) joyY=1.0; + posPad = newpos; + [self updatePadView]; + } + + return self.padTouch || caButton || oaButton ; + +} + +- (void)notifyPaddle:(id)sender +{ + if (x_lock_zoom == LOCKZOOM_ARCADE) + [self setInputMode:(INPUTMODE_ARCADE + INPUTMODE_PAD)]; + else + [self setInputMode:(INPUTMODE_PAD + INPUTMODE_MINIACCESS)]; +} + + +-(void)setInputMode:(int)_mode +{ + + debug_printf("setting inputMode to : %X (was:%X)\n",_mode,inputMode); + inputMode = _mode; + + if ([self isInputVisible:INPUTMODE_PAD]) + padEnabled = TRUE; + + + BOOL b = [self.textField isFirstResponder]; + if ([self isInputVisible:INPUTMODE_KBD] || isHardwareKeyboard() /*(inputMode & INPUTMODE_HARDWAREKBD)*/) + { + if (isHardwareKeyboard()) + debug_printf("*enabling HW keyboard\n"); + else + debug_printf("*enabling keyboard\n"); + + // A faire avant le becomeFirstResponder + + debug_printf("setInputAccessoryView:accessView"); + // IOS8 + [self.accessView removeFromSuperview]; + [self.textField setInputAccessoryView:self.accessView]; + + [self.textField becomeFirstResponder]; + } + else + { + if (b) + [self.textField resignFirstResponder]; + + debug_printf("setInputAccessoryView:nil"); + [self.textField setInputAccessoryView:nil]; + + debug_printf("addSubview:accessView"); + [self.interfaceView addSubview:self.accessView]; + + } + + + [[pManager getEmulatorView] updateView]; + +} + +-(void)showDebug:(BOOL)_visible +{ + + self.debugIndicator.hidden = !_visible; + self.swipeIndicator.hidden = !_visible; + self.zoomIndicator.hidden = !_visible; + self.padIndicator.hidden = !_visible; + self.mouseButtonIndicator.hidden = !_visible; + self.inputIndicator.hidden = !_visible; +} + + +-(void)setDebugIndicatorText:(const char*)_text +{ + NSString* str = [NSString stringWithUTF8String:_text]; + self.debugIndicator.text = str; +} + + +const int cycles[]= +{ + + INPUTMODE_PAD+INPUTMODE_MINIACCESS, + INPUTMODE_ACCESS, + INPUTMODE_KBD+INPUTMODE_ACCESS, + INPUTMODE_ACCESS+INPUTMODE_PAD +#ifdef ACTIVEGS_CUSTOMKEYS + ,INPUTMODE_CUSTOMKEYS +#endif +}; + + +- (void)swipeDown +{ + debug_printf("swipeDown"); + + + if ( !(inputMode & INPUTMODE_ARCADE) && [self isInputVisible:INPUTMODE_ALL] ) + { + [self hideInput]; + return ; + } + + if (!bMenuBarVisibility) + { + debug_printf("*displaying menubar\n"); + [self setMenuBarVisibility:TRUE]; + [self showDebug:FALSE]; + + } + else + { + if (option.getIntValue(OPTION_DEBUGMODE)) + [self showDebug:TRUE]; + } + + +} + +- (void)swipeUp +{ + + debug_printf("swipeUp"); + + // si la barre est cachée, fait la apparaitre + + if (bMenuBarVisibility) + { + debug_printf("*hidding menubar\n"); + [self setMenuBarVisibility:FALSE]; + return; + } + + // en mode arcade, on ne peut pas cycler dans les interfaces + + if (inputMode & (INPUTMODE_CUSTOMKEYS | INPUTMODE_ARCADE)) + return ; + + // si l'interface était cachée, fait la réapparaitre + + if (inputMode & INPUTMODE_HIDDEN) + { + [self setInputMode:inputMode &~INPUTMODE_HIDDEN]; + return ; + } + + // sinon, cycle dans les interfaces de saisies + [self cycleInput]; + +} + + +-(void)cycleInput +{ + + + const int nbcycle = sizeof(cycles)/sizeof(int); + int m = cycles[0] ; // default value + for(int i =0;i ACCESS_HEIGHT) + { + // Bug! + printf("resizing keyboard to compensate bug in UIKeyboardFrameEndUserInfoKey\n"); + + // + if (bForceOnScreenKeyboard) + { + // on-screen keyboard has been dismissed + printf("on-screen keyboard has been dismissed..."); + [self OnScreenKeyboard:FALSE]; + } + + [self updateViewForKeyboard:deltaY]; + } + else + { +// A ELIMINER QD ON POURRA DETECTER LES CLAVIERS HARDWARE AVEC LE SDK +#ifdef ACTIVEGS_NOHARDWAREKEYBOARDDETECTION + if (keyboardDelta.size.height) + { + if (option.getIntValue(OPTION_EXTERNALKBD)) + { + printf("*** reverting option ***"); + option.setIntValue(OPTION_EXTERNALKBD,0); + option.saveOptions(1); + x_refresh_panel(PANEL_RUNTIME); + [self setInputMode:inputMode]; // pour forcer un refresh! + x_alert("No external keyboard detected! Disabling option."); + } + } +#endif + } + + + +} + +- (void)updateViewForKeyboard:(int)_height +{ + + + BOOL isPortrait = abs([pManager getAngle])==90 ; + + keyboardDelta.origin.x = 0; + keyboardDelta.origin.y = 0; + keyboardDelta.size.width = 0; + keyboardDelta.size.height = _height; + if (isPortrait) + keyboardScale = 1; + else + { + float h = self.view.bounds.size.width ; + keyboardScale = (h - _height) / h ; + } + debug_printf("updateViewForKeyboard: h:%d s:%f",_height,keyboardScale); + [[pManager getEmulatorView] updateView]; + +} + +- (void) keyboardWillShow:(NSNotification*)aNotification +{ + debug_printf("keyboardWillShow\n"); + + CGFloat _keyboardHeight; + CGRect _keyboardEndFrame; + BOOL isPortrait = abs([pManager getAngle])==90 ; + + + NSDictionary *info = [aNotification userInfo]; + [[info valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardEndFrame]; + + if (isPortrait) + _keyboardHeight = _keyboardEndFrame.size.height; + else + _keyboardHeight = _keyboardEndFrame.size.width; + + // enleve l'accessory + _keyboardHeight -= self.specialView.frame.size.height; + + + debug_printf("keyboardheight:%f\n", _keyboardHeight); + [self updateViewForKeyboard:_keyboardHeight]; + +} + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + + +- (void)menuButton:(id)sender +{ + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromLeft]; + +} + + + +- (void)mountButton:(UIButton*)sender + { + int i = sender.tag; + int active = i / 100; + int disk = (i - active*100)/10; + int slot = (i - active*100)%10; + + pMac->swapDisk(slot,disk,active); + [self diskSelectionButton:self]; // pour fermer la fenetre + + + } + /* +- (void)swapButton:(id)sender +{ + NSString* str = nil; + int sw = pMac->getSmartSwap(); + if (!sw) + str = @"Nothing to swap"; + else + { + pMac->smartSwap(); + CSlotInfo& info =pMac->getLocalIMGInfo(sw/10,sw%10); + + MyString s; + s.Format("Disk %s inserted",info.shortname.c_str()); + str = [NSString stringWithUTF8String: s.c_str()]; + } + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"ActiveGS" message:str delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil] autorelease]; + [alert show]; + +} + */ + + +- (void)setEmulatorTitle:(const char*)_name +{ + printf("setEmulatorTitle:%s",_name); + if (_name && *_name) + { + NSString* str = [NSString stringWithUTF8String: _name]; + [self.emulatorNavItem setTitle:str]; + } +} + +- (void)restoreButton:(id)sender +{ + //CEmulator* p = CEmulator::theEmulator; + option.setDefaultOptions(); + option.saveOptions(1); + [self refreshControls:nil]; +} + +-(void)enableKeyboard:(int)_enable +{ + if (_enable) + inputMode |= INPUTMODE_KBD; + else + inputMode &= ~INPUTMODE_KBD; + [self setInputMode:inputMode]; + +} + +-(int)isInputVisible:(int) _im +{ + if (inputMode & INPUTMODE_HIDDEN) + return 0; + return inputMode & _im; +} + +-(void)restoreInput +{ + [self setInputMode:inputMode & ~INPUTMODE_KBD]; +} + + +-(void)hideInput +{ + [self setInputMode:inputMode | INPUTMODE_HIDDEN]; +} + +- (void)optionsButton:(id)sender +{ + + // vire le clavier + /* + if ([self isInputVisible:INPUTMODE_KBD]) + [self hideInput]; + */ + // [self enableKeyboard:FALSE]; + [self restoreInput]; + + + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.3]; + float a = self.runtimeControls.alpha; + if (a==1.0) + a=0.0; + else + { + [self.uit flashScrollIndicators]; + a=1.0; + } + self.runtimeControls.alpha = a; + + self.runtimeControls.hidden = NO; + [UIView commitAnimations]; +} + +- (void)diskSelectionButton:(id)sender +{ + + + [self restoreInput]; + + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.3]; + float a = self.diskSelection.alpha; + if (a==1.0) + a=0.0; + else + { + // [self.uit flashScrollIndicators]; + a=1.0; + } + self.diskSelection.alpha = a; + + self.diskSelection.hidden = NO; + [UIView commitAnimations]; +} + + + + +- (void)dealloc +{ + + NSLog(@"---kbd dealloc"); + self.textField.delegate = nil; + self.textField = nil; + self.menuButton = nil; + self.optionButton = nil; + self.diskView = nil; + self.diskLoadingView = nil; + self.loaderLabel = nil; + self.debugIndicator = nil; + self.swipeIndicator = nil; + self.zoomIndicator = nil; + self.padIndicator = nil; + self.mouseButtonIndicator = nil; + self.inputIndicator = nil; + self.loader = nil; + self.padCircleOutter = nil; + self.padCircleInner = nil; + self.oaButtonView = nil; + self.caButtonView = nil; + self.emulatorNavItem = nil; + self.barView = nil; + self.hardwarekbdDetectionTimer = nil; + self.animateDiskTimer = nil; + + + [super dealloc]; + +} + + +@end + diff --git a/Common.iphone/MainWindow-iPad.xib b/Common.iphone/MainWindow-iPad.xib new file mode 100644 index 0000000..7a103b9 --- /dev/null +++ b/Common.iphone/MainWindow-iPad.xib @@ -0,0 +1,226 @@ + + + + 1056 + 10F569 + 823 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 132 + + + YES + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBIPadFramework + + + IBFirstResponder + IBIPadFramework + + + IBIPadFramework + + + + 292 + {768, 1024} + + 1 + MC4wMDUxMDIwNDA4MTYgMC4wMDUxMDIwNDA4MTYgMC4wMDUxMDIwNDA4MTYAA + + NO + NO + IBIPadFramework + YES + + + + + YES + + + delegate + + + + 4 + + + + window + + + + 15 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + activegs App Delegate + + + -2 + + + + + 12 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + activegsAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 16 + + + + YES + + UIView + + IBProjectSource + ../Common.iphone/GTMUIView+SubtreeDescription.h + + + + activegsAppDelegate + NSObject + + window + UIWindow + + + window + + window + UIWindow + + + + IBProjectSource + ../Common.iphone/activegsAppDelegate.h + + + + activegsAppDelegate + NSObject + + IBUserSource + + + + + + YES + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + + 0 + IBIPadFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ../activegs_iphone2/activegs.xcodeproj + 3 + 132 + + diff --git a/Common.iphone/MainWindow.xib b/Common.iphone/MainWindow.xib new file mode 100644 index 0000000..64c1587 --- /dev/null +++ b/Common.iphone/MainWindow.xib @@ -0,0 +1,418 @@ + + + + 1024 + 10F569 + 788 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 117 + + + YES + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + + 292 + {320, 480} + + + + 1 + MC4wMDUxMDIwNDA4MTYgMC4wMDUxMDIwNDA4MTYgMC4wMDUxMDIwNDA4MTYAA + + NO + NO + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + + + YES + + + delegate + + + + 4 + + + + window + + + + 15 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + 3 + + + activegs App Delegate + + + -2 + + + + + 12 + + + + + 16 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 12.IBEditorWindowLastContentRect + 12.IBPluginDependency + 16.CustomClassName + 16.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + {{525, 346}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + activegsAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + activegsAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 16 + + + + YES + + UIView + + IBProjectSource + ../Common.iphone/GTMUIView+SubtreeDescription.h + + + + activegsAppDelegate + NSObject + + window + UIWindow + + + window + + window + UIWindow + + + + IBProjectSource + ../Common.iphone/activegsAppDelegate.h + + + + activegsAppDelegate + NSObject + + IBUserSource + + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ../ActiveBestOfFTA/activebestoffta.xcodeproj + 3 + 117 + + diff --git a/Common.iphone/Tab2GS.png b/Common.iphone/Tab2GS.png new file mode 100644 index 0000000..28bd373 Binary files /dev/null and b/Common.iphone/Tab2GS.png differ diff --git a/Common.iphone/Tab2GS@2x.png b/Common.iphone/Tab2GS@2x.png new file mode 100644 index 0000000..7285f0e Binary files /dev/null and b/Common.iphone/Tab2GS@2x.png differ diff --git a/Common.iphone/Tab2_32.png b/Common.iphone/Tab2_32.png new file mode 100644 index 0000000..570d9ec Binary files /dev/null and b/Common.iphone/Tab2_32.png differ diff --git a/Common.iphone/TabFTA.png b/Common.iphone/TabFTA.png new file mode 100644 index 0000000..164dd78 Binary files /dev/null and b/Common.iphone/TabFTA.png differ diff --git a/Common.iphone/TabFTA@2x.png b/Common.iphone/TabFTA@2x.png new file mode 100644 index 0000000..31d599b Binary files /dev/null and b/Common.iphone/TabFTA@2x.png differ diff --git a/Common.iphone/TabFTA_32.png b/Common.iphone/TabFTA_32.png new file mode 100644 index 0000000..e693578 Binary files /dev/null and b/Common.iphone/TabFTA_32.png differ diff --git a/Common.iphone/Tab][.png b/Common.iphone/Tab][.png new file mode 100644 index 0000000..800dc9b Binary files /dev/null and b/Common.iphone/Tab][.png differ diff --git a/Common.iphone/Tab][@2x.png b/Common.iphone/Tab][@2x.png new file mode 100644 index 0000000..83168f1 Binary files /dev/null and b/Common.iphone/Tab][@2x.png differ diff --git a/Common.iphone/UICustomKey.h b/Common.iphone/UICustomKey.h new file mode 100644 index 0000000..8bc6531 --- /dev/null +++ b/Common.iphone/UICustomKey.h @@ -0,0 +1,79 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + + + +enum enum_key_type +{ + KEYTYPE_KEYBOARD=66, + KEYTYPE_BUTTON + +}; + +enum custom_align +{ + LEFT_ALIGN = 0x100, + RIGHT_ALIGN =0x200, + SAME_LINE = 0x400, + SAME_COL = 0x800, + TOP_ALIGN = 0x1000, + BOTTOM_ALIGN = 0x2000, + BOTTOM_BORDER=0x4000, + LEFT_BORDER=0x8000, + RIGHT_BORDER =0x10000, + VERTICAL_CENTER = 0x20000, + LEFTCENTER_ALIGN = 0x40000, + MIDDLE_BOTTOM = 0x80000 + + +}; + +struct key_type +{ + enum enum_key_type type; + NSString* str; + int code; + + int status; + int halign; + int valign; + int mode; + int vfactor; + int hfactor; + UILabel* view; + UIColor* bgcolor_off; + UIColor* bgcolor_on; + UIColor* bgcolor_over; + key_type() + { + mode = 0; + bgcolor_on = [UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:0.5f]; + bgcolor_off = [UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:0.0f]; + bgcolor_over = [UIColor colorWithRed:0.8f green:0.8f blue:0.8f alpha:0.5f]; + vfactor=1; + hfactor=1; + }; +} ; + +#define MAX_CUSTOM_KEYS 32 +extern key_type custom_keys[MAX_CUSTOM_KEYS]; +extern void show_custom_keys(CGRect _rv, int _mode,int _centery); +//extern void hide_custom_keys(); +extern void fade_custom_keys(float _alpha); +extern void init_custom_keys(); + +extern void touch_begin_custom_key(CGPoint p,int nbtap); +extern void touch_end_custom_key(); +extern void toggle_custom_keys(int _mode, int _hide); + +extern float CUSTOM_KEY_WIDTH ; +extern float CUSTOM_KEY_HEIGHT ; + +@interface UICustomKey : UIView + +@end diff --git a/Common.iphone/UICustomKey.mm b/Common.iphone/UICustomKey.mm new file mode 100644 index 0000000..ca23d11 --- /dev/null +++ b/Common.iphone/UICustomKey.mm @@ -0,0 +1,370 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "activegsAppDelegate.h" +#include"../ActiveGS_Karateka/KaratekaKBDController.h" +#import "UICustomKey.h" + + + +@implementation UICustomKey + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + // Initialization code + } + return self; +} + + +@end + +#define CUSTOM_KEY_WIDTH_DEFAULT 64.0f +#define CUSTOM_KEY_HEIGHT_DEFAULT 64.0f + +float CUSTOM_KEY_WIDTH ; +float CUSTOM_KEY_HEIGHT ; + +int nb_custom_keys = 0; +key_type custom_keys[MAX_CUSTOM_KEYS]; + + +void init_custom_keys() +{ + custom_keys[0].mode = INPUTMODE_LEFTRIGHTKEY; + custom_keys[0].str = @"←"; + custom_keys[0].code = 0x3B; + custom_keys[0].halign = LEFT_BORDER ; + // custom_keys[0].valign = MIDDLE_BOTTOM+ 3 ; + custom_keys[0].valign = SAME_LINE + 4 ; + custom_keys[0].hfactor = 1 ; + + + + custom_keys[1].mode = INPUTMODE_LEFTRIGHTKEY; + custom_keys[1].str = @"→"; + custom_keys[1].code = 0x3C; + custom_keys[1].halign = LEFT_ALIGN + 0; + custom_keys[1].valign = SAME_LINE + 0; + custom_keys[1].hfactor = 1 ; + + custom_keys[8].mode = INPUTMODE_LEFTRIGHTKEY; + custom_keys[8].str = @"SPC"; + custom_keys[8].code = 0x31; + custom_keys[8].halign = LEFT_BORDER /*LEFTCENTER_ALIGN*/ + 0; + custom_keys[8].valign = TOP_ALIGN + 0; + // custom_keys[8].valign = BOTTOM_ALIGN + 0; + custom_keys[8].hfactor = 2 ; + + + + custom_keys[2].mode = INPUTMODE_PUNCHKEY + INPUTMODE_PUNCHLEFTRIGHT; + custom_keys[2].str = @"W"; //@"Q"; + custom_keys[2].halign = RIGHT_ALIGN + RIGHT_BORDER; + custom_keys[2].valign = TOP_ALIGN + 3; + custom_keys[2].code = 0x0D; //0x0C; + + custom_keys[3].mode = INPUTMODE_PUNCHKEY + INPUTMODE_PUNCHLEFTRIGHT; + custom_keys[3].str = @"S"; //@"A"; + custom_keys[3].halign = RIGHT_ALIGN + RIGHT_BORDER; + custom_keys[3].valign = VERTICAL_CENTER; + custom_keys[3].code = 0x01; //0x00; + + custom_keys[4].mode = INPUTMODE_PUNCHKEY + INPUTMODE_PUNCHLEFTRIGHT; + custom_keys[4].str = @"X"; //@"Z"; + custom_keys[4].halign = RIGHT_ALIGN + RIGHT_BORDER; + custom_keys[4].valign = BOTTOM_ALIGN +3; + custom_keys[4].code = 0x07; //0x06; + + custom_keys[5].mode = INPUTMODE_PUNCHKEY ; + custom_keys[5].str = @"Q"; //@"W"; + custom_keys[5].code = 0x0C; //0x0D; + custom_keys[5].halign = RIGHT_ALIGN + 2; + custom_keys[5].valign = SAME_LINE + 2; + + + custom_keys[6].mode = INPUTMODE_PUNCHKEY ; + custom_keys[6].str = @"A"; //@"S"; + custom_keys[6].code = 0x00; //0x01; + custom_keys[6].halign = SAME_COL + 5; + custom_keys[6].valign = BOTTOM_ALIGN + 5; + + + custom_keys[7].mode = INPUTMODE_PUNCHKEY ; + custom_keys[7].str = @"Z"; //@"X"; + custom_keys[7].code = 0x06; //0x07; + custom_keys[7].halign = SAME_COL + 6; + custom_keys[7].valign = BOTTOM_ALIGN + 6; + + custom_keys[9].mode = INPUTMODE_SPACEKEY ; + custom_keys[9].str = @"SPC"; + custom_keys[9].code = 0x31; + custom_keys[9].halign = RIGHT_ALIGN + RIGHT_BORDER; + custom_keys[9].valign = VERTICAL_CENTER; + custom_keys[9].vfactor = 2; + custom_keys[9].hfactor = 2; + + custom_keys[10].mode = INPUTMODE_PUNCHLEFTRIGHT ; + custom_keys[10].str = @"W"; + custom_keys[10].code = 0x0D; + custom_keys[10].halign = LEFT_ALIGN + LEFT_BORDER; + custom_keys[10].valign = SAME_LINE + 2; + + + custom_keys[11].mode = INPUTMODE_PUNCHLEFTRIGHT ; + custom_keys[11].str = @"S"; + custom_keys[11].code = 0x01; + custom_keys[11].halign = LEFT_ALIGN + LEFT_BORDER; + custom_keys[11].valign = BOTTOM_ALIGN + 5; + + + custom_keys[12].mode = INPUTMODE_PUNCHLEFTRIGHT ; + custom_keys[12].str = @"X"; + custom_keys[12].code = 0x07; + custom_keys[12].halign = LEFT_ALIGN + LEFT_BORDER; + custom_keys[12].valign = BOTTOM_ALIGN + 6; + + nb_custom_keys = 13; + + float res = [pManager resolutionRatio]; + CUSTOM_KEY_HEIGHT = CUSTOM_KEY_HEIGHT_DEFAULT*res; + CUSTOM_KEY_WIDTH = CUSTOM_KEY_WIDTH_DEFAULT*res; + + + for (int i=0;ix:%f, y:%f",i,refx,refy); + [v setFrame:r]; + } + + done = 0; + } + } + while (!done); + +} diff --git a/Common.iphone/activegsAppDelegate.h b/Common.iphone/activegsAppDelegate.h new file mode 100644 index 0000000..99a13bd --- /dev/null +++ b/Common.iphone/activegsAppDelegate.h @@ -0,0 +1,181 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#import +#import +#include "../Common.osx/CEmulatorCtrlMac.h" + +#define IPHONETHUMB "thumb" + +#ifdef USE_CAPPTAIN +#import "../Libraries/CapptainSDK/Headers/CapptainAgent.h" +#import "../Libraries/CapptainSDK/Headers/CapptainViewController.h" + #define UIVIEWCONTROLLERROOT CapptainViewController +#else + #define UIVIEWCONTROLLERROOT UIViewController +#endif + +@interface ActiveGSBaseViewController : UIViewController +{ + +} + +//- (void) update; +@end + + +//#import "activegsList.h" +#import "activegsEmulatorController.h" + + +//#import "activegsViewController.h" +#import "infoViewController.h" +#import "detailViewController.h" + +#ifdef USE_GOOGLEANALYTICS +#import "../Libraries/GoogleAnalytics/GAI.h" +#endif + + +#import "activeGSViewController.h" +#define ACTIVEGS_LAUNCHVIEWCONTROLLER activegsViewController + +#ifdef BESTOFFTA +#define ACTIVEGS_TITLE "ActiveGS - Best Of FTA" +#define ACTIVEGS_CAPPTAINAPP "act384142" +#define ACTIVEGS_CAPPTAINKEY "376e71d41db2422c88e1486a8a31e25b" +#define ACTIVEGS_BACKGROUNDIMAGE "Default" +#define ACTIVEGS_FIRSTTABLIST "list" +#define ACTIVEGS_FIRSTTABTITLE "Best Of FTA" +#define ACTIVEGS_FIRSTTABTRACKER "BestOfFta" +#define ACTIVEGS_FIRSTTABICON "BestOfFta" +#define ACTIVEGS_SINGLETAB // Une seule liste sera affichée +#define ACTIVEGS_IMAGEREQUIRED // On ne peut pas lancer l'émulateur sans image +#define ACTIVEGS_NOAPPLEBRANDING // Eliminer les logos Apple 2 & Apple 2GS +#define ACTIVEGS_NOHARDWAREKEYBOARDETECTION // Pour passer la soumission Appstore +#define ACTIVEGS_NOTIFICATION +#define HANDLE_URL + +#elif ACTIVEGSKARATEKA +#error unsupported + +#elif BESTOF +#define ACTIVEGS_TITLE "ActiveGS - BestOf" +#define ACTIVEGS_CAPPTAINAPP "act037442" +#define ACTIVEGS_CAPPTAINKEY "881708d1abb44dbb97fcb0620b3f4ef0" +#define ACTIVEGS_BACKGROUNDIMAGE "karatekalaunch" +#define ACTIVEGS_FIRSTTABLIST "bestof" +#define ACTIVEGS_FIRSTTABTITLE "Jordan's" +#define ACTIVEGS_FIRSTTABICON "Tab2GS" +#define ACTIVEGS_FIRSTTABTRACKER "JM" + +#else +// Default ACTIVEGS +#define ACTIVEGS_TITLE "ActiveGS" +#define ACTIVEGS_CAPTAINAPP "act651309" +#define ACTIVEGS_CAPTAINKEY "26ae7a388bf74c8c993d78bebb63fc41" +#undef ACTIVEGS_BACKGROUNDIMAGE +#define ACTIVEGS_ENABLE_DOCUMENT +#define ACTIVEGS_NOTIFICATION +//#define ACTIVEGS_MANUAL_ROM +#define ACTIVEGS_SAVELASTTAB +#define ACTIVEGS_FIRSTTABLIST "list" +#define ACTIVEGS_FIRSTTABTITLE "Best Of FTA" +#define ACTIVEGS_FIRSTTABTRACKER "BestOfFta" +#define ACTIVEGS_FIRSTTABICON "TabFTA" +#define HANDLE_URL +#define ACTIVEGS_NOHARDWAREKEYBOARDETECTION // Pour passer la soumission Appstore + +#endif + + +#define BARVIEW_HEIGHT 44 + +//extern UIView* backgroundView; +//extern UIImageView* backgroundImageView; + +extern CEmulatorMac* pMac; +extern CEmulatorConfig config; + +enum machineSpecsEnum +{ + SPEC_DEFAULT=0, + FPS_60HZ = 1, + AUDIO_44KHZ = 2 +}; + +extern enum machineSpecsEnum machineSpecs; + +@interface activegsAppDelegate : NSObject { + UIWindow *_window; + UIWindow *_secondaryWindow; + + UILabel* _notificationView; + UIViewController* _primaryViewController ; + UIViewController* _secondaryViewController ; + UIView* _backgroundView; + UIImageView* _backgroundImageView ; + + + //controllers + activegsEmulatorController* _emulatorController; + ACTIVEGS_LAUNCHVIEWCONTROLLER* _viewController; + infoViewController* _infoController; + detailViewController* _detailController ; + float _currentRawReading; + float _dpiRatio ; + float _resolutionRatio; + NSTimer* _notificationTimer; + UIScreen* _secondaryScreen; + UIScreen* _primaryScreen; + UIDeviceOrientation curOrientation; +@public + MyString firstTabXML; +#ifdef USE_GOOGLEANALYTICS + id GAITrackerActiveGS; +#endif + +} + + +- (void) screenDidConnect:(NSNotification *)notification; +-(void) initSecondaryScreen:(UIScreen*) _screen; +-(bool) hasSecondary; +-(void)setSecondaryInputMode; + + +- (void) doStateChange:(UIViewController*)_viewController type:(NSString*)_type sens:(NSString*)_sens; +-(void)launchDiskImage:(ActiveGSElement*)_element pathname:(const char*)_pathname trackername:(const char*)_trackername; +- (void) didRotate:(NSNotification *)notification; +-(void)firstLaunch:(NSTimer*)timer; +-(void)setNotificationText:(NSString*) _text; +-(void)updateNotificationView:(CGRect) newRect; +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; +@property(nonatomic,retain,getter=getEmulatorView) activegsEmulatorController* emulatorController; +@property(nonatomic,retain,getter=getBrowserView) ACTIVEGS_LAUNCHVIEWCONTROLLER* viewController; +@property(nonatomic,retain,getter=getInfoView) infoViewController* infoController; +@property(nonatomic,retain,getter=getDetailView) detailViewController* detailController; +@property(nonatomic,retain) UIViewController* primaryViewController; +@property(nonatomic,retain) UIViewController* secondaryViewController; +@property(nonatomic,retain) UIView* backgroundView; +@property(nonatomic,retain) UIImageView* backgroundImageView ; +@property(nonatomic,retain) UIScreen* secondaryScreen ; +@property(nonatomic,retain) UIScreen* primaryScreen ; + +@property(nonatomic,retain) NSTimer* notificationTimer; +@property(nonatomic,retain) UILabel* notificationView; +@property(assign,getter=getAngle) float currentRawReading; +@property (nonatomic, retain)/* IBOutlet*/ UIWindow *window; +@property (nonatomic, retain) UIWindow *secondaryWindow; +@property(assign) float dpiRatio; +@property(assign) float resolutionRatio; + +@end + + +extern activegsAppDelegate* pManager; diff --git a/Common.iphone/activegsAppDelegate.mm b/Common.iphone/activegsAppDelegate.mm new file mode 100644 index 0000000..51e5ec9 --- /dev/null +++ b/Common.iphone/activegsAppDelegate.mm @@ -0,0 +1,902 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "activegsAppDelegate.h" +#include "../Common/svnversion.h" +#include "../Kegs/Src/adb.h" +#include "../Kegs/Src/sim65816.h" +#include "../Kegs/Src/driver.h" +#include "../Common/ki.h" +#import +#include "asynccommand.h" +#import + +// Application Singleton +activegsAppDelegate* pManager = nil; + +//int runningOnIOS_3_2 = 0; +enum machineSpecsEnum machineSpecs = SPEC_DEFAULT; + +CEmulatorMac* pMac = NULL; +CEmulatorConfig config; + + +#ifdef _DEBUG +// #define TEST_HANDLE_URL +#endif + +#define ENABLE_AIRPLAY + +MyString resourcesPath; + +int padAlreadyDisplayedOnce = 0; + + +// mets à jour le framerate +extern char estimatedSpeed[256]; +extern int getFrameRate(int _id); +void x_update_framerate() +{ + char str[256]; + sprintf(str,"req:%d fps:%d speed:%s",getFrameRate(1),getFrameRate(0),estimatedSpeed); + [[pManager getEmulatorView].kbdc setDebugIndicatorText:str]; +} + + + +void activegs_apply_default_options(void* _config) +{ + namevalue* options = ((COption*)_config)->options; + + if (machineSpecs & FPS_60HZ) + options[OPTION_FRAMERATE].intvalue = 60; + else + options[OPTION_FRAMERATE].intvalue = 20; + + + if (machineSpecs & AUDIO_44KHZ) + options[OPTION_AUDIORATE].intvalue = 44100; + else + options[OPTION_AUDIORATE].intvalue = 22050; + +} + + +void x_notify_eject() +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + [[pManager getEmulatorView].kbdc performSelectorOnMainThread:@selector(animateDiskEjection:) withObject:nil waitUntilDone:NO]; + [pool release]; + +} + +void x_set_video_fx(videofxenum _vfx) +{ + [pManager getEmulatorView].zv.crt.hidden = (_vfx==VIDEOFX_CRT?0:1); +} + + +void x_notify_paddle(int _on) +{ + + // only once per view + if (padAlreadyDisplayedOnce) + return; + + printf("x_notify_paddle"); + padAlreadyDisplayedOnce = 1; + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + [[pManager getEmulatorView].kbdc performSelectorOnMainThread:@selector(notifyPaddle:) withObject:nil waitUntilDone:NO]; + [pool release]; + +} + + +void x_notify_download_failure(const char*_url) +{ + printf("download failed : %s\n",_url); + x_display_alert(0,"Downloading Failed" ,"Check your Internet Connection!"); +} + +void x_loadinginprogress(int _on,int _s,int _d) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + + _d --; + int param = (_s==5 ? _d : _d +2 ); + if (_on) param |= 0x80; + + NSNumber* b = [NSNumber numberWithInt:param] ; + [[pManager getEmulatorView].kbdc performSelectorOnMainThread:@selector(setLoading:) withObject:b waitUntilDone:NO]; + [pool release]; +} + +void x_refresh_panel(int _panel) +{ + if (!_panel & PANEL_RUNTIME) return ; + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + [[pManager getEmulatorView].kbdc performSelectorOnMainThread:@selector(refreshControls:) withObject:nil waitUntilDone:NO]; + [pool release]; +} + +void x_downloadinginprogress(int _percent) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSNumber* b = [NSNumber numberWithInt:_percent]; + [[pManager getEmulatorView].kbdc performSelectorOnMainThread:@selector(setDownLoading:) withObject:b waitUntilDone:NO]; + [pool release]; +} + +int alertAbort; +MyString alertTitle; +MyString alertMessage; + + + + +void x_init_persistent_path(MyString& hp) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSArray *paths= NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *dir = [paths objectAtIndex:0]; + const char *bar = [dir UTF8String]; + CFStringRef sd = __CFStringMakeConstantString(bar); + hp= CFStringGetCStringPtr(sd,CFStringGetSystemEncoding()); + + [pool release]; +} + + +@implementation ActiveGSBaseViewController +@end + + +@implementation activegsAppDelegate + +@synthesize emulatorController = _emulatorController; +@synthesize viewController = _viewController; +@synthesize infoController = _infoController; +@synthesize detailController = _detailController; +@synthesize currentRawReading = _currentRawReading; +@synthesize window = _window; +@synthesize secondaryWindow = _secondaryWindow; +@synthesize dpiRatio = _dpiRatio; +@synthesize resolutionRatio = _resolutionRatio; +@synthesize notificationTimer = _notificationTimer; +@synthesize notificationView = _notificationView; +@synthesize primaryViewController = _primaryViewController; +@synthesize secondaryViewController = _secondaryViewController; +@synthesize primaryScreen = _primaryScreen; +@synthesize secondaryScreen = _secondaryScreen; +@synthesize backgroundView = _backgroundView; +@synthesize backgroundImageView = _backgroundImageView; + + +- (void)displayAlert:(id)sender { + + NSString* strMsg = [NSString stringWithUTF8String:alertMessage.c_str()]; + NSString* strTitle = [NSString stringWithUTF8String:alertTitle.c_str()]; + + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil] autorelease]; + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex +{ + if (!alertAbort) + return ; + + // quite l'émulateur & revient au menu principal + if (pMac) + { + delete pMac; + pMac = NULL; + } + [self doStateChange:[self getBrowserView] type:kCATransitionPush sens:kCATransitionFromRight]; +} + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + CDownload::initPersistentPath(); + + MyString dir ; + dir = CDownload::getPersistentPath(); + dir += ACTIVEGS_DIRECTORY_SEPARATOR; + dir += IPHONETHUMB; + CDownload::createDirectory(dir.c_str()); + + + NSString* resource = [[NSBundle mainBundle] pathForResource:@ACTIVEGS_FIRSTTABLIST ofType:@"activegsxml"] ; + self->firstTabXML = [resource UTF8String]; + +#define THEVER "/"ACTIVEGS_TITLE "_" TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) + + NSString* ver = [NSString stringWithUTF8String:THEVER]; + NSLog(@"%@",ver); + NSString* resPath = [[NSBundle mainBundle] resourcePath]; + resourcesPath =[resPath UTF8String]; + + +#ifdef USE_GOOGLEANALYTICS +// static const NSInteger kGANDispatchPeriodSec = 10; + GAITrackerActiveGS = [[GAI sharedInstance ]trackerWithTrackingId:@"UA-89449-3"] ; + [GAITrackerActiveGS sendView:ver]; +#endif + + +#ifdef USE_CAPPTAIN + [CapptainAgent registerApp:@ACTIVEGS_CAPTAINAPP identifiedBy:@ACTIVEGS_CAPTAINKEY]; +#endif + +#ifdef ACTIVEGS_MANUAL_ROM + // setup the rom path (in the main thread) + { + extern void initRomPath(); + initRomPath(); + } +#endif + + // Modify global variables to tweak the emulator on iphone + g_adb.g_warp_pointer = WARP_POINTER; + config.bootslot=7; + + CGRect physicalRect = [[UIScreen mainScreen] bounds]; + self.window = [[UIWindow alloc] initWithFrame:physicalRect]; + + [[UIApplication sharedApplication] setStatusBarHidden:TRUE]; + + CGFloat screenScale; + + NSString* systemVer = [[UIDevice currentDevice] systemVersion]; + NSLog(@"iOS version : %@",systemVer); + printf("Min SDK Version : " TOSTRING(__IPHONE_OS_VERSION_MIN_REQUIRED)); + printf("Max SDK Version : " TOSTRING(__IPHONE_OS_VERSION_MAX_ALLOWED)); + printf("%f x %f",physicalRect.size.width,physicalRect.size.height); + + struct utsname systemInfo; + uname(&systemInfo); + + NSString* platformVer = [NSString stringWithCString:systemInfo.machine + encoding:NSUTF8StringEncoding]; + NSLog(@"iOS platform : %@",platformVer); + + screenScale = [[UIScreen mainScreen] scale]; + self.dpiRatio = screenScale; + + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + self.resolutionRatio = 1.6; // pour que la liste prenne toute la hauteur de l'ipad + else + self.resolutionRatio = 1.0; + + machineSpecs = SPEC_DEFAULT; + + if (self.resolutionRatio != 1.0 || screenScale != 1.0f) + { + printf("fps set to 60hz"); + machineSpecs = (machineSpecsEnum)(machineSpecs | FPS_60HZ); + } + if ( [platformVer compare:@"iPhone5"]==NSOrderedDescending + || [platformVer compare:@"iPad3"]==NSOrderedDescending ) + { + printf("audio set to 44 khz"); + machineSpecs = (machineSpecsEnum)(machineSpecs | AUDIO_44KHZ); + } + + self.currentRawReading = -90; // default mode = portrait + pManager = self; + + + extern void activegs_driver(); + g_driver.init(activegs_driver); + g_driver.x_apply_default_options = activegs_apply_default_options; + option.initOptions(); + + self.emulatorController = [[activegsEmulatorController alloc] init ] ; // =retain + self.detailController = [[detailViewController alloc] init] ; // =retain + + + + NSString* infoXB = @"infoViewController"; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + infoXB = [infoXB stringByAppendingString:@"-ipad"]; + + NSLog(@"Trying to load %@",infoXB); + self.infoController = [[infoViewController alloc] initWithNibName:infoXB bundle:nil ]; // =retain + + self.viewController = [[ACTIVEGS_LAUNCHVIEWCONTROLLER alloc] init ]; // =retain + + + + [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didRotate:) + name:@"UIDeviceOrientationDidChangeNotification" object:nil]; + + // ajoute la détection de l" + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(screenDidConnect:) + name:@"UIScreenDidConnectNotification" object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(screenDidDisconnect:) + name:@"UIScreenDidDisconnectNotification" object:nil]; + + + +#ifdef ACTIVEGS_BACKGROUNDIMAGE + NSString* imgPath = @ACTIVEGS_BACKGROUNDIMAGE; + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + imgPath = [imgPath stringByAppendingString:@"-ipad"]; + + NSString *backgroundPath = [[NSBundle mainBundle] pathForResource:imgPath ofType:@"png"]; + UIImage* background = [UIImage imageWithContentsOfFile: backgroundPath] ; + self.backgroundImageView = [[UIImageView alloc ]initWithImage:background]; + CGRect r = [UIScreen mainScreen].applicationFrame; + + self.backgroundView = [[UIView alloc ] initWithFrame:r]; + self.backgroundView.backgroundColor = [UIColor whiteColor]; + [self.backgroundView addSubview:self.backgroundImageView]; + [self.window addSubview:self.backgroundView]; + ; +#endif + + + self.notificationView = [[[UILabel alloc] initWithFrame:CGRectMake(8,48,200,32)] autorelease]; + + + self.notificationView.alpha=0.0; + self.notificationView.textColor =[UIColor blackColor]; + self.notificationView.backgroundColor = [UIColor grayColor]; + self.notificationView.layer.borderColor = [[UIColor whiteColor] CGColor]; + self.notificationView.layer.borderWidth = 1; + self.notificationView.layer.cornerRadius = 5; + self.notificationView.font = [UIFont systemFontOfSize:16]; + self.notificationView.textAlignment = UITextAlignmentCenter; + + [[pManager getBrowserView] updateView ]; + + [self.window makeKeyAndVisible]; + +#ifdef HANDLE_URL + +# ifdef TEST_HANDLE_URL + [self application:nil openURL:nil sourceApplication:nil annotation:nil]; + return YES; +# else + NSURL* url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey]; + if (url) + { + printf("will launch url %@",url); + return YES; + } +# endif +#endif + + +#ifdef ACTIVEGS_BACKGROUNDIMAGE + + //pour laisser le temps à ma view "splashscreen" de s'afficher + [self performSelectorOnMainThread:@selector(firstLaunch:) withObject:nil waitUntilDone:NO]; +#else + + [self firstLaunch:nil]; +#endif + + // ready to accept option + return NO; + + +} + +-(void)firstLaunch:(NSTimer*)timer +{ + [self doStateChange:[self getBrowserView] type:kCATransitionFade sens:kCATransitionFromRight]; + + self.primaryScreen = [UIScreen mainScreen]; + self.secondaryScreen =[UIScreen mainScreen]; + + NSUInteger nbscreen =[[UIScreen screens] count]; + printf("nbscreen:%d\n",nbscreen); + if (nbscreen>1) + { + [self initSecondaryScreen:[[UIScreen screens]objectAtIndex:1]]; + + } +} + +-(void)launchDiskImage:(ActiveGSElement*)_element pathname:(const char*)_pathname trackername:(const char*)_trackername; +{ + + // détruit l'émulateur pour qu'il redémarre + if (pMac) + { + pMac->terminateEmulator(); + delete pMac ; + pMac = NULL; + } + + + config.resetConfig(); // remets les valeur par défault + + + // config.xmlconfig = pt.c_str(); + getdir(_pathname,config.baseURL); + config.pXML = _element->pXML; + config.visibleName = _element->name.c_str(); + + //is2GS = _element->is2GS; + + NSString* ntr = [NSString stringWithUTF8String:_trackername]; + NSString* nid = [NSString stringWithUTF8String:_element->theid.c_str()]; + + // statistique sur les images + NSString* track = [NSString stringWithFormat:@"/%@/%@",ntr,nid]; + NSLog(@"Launching : %@",track); +#ifdef USE_CAPPTAIN + [[pManager getEmulatorView] setTrackerName:track]; +#endif + + +#ifdef USE_GOOGLEANALYTICS + [pManager->GAITrackerActiveGS sendView:track]; +#endif + // affichera le pad si une application le demande + padAlreadyDisplayedOnce=0; + + + // redémarre l'émulateur + [pManager doStateChange:[pManager getEmulatorView] type:kCATransitionPush sens:kCATransitionFromRight]; +} + + + + +- (void) doStateChange:(ACTIVEGS_LAUNCHVIEWCONTROLLER*)_newViewController type:(NSString*)_type sens:(NSString*)_sens +{ + debug_printf("changing view\n"); + + if ([self.window rootViewController ] == _newViewController) + { + printf("same root"); + [_newViewController viewWillAppear:FALSE]; + return ; + } + + + // set up an animation for the transition between the views on 1 screen configuration + if (1)// [self hasSecondary]==false || _newViewController != (UIViewController*)[pManager getEmulatorView]) + { + + CATransition *animation = [CATransition animation]; + [animation setDuration:0.3]; + [animation setType:_type /*kCATransitionPush*/]; + + + if (self.primaryViewController) + [self.primaryViewController.view removeFromSuperview]; + else + { + if (self.backgroundView) + [self.backgroundView removeFromSuperview]; + } + + [self.notificationView removeFromSuperview]; + [_newViewController.view addSubview:self.notificationView]; + + [self.window setRootViewController:_newViewController]; + + // required for IOS4.3 + [self.window makeKeyAndVisible]; + + + self.primaryViewController = _newViewController; + + + debug_printf("finalizing view\n"); + if (self.primaryViewController == (UIViewController*)[pManager getEmulatorView]) + { + } + else + { + // enleve toute l'interface + [[pManager getEmulatorView].kbdc hideInput]; + } + + // Réajuste le sens de l'animation en fonction de l'orientation du mobile + //UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + switch(curOrientation) + { + case UIDeviceOrientationPortrait: + break; + case UIDeviceOrientationPortraitUpsideDown: + if (_sens == kCATransitionFromRight) + _sens = kCATransitionFromLeft; + else + _sens = kCATransitionFromRight; + break; + case UIDeviceOrientationLandscapeLeft: + if (_sens == kCATransitionFromRight) + _sens = kCATransitionFromTop; + else + _sens = kCATransitionFromBottom; + break; + break; + case UIDeviceOrientationLandscapeRight: + if (_sens != kCATransitionFromRight) + _sens = kCATransitionFromTop; + else + _sens = kCATransitionFromBottom; + break; + default: + break; + } + + [animation setSubtype:_sens]; + [[self.window layer] addAnimation:animation forKey:@"SwitchToView1"]; + + } + /* + else + { + // setting up the secondary screen + if (self.secondaryViewController) + [self.secondaryViewController.view removeFromSuperview]; + self.secondaryViewController = _newViewController; + [self.secondaryWindow addSubview:_newViewController.view]; + } + */ + + + printf("manual rotate"); + [self didRotate:nil]; + +} + +-(void)updateNotificationView:(CGRect) newRect +{ +#define NOTIFICATION_WIDTH 240.0f +#define NOTIFICATION_HEIGHT 32.0f + + CGRect r ; + + + r = CGRectMake( + (newRect.size.width-NOTIFICATION_WIDTH)/2, + (newRect.size.height-NOTIFICATION_HEIGHT)/2, + NOTIFICATION_WIDTH, + NOTIFICATION_HEIGHT + ); + + [self.notificationView setFrame:r]; + +} + +-(void)setNotificationText:(NSString*) _text +{ + + NSLog(@"### %@",_text); +#ifdef ACTIVEGS_NOTIFICATION + + [self.notificationView.layer removeAllAnimations]; + [self.notificationTimer invalidate]; + + self.notificationView.text = _text; + + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.3]; + self.notificationView.alpha=1.0; + [UIView commitAnimations]; + + self.notificationTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(dismissNotification:) userInfo:nil repeats:NO]; +#endif + +} +-(void)dismissNotification:(id)_obj +{ + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.3]; + self.notificationView.alpha=0.0; + [UIView commitAnimations]; + self.notificationTimer= nil; + +} + + +- (void) screenDidConnect:(NSNotification *)notification +{ + NSLog(@"Screen did connect"); + UIScreen* screen = [notification object]; + [self initSecondaryScreen:screen]; + + // revient au menu principal si on ne l'était pas + /* + if (self.primaryViewController == [pManager getEmulatorView]) + { + + [self doStateChange:[self getBrowserView] type:kCATransitionPush sens:kCATransitionFromRight]; + } + */ + +} + +- (void) screenDidDisconnect:(NSNotification *)notification +{ + NSLog(@"screenDidDisconnect"); + /* + UIScreen* screen = [notification object]; + if (screen == self.secondaryScreen) + */ + activegsEmulatorController* a = [pManager getEmulatorView]; + if (a && a->attachedTo == ATTACH_SECONDARY) + { + NSLog(@"about to detach secondary"); + + self.secondaryScreen = self.primaryScreen; + self.secondaryWindow.hidden = YES; + [self.secondaryWindow release]; + self.secondaryWindow = nil; + + [a updateView]; + } + + [self setNotificationText:@"Airplay Disconnected"]; +} + +-(void) initSecondaryScreen:(UIScreen*) _screen +{ + [self setNotificationText:@"Airplay Detected"]; + +#ifdef ENABLE_AIRPLAY + self.secondaryScreen = _screen; + CGRect frame = _screen.bounds; + printf("SecondaryScreen size %d x %d",(int)frame.size.width,(int)frame.size.height); + + self.secondaryWindow = [[UIWindow alloc] initWithFrame:frame]; + [self.secondaryWindow setScreen:_screen]; + self.secondaryWindow.hidden = NO; +#endif + activegsEmulatorController* a = [pManager getEmulatorView]; + [a updateView]; + // [pManager setSecondaryInputMode]; + +} + +-(void)setSecondaryInputMode +{ + NSLog(@"setSecondaryInputMode"); + [[pManager getEmulatorView].kbdc setInputMode:INPUTMODE_ACCESS+INPUTMODE_KBD]; +} + + +-(bool) hasSecondary +{ + return self.secondaryWindow != nil; +} + + +- (void) didRotate:(NSNotification *)notification +{ + + + UIViewController *v = self.primaryViewController; + if (v==nil) + return ; + + + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + /* + BOOL valid = [v shouldAutorotateToInterfaceOrientation:orientation]; + if (valid==NO) + { + return ; + } + */ + + float oldRotate = self.currentRawReading; + + switch(orientation) + { + case UIDeviceOrientationPortrait: + NSLog(@"UIDeviceOrientationPortrait"); + self.currentRawReading = -90; + break; + case UIDeviceOrientationPortraitUpsideDown: + NSLog(@"UIDeviceOrientationPortraitUpsideDown"); + self.currentRawReading = 90; + break; + case UIDeviceOrientationLandscapeLeft: + NSLog(@"UIDeviceOrientationLandscapeLeft"); + self.currentRawReading = 180; + break; + case UIDeviceOrientationLandscapeRight: + NSLog(@"UIDeviceOrientationLandscapeRight"); + self.currentRawReading = 0; + break; + case UIDeviceOrientationUnknown: + NSLog(@"ignoring UIDeviceOrientationUnknown"); + return; + break; + default: + NSLog(@"ignoring faceUp or faceDown"); + // ignore face up or down + return; + break; + } + curOrientation = orientation; + NSLog(@"didRotate"); + + + if (self.primaryViewController != [pManager getEmulatorView]) + { + if (self.primaryViewController == [pManager getBrowserView]) + [[pManager getBrowserView] updateView ]; + if (self.primaryViewController == [pManager getInfoView]) + [[pManager getInfoView] updateView:orientation]; + return ; + } + + + // Gère manuellement la rotation + + // Mets les interfaces systèmes (UIAlert) dans le bon mode + + if (self.currentRawReading==0) + [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft]; + else + if (self.currentRawReading==90) + [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortraitUpsideDown]; + else + if (self.currentRawReading==180) + [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight]; + else + // if (currentRawReading==270) + [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait]; + + + + // Recalcule la zone d'affichage de l'émulateur + + // enleve le clavier si une rotation a eu lieu + if (oldRotate != self.currentRawReading )//&& [self hasSecondary]==false) + { + + [[pManager getEmulatorView].kbdc restoreInput]; + + //[[pManager getEmulatorView].kbdc hideInput]; + // [[pManager getEmulatorView].kbdc enableKeyboard:FALSE]; + } + + [[pManager getEmulatorView] updateView ]; + + +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + printf("applicationDidEnterBackground"); + +} +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + printf("applicationWillEnterForeground"); + +} + + + +- (void)dealloc { + + if (pMac) + { + pMac->terminateEmulator(); + delete pMac; + pMac = NULL; + } + + self.viewController = nil; + self.emulatorController = nil; + self.detailController = nil; + self.infoController = nil; + self.window = nil; + [super dealloc]; +} + + +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation +//- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url +{ + +#ifdef HANDLE_URL + NSLog(@"Custom Url %@",url); + + + // NSString* resource = [[NSBundle mainBundle] pathForResource:@ACTIVEGS_FIRSTTABLIST ofType:@"activegsxml"] ; + // MyString source = [resource UTF8String]; + MyString appid; + MyString source; + +#ifdef TEST_HANDLE_URL + source = "http://www.freetoolsassociation.com/fta/undergroundlist.xml"; +#else + for (NSString *param in [[url query] componentsSeparatedByString:@"&"]) + { + NSArray *elts = [param componentsSeparatedByString:@"="]; + if([elts count] < 2) continue; + if ([[elts objectAtIndex:0] isEqualToString:@"id"]) + appid=[ [elts objectAtIndex:1] UTF8String]; + if ([[elts objectAtIndex:0] isEqualToString:@"source"]) + source =[[elts objectAtIndex:1] UTF8String]; + + } +#endif + +if (source.IsEmpty()==FALSE) +{ + self->firstTabXML= source; + activegsViewController* ags = [self getBrowserView]; + if (ags) + { + activegsList* l = [ags l0]; + if (l) + { + l->listPath = self->firstTabXML; + [l reloadData:TRUE]; + } + } + +} + ActiveGSElement* element = NULL; + ActiveGSList temp; + if (appid.IsEmpty()==FALSE) + { + + temp.loadFromFile(self->firstTabXML.c_str()); + for(int i =0;i +#import "../kegs/iOS/zoomEmulatorView.h" +#import "../kegs/iOS/emulatorView.h" +#import "KBDController.h" + +enum gestureModes +{ + + MODE_PAD = 1, + MODE_ZOOM = 2, + MODE_SWIPE= 4, + MODE_ALL = MODE_PAD+MODE_ZOOM+MODE_SWIPE, + MODE_MOUSEBUTTON=8, + MODE_EMULATOR=16, +}; + +@interface customView : UIView +{ + double possibleSwipeLeftTime ; + double possibleSwipeRightTime ; + double possibleSwipeUpTime ; + double possibleSwipeDownTime ; + + UISwipeGestureRecognizer* _grswipeup; + UISwipeGestureRecognizer* _grswipedown; + UISwipeGestureRecognizer* _grswipeleft; + UISwipeGestureRecognizer* _grswiperight; + NSTimer* enableTimer; + NSTimer* disableTimer; +} + +@property (retain,nonatomic) UISwipeGestureRecognizer* grswipeup; +@property (retain,nonatomic) UISwipeGestureRecognizer* grswipedown; +@property (retain,nonatomic) UISwipeGestureRecognizer* grswipeleft; +@property (retain,nonatomic) UISwipeGestureRecognizer* grswiperight; + +-(void)disableGestures:(int)_mode ; +-(void)enableGestures:(int)_mode ; +-(void)disableAllGestures; +-(void)reenableAllGestures ; +-(void)processGesturesOnTouchesEnded ; +-(void)scheduleDisableAllGestures; +-(void)scheduleEnableAllGestures; +-(void)invalidateTimers; + +@end + +enum attachMode +{ + ATTACH_NONE, + ATTACH_PRIMARY, + ATTACH_SECONDARY +}; + +@interface activegsEmulatorController : UIVIEWCONTROLLERROOT +{ + NSString* _trackerName; + customView* _contentView; + zoomEmulatorView* _zv; + KBDController* _kbdc ; +@public + int attachedTo; +} + +#ifdef USE_CAPPTAIN +-(NSString*)getCapptainActivityName; +#endif + +-(void) updateView; + +@property (assign) customView* contentView; +@property (assign) zoomEmulatorView* zv; +@property (assign) KBDController* kbdc ; +@property (nonatomic, retain) NSString* trackerName ; + + +@end + diff --git a/Common.iphone/activegsEmulatorController.mm b/Common.iphone/activegsEmulatorController.mm new file mode 100644 index 0000000..40cbead --- /dev/null +++ b/Common.iphone/activegsEmulatorController.mm @@ -0,0 +1,682 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "activegsAppDelegate.h" +#include "../kegs/src/protos_macdriver.h" +#include "../kegs/src/sim65816.h" + +#define TIME_BEFORE_REENABLING_GESTURES 1.0 +#define TIME_BEFORE_DISABLING_GESTURES 0.5 +#define DELAY_TO_EXECUTE_SWIPE 0.4 +#define SWIPENBTOUCHES 1 + + +#undef debug_printf +#define debug_printf(X,...) + +int x_lock_zoom = 0; + +@implementation customView + +@synthesize grswipedown = _grswipedown; +@synthesize grswipeleft = _grswipeleft; +@synthesize grswiperight = _grswiperight; +@synthesize grswipeup = _grswipeup; + + + +- (UIView *)hitTest:(CGPoint)_point withEvent:(UIEvent *)event +{ + + KBDController *pKbd = [pManager getEmulatorView].kbdc; + UIView* curHit; + CGPoint p; + + if (!pKbd.runtimeControls.hidden && pKbd.runtimeControls.alpha!=0.0) + { + + p = [self convertPoint:_point toView:pKbd.runtimeControls]; + + curHit= [pKbd.runtimeControls hitTest:p withEvent:event]; + if ( [curHit isDescendantOfView:pKbd.runtimeControls]) + { + return curHit; + } + } + + + if (!pKbd.diskSelection.hidden && pKbd.diskSelection.alpha!=0.0) + { + + p = [self convertPoint:_point toView:pKbd.diskSelection]; + + curHit= [pKbd.diskSelection hitTest:p withEvent:event]; + if ( [curHit isDescendantOfView:pKbd.diskSelection]) + { + return curHit; + } + } + + + if (!pKbd.barView.hidden) + { + + p = [self convertPoint:_point toView:pKbd.barView]; + curHit= [pKbd.barView hitTest:p withEvent:event]; + + if ( [curHit isDescendantOfView:pKbd.barView]) + { + // debug_printf("intercepting event : barview\n"); + return curHit; + } + } + + if ([pKbd isInputVisible:(INPUTMODE_ACCESS+INPUTMODE_MINIACCESS)]) + { + + p = [self convertPoint:_point toView:pKbd.accessView]; + curHit= [pKbd.accessView hitTest:p withEvent:event]; + + // regarde si on tape dans la barview + if ( !curHit.hidden && [curHit isDescendantOfView:pKbd.accessView]) + { + + return curHit; + } + } + + + // renvoie les évenements à l'emulator + return [pManager getEmulatorView].zv; +} + +- (id)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) + { + + // Swipe down to hide keyboard + self.grswipeup = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeUp:)] autorelease]; + self.grswipeup.direction = UISwipeGestureRecognizerDirectionUp ; + self.grswipeup.cancelsTouchesInView = NO; + self.grswipeup.numberOfTouchesRequired = SWIPENBTOUCHES; + [self addGestureRecognizer:self.grswipeup]; + + + // Swipe up to display keyboard + self.grswipedown = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeDown:)] autorelease]; + self.grswipedown.direction = UISwipeGestureRecognizerDirectionDown; + self.grswipedown.cancelsTouchesInView = NO; + self.grswipedown.numberOfTouchesRequired = SWIPENBTOUCHES; + [self addGestureRecognizer:self.grswipedown]; + + // Swipe left to go back to browsing + self.grswipeleft = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)] autorelease]; + self.grswipeleft.direction = UISwipeGestureRecognizerDirectionLeft; + self.grswipeleft.cancelsTouchesInView = NO; + self.grswipeleft.numberOfTouchesRequired = SWIPENBTOUCHES; + [self addGestureRecognizer:self.grswipeleft]; + + + // Swipe Right to go back to browsing + self.grswiperight = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)] autorelease]; + self.grswiperight.direction = UISwipeGestureRecognizerDirectionRight; + self.grswiperight.cancelsTouchesInView = NO; + self.grswiperight.numberOfTouchesRequired = SWIPENBTOUCHES; + [self addGestureRecognizer:self.grswiperight]; + + + } + return self; +} + + + +-(void)invalidateTimers +{ + + + if ([enableTimer isValid]) + { + debug_printf("deactivating enable gesture timer"); + [enableTimer invalidate]; + enableTimer=nil; + } + + if ([disableTimer isValid]) + { + debug_printf("deactivating disable gesture timer"); + [disableTimer invalidate]; + disableTimer=nil; + } + +} + +-(void)scheduleDisableAllGestures +{ + + debug_printf("scheduleDisableAllGestures"); + + [self invalidateTimers]; + + disableTimer = [NSTimer scheduledTimerWithTimeInterval:TIME_BEFORE_DISABLING_GESTURES target:self selector:@selector(disableAllGestures) userInfo:nil repeats:NO]; + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_ALL color:[UIColor blueColor]]; + +} + + +-(void)scheduleEnableAllGestures +{ + + debug_printf("scheduleEnableAllGestures"); + + + [self enableGestures:MODE_PAD]; + [self disableGestures:MODE_SWIPE+MODE_ZOOM]; + + enableTimer = [NSTimer scheduledTimerWithTimeInterval:TIME_BEFORE_REENABLING_GESTURES target:self selector:@selector(reenableAllGestures) userInfo:nil repeats:NO]; + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:(MODE_SWIPE+MODE_ZOOM) color:[UIColor orangeColor]]; + +} + +-(void)disableAllGestures +{ + + debug_printf("disableAllGestures\n"); + [self disableGestures:MODE_ALL]; + +} + +-(void)disableGestures:(int)_mode +{ + + debug_printf("disableGestures: %d",_mode); + + [self invalidateTimers]; + + if (_mode & MODE_SWIPE) + { + + self.grswipeup.enabled = FALSE; + self.grswipedown.enabled = FALSE; + self.grswipeleft.enabled = FALSE; + self.grswiperight.enabled = FALSE; + } + if (_mode & MODE_PAD) + [[pManager getEmulatorView].kbdc enablePad:FALSE]; + + if (_mode & MODE_ZOOM) + [[pManager getEmulatorView].zv disableZoom]; + + if (_mode & MODE_EMULATOR) + [[pManager getEmulatorView].zv disableInput]; + + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:_mode color:[UIColor redColor]]; + +} + + + +-(void)enableGestures:(int)_mode +{ + + debug_printf("enableGestures %d\n",_mode); + + if (_mode & MODE_SWIPE) + { + [self invalidateTimers]; + + self.grswipeup.enabled = TRUE; + self.grswipedown.enabled = TRUE; + self.grswipeleft.enabled = TRUE; + self.grswiperight.enabled = TRUE; + } + + if (_mode & MODE_ZOOM) + { + if (x_lock_zoom) + { + // [self disableGestures:MODE_ZOOM]; + [[pManager getEmulatorView].zv disableZoom]; + } + else + [[pManager getEmulatorView].zv enableZoom]; + } + + if (_mode & MODE_PAD) + [[pManager getEmulatorView].kbdc enablePad:TRUE]; + if (_mode & MODE_EMULATOR) + [[pManager getEmulatorView].zv enableInput]; + + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:_mode color:[UIColor greenColor]]; + +} + +-(void)reenableAllGestures +{ + + debug_printf("reenableAllGestures"); + [self enableGestures:(MODE_ALL+MODE_EMULATOR)]; + +} + + +-(void)processGesturesOnTouchesEnded +{ +#if SWIPENBTOUCHES == 1 + debug_printf("processGesturesOnTouchesEnded"); + + // Execute les gestures en attente + double curtime = [[NSDate date] timeIntervalSince1970]; + + if (possibleSwipeLeftTime > curtime) + { + + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromRight]; + + return ; + } + + if (possibleSwipeRightTime > curtime) + { + if ([pManager getDetailView]->diskSelected) + [pManager doStateChange:[pManager getDetailView] type:kCATransitionPush sens:kCATransitionFromLeft]; + else + { + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromLeft]; + } + return ; + } + + if (possibleSwipeDownTime > curtime) + { + [[pManager getEmulatorView].kbdc swipeDown]; + // We remain on the currentView: immediatly turn on gestures + [self reenableAllGestures]; + return ; + } + + if (possibleSwipeUpTime > curtime) + { + + [[pManager getEmulatorView].kbdc swipeUp]; + // We remain on the currentView: immediatly turn on gestures + [self reenableAllGestures]; + return ; + } +#endif + // no gestures + [self scheduleEnableAllGestures]; + [self enableGestures:MODE_ZOOM]; // pour éviter l'interprétation en click! +} + +-(void)swipeLeft :(UISwipeGestureRecognizer*)_rec +{ + if (_rec.state == UIGestureRecognizerStateEnded) + { + +#if SWIPENBTOUCHES == 2 + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromRight]; + +#else + if ([_rec locationInView:self].y < 44 * [pManager resolutionRatio]) + { + possibleSwipeLeftTime = [[NSDate date] timeIntervalSince1970] + DELAY_TO_EXECUTE_SWIPE; + debug_printf("possibleSwipeLeftTime %f\n",possibleSwipeLeftTime); + } +#endif + } +} + +-(void)swipeRight :(UISwipeGestureRecognizer*)_rec +{ + if (_rec.state == UIGestureRecognizerStateEnded) + { +#if SWIPENBTOUCHES == 2 + if ([pManager getDetailView].diskSelected) + [pManager doStateChange:[pManager getDetailView] type:kCATransitionPush sens:kCATransitionFromLeft]; + else + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromLeft]; +#else + + if ([_rec locationInView:self].y < 44 * [pManager resolutionRatio]) + { + possibleSwipeRightTime = [[NSDate date] timeIntervalSince1970] + DELAY_TO_EXECUTE_SWIPE; + debug_printf("possibleSwipeRightTime %f\n",possibleSwipeRightTime); + } +#endif + } + +} + + +-(void)swipeDown : (UISwipeGestureRecognizer*)_rec +{ + debug_printf("swipeDown : %d",_rec.state); + + if (_rec.state == UIGestureRecognizerStateEnded) + { + +#if SWIPENBTOUCHES == 2 + [[pManager getEmulatorView].kbdc swipeDown]; +#else + possibleSwipeDownTime = [[NSDate date] timeIntervalSince1970] + DELAY_TO_EXECUTE_SWIPE; + debug_printf("possibleSwipeDownTime %f\n",possibleSwipeDownTime); +#endif + } + +} + +-(void)swipeUp : (UISwipeGestureRecognizer*)_rec +{ + debug_printf("swipeUp : %d",_rec.state); + + if (_rec.state == UIGestureRecognizerStateEnded) + { +#if SWIPENBTOUCHES == 2 + [[pManager getEmulatorView].kbdc swipeUp]; +#else + possibleSwipeUpTime = [[NSDate date] timeIntervalSince1970] + DELAY_TO_EXECUTE_SWIPE; + debug_printf("possibleSwipeUpTime %f\n",possibleSwipeUpTime); +#endif + } + +} + +- (void)dealloc +{ + + self.grswipedown = nil; + self.grswipeup = nil; + self.grswipeleft = nil; + self.grswiperight = nil; + + [super dealloc]; +} + +@end + +@implementation activegsEmulatorController + +@synthesize kbdc = _kbdc; +@synthesize zv = _zv; +@synthesize contentView = _contentView; +@synthesize trackerName = _trackerName; + + +#ifdef USE_CAPPTAIN +-(NSString*)getCapptainActivityName +{ + NSLog(@"loggin capptain:%@",_trackerName); + return _trackerName; +} +#endif + +- (void)createZoomEmulatorView +{ + + CGRect rv = CGRectMake(0,0,100.0,100.0); + self.zv = [[[zoomEmulatorView alloc] initWithFrame:rv ratio:1.0] retain]; + +} + +- (void)loadView +{ + + attachedTo = ATTACH_NONE; + + CGRect apprect = [[UIScreen mainScreen] applicationFrame]; + printf("mainScreen apprect %d x %d\n",(int)apprect.size.width,(int)apprect.size.height); + + self.contentView = [[[customView alloc] initWithFrame:apprect] autorelease]; +#ifdef SHOW_COLOR + self.contentView.backgroundColor = [UIColor yellowColor]; +#else + self.contentView.backgroundColor = [UIColor blackColor]; +#endif + + + [self createZoomEmulatorView]; + + [self.zv setUserInteractionEnabled:TRUE]; + + self.kbdc = [[KBDController alloc] retain]; + [self.contentView addSubview:self.kbdc.view]; + + self.view = self.contentView; + + + [self.zv disableZoom]; +} + +-(void) updateView +{ + static int inUpdateView=0; + if (inUpdateView) + return ; + inUpdateView++; + debug_printf("viewController updateView\n"); + + + // Transforme la fenetre root view + + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.3]; + + CGAffineTransform matv = CGAffineTransformIdentity; + matv = CGAffineTransformRotate (matv,(270-[pManager getAngle])*M_PI/180); //Avec + self.contentView.transform = matv; + + + + CGRect emulatorRect; // emulator rect + CGRect boundRect; // emulator rect rotate + int requiredOrientation = -1 ; + CGRect kbddelta = CGRectZero; + + CGAffineTransform mat = CGAffineTransformIdentity; +#ifdef VIDEO_SINGLEVLINE + mat = CGAffineTransformScale(mat,1,-2); +#else + mat = CGAffineTransformScale(mat,1,-1); + +#endif + self.zv.transform = mat; + + // Mets à jour la taille de la fenetre en fonction de l'affichage du clavier + if ([pManager hasSecondary ]) + { + CGRect secondaryapprect = [pManager secondaryScreen].bounds; + emulatorRect = CGRectMake(0.0,0.0,secondaryapprect.size.width,secondaryapprect.size.height); + + if (attachedTo != ATTACH_SECONDARY ) + { + printf("attaching to secondary..."); + + attachedTo = ATTACH_SECONDARY; + + [self.zv removeFromSuperview]; + [pManager.secondaryWindow addSubview:self.zv]; + + float ratio = [[pManager secondaryScreen] scale]; + + // recalcule la vue car la résolution/ratio a changé + [self.zv updateScreen:emulatorRect ratio:ratio]; + + [self.kbdc setMenuBarVisibility:true]; + + [pManager setSecondaryInputMode]; + } + + // Force L'affichage par défault + requiredOrientation = 0; + boundRect = emulatorRect; + } + else + { + CGRect primaryapprect = [UIScreen mainScreen].bounds; + emulatorRect = CGRectMake(0.0,0.0,primaryapprect.size.width,primaryapprect.size.height); + NSLog(@"emulatorRect : %f*%f\n",emulatorRect.size.width,emulatorRect.size.height); + if (attachedTo != ATTACH_PRIMARY ) + { + printf("attaching to primay..."); + attachedTo = ATTACH_PRIMARY; + + [self.zv removeFromSuperview]; + + + float ratio = [[UIScreen mainScreen] scale]; + + // recalcule la vue car la résolution/ratio a changé + [self.zv updateScreen:emulatorRect ratio:ratio]; + + [self.contentView addSubview:self.zv]; + + // fait apparaite l'inputr + [self.kbdc restoreInput]; + + // le remts en premier + [self.contentView bringSubviewToFront:self.kbdc.view]; + + + + } + + // primary parameters + + requiredOrientation = ([pManager getAngle]/90)+1; + kbddelta = [self.kbdc getEmulatorDelta]; + + NSString* systemVer = [[UIDevice currentDevice] systemVersion]; + if ([systemVer compare:@"8.0"] == NSOrderedDescending) + boundRect = emulatorRect; + else + { + boundRect = CGRectApplyAffineTransform(emulatorRect,matv); + boundRect.origin.x = 0; + boundRect.origin.y = 0; + } + + + [self.contentView setBounds:boundRect]; + } + + + + [self.zv updateFrame: boundRect kbdRect:kbddelta]; + [self.zv switchOrientation:requiredOrientation]; // a faire après le boundRect + + printf("*** setbound rect %f,%f\n",boundRect.size.width,boundRect.size.height); + + [UIView commitAnimations]; + + + // l'interface est repositionnées mais non animée + + CGRect uirect = [[UIScreen mainScreen] applicationFrame]; + CGRect uirectrotate = CGRectApplyAffineTransform(uirect,matv); + + uirectrotate.origin.x = 0; + uirectrotate.origin.y = 0; + + [self.kbdc updateView:uirectrotate]; + [pManager updateNotificationView:uirectrotate]; + + inUpdateView--; +} + + +// IOS 5 Compatibility + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return NO; +} + +- (BOOL)shouldAutorotate +{ + return NO; +} + + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + + +-(void)viewWillAppear:(BOOL)animated +{ + printf("view will appear"); + [[pManager getEmulatorView].contentView reenableAllGestures]; + + [[pManager getEmulatorView].kbdc setEmulatorTitle:config.visibleName.c_str()]; + + if ([pManager hasSecondary]) + { + [pManager setSecondaryInputMode]; + } + + if (pMac) + { + // réactive l'interface + if ([pManager hasSecondary]) + { + // [[pManager getEmulatorView].kbdc restoreInput]; + } + else + { + debug_printf("### unpausing emulator"); + r_sim65816.resume(); + } + } + else + { + debug_printf("### starting new emulator instance"); + + + [[pManager getEmulatorView].kbdc resetSpecialKeys]; + pMac = new CEmulatorMac(NULL,1); + config.xmlAlreadyLoaded=0; + pMac->setConfig(&config); + pMac->launchEmulator(); + + // remets un ratio de 1.0 + [self.zv setRatioToOne]; + [self.zv switchOrientation:self.zv->curOrientation]; + } + + [self.zv.ew activateEmulatorRefresh:option.getIntValue(OPTION_FRAMERATE)]; + +} + +-(void)viewWillDisappear:(BOOL)animated +{ + + // elimine les gestures (et les timers) + [[pManager getEmulatorView].contentView disableGestures:MODE_ALL]; + if (pMac) + { + if ([pManager hasSecondary]==false) + { + debug_printf("### pausing emulator"); + r_sim65816.pause(); + } + } + [self.zv.ew deactivateEmulatorRefresh]; +} + +- (void)dealloc { + + [self.zv release]; + self.zv = nil; + + [super dealloc]; +} + +@end diff --git a/Common.iphone/activegsList.h b/Common.iphone/activegsList.h new file mode 100644 index 0000000..d140272 --- /dev/null +++ b/Common.iphone/activegsList.h @@ -0,0 +1,79 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#import +#include "../Common/CEMulatorCtrl.h" +#include "../Common/3rdpartylib/simplexml.h" +#include "../Common/ActiveGSList.h" + +#define LABELWIDTH 260 +#define LABELHEIGHT 200 + +@interface itemClass : NSObject +{ +@public + /* + MyString name; + MyString desc; + MyString company; + MyString year; + MyString theid; + MyString thumb; +//#define MAX_SCREENSHOTS 10 +// MyString screenShots[MAX_SCREENSHOTS]; + MyString screenShots0; + MyString screenShots1; + MyString screenShots2; + simplexml* pXML; + int is2GS; + */ + ActiveGSElement* element; +} +@end + + +@interface UILabelMargin : UILabel +{ + +} + +@end + +enum { ONLY_APPLE2=1, ONLY_2GS=2, ALL=4, ALL_NO_INDEX=8, DOC_LIST=128 }; + +@interface activegsList : UITableViewController +{ + + + NSArray *_searchArray ; + NSString* _sourceName; + NSString* _sourceRevision; + UILabelMargin* _warningLabel; + NSMutableArray *_listOfItems; + int bLoaded; + int updateCheckHasBeenDone; +// simplexml* pXML; +@public + ActiveGSList list; + + MyString listPath; + MyString versionPath; + MyString trackerName; + int filter; +} + +@property(nonatomic,retain) NSMutableArray* listOfItems; +@property(nonatomic,retain) UILabelMargin* warningLabel; +@property(nonatomic,retain) NSString* sourceRevision; +@property(nonatomic,retain) NSString* sourceName; +@property(nonatomic,retain) NSArray *searchArray ; + +- (simplexml*)addList:(const char*)_listPath; +- (void)retrieveDocumentList:(MyString&) tempXML withBaseURL:(MyString&)baseURL; +-(void)reloadData:(BOOL)_forceDownload; +-(void)checkUpdateCallback:(NSData*)_data; +@end diff --git a/Common.iphone/activegsList.mm b/Common.iphone/activegsList.mm new file mode 100644 index 0000000..758e37c --- /dev/null +++ b/Common.iphone/activegsList.mm @@ -0,0 +1,766 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "activegsAppDelegate.h" +#import "activegsList.h" +#include "../Common/svnversion.h" +#import "asyncimageview.h" +#import "activegsViewController.h" +//#include "../Common/3rdpartylib/tinyxml/tinyxml.h" +#include "../kegs/src/sim65816.h" +#include "asynccommand.h" + +extern void x_notify_download_failure(const char*_url); + + +@implementation itemClass +@end + +@implementation UILabelMargin + +- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines +{ + return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds,UIEdgeInsetsMake(15,15,15,15)) limitedToNumberOfLines:numberOfLines]; +} + +-(void)drawTextInRect:(CGRect)rect +{ + CGRect r = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines]; + [super drawTextInRect:r]; +} + +@end + + +void xmltostring(simplexml* _this,MyString& _output) +{ + + + MyString s; + s.Format("<%s",_this->key()); + _output += s; + + for (keyvalue_rec *ptr = _this->properties(); ptr!=NULL; ptr=ptr->next) + { + s.Format(" %s=\"%s\"",ptr->key,ptr->value); + _output += s; + } + + _output +=">\n"; + const char *v = _this->value(); + if (v) + _output +=v; + int nc = _this->number_of_children(); + for(int i=0;ichild(i),_output); + s.Format("\n",_this->key()); + _output += s; + +} + + +static UIImage* defaultImage2GS = nil; +static UIImage* defaultImageII = nil; + + +@implementation activegsList + +@synthesize listOfItems = _listOfItems; +@synthesize warningLabel = _warningLabel; +@synthesize sourceRevision = _sourceRevision; +@synthesize sourceName = _sourceName; +@synthesize searchArray = _searchArray ; + + ++(void)initialize +{ + [super initialize]; + + float rr = [pManager resolutionRatio]; + + NSString *imgSource = [[NSBundle mainBundle] pathForResource:@"logo_apple2gs" ofType:@"png"]; + if (imgSource) + { + defaultImage2GS = [UIImage imageWithContentsOfFile: imgSource] ; + defaultImage2GS = [AsyncImageView processImage:defaultImage2GS width:64*rr height:40*rr]; + [defaultImage2GS retain]; + } + else + defaultImage2GS = nil; + + NSString *imgSource2 = [[NSBundle mainBundle] pathForResource:@"logo_apple2" ofType:@"png"]; + if (imgSource2) + { + defaultImageII = [UIImage imageWithContentsOfFile: imgSource2]; + defaultImageII = [AsyncImageView processImage:defaultImageII width:64*rr height:40*rr]; + [defaultImageII retain]; + } + else + defaultImageII = nil; + +} + +-(void)retrieveDocumentList:(MyString&) tempXML withBaseURL:(MyString&) _baseUrl; +{ + + tempXML = "\n"; + tempXML += "My 2GS"; + + NSArray *dopaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [dopaths objectAtIndex:0]; + NSFileManager *manager = [NSFileManager defaultManager]; +// NSArray *fileList = [manager directoryContentsAtPath:documentsDirectory]; + NSError* err; + NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory error:&err]; + + MyString ignoreList; + + const char* utf8docdir = [documentsDirectory UTF8String]; + listPath.Format("%s/LOCAL.ACTIVEGSXML",utf8docdir); + _baseUrl =listPath; + + CDownload dl(utf8docdir); + dl.bNotifyDownloadFailure = true; + + + // parse déjà les fichier .activegsxml + + for (NSString *s in fileList) + { + const char* fn = [s UTF8String]; + const char* ext = getext(fn); + + if (strcasecmp(ext,"activegsxml")) + continue; + + /* + MyString fullpathname = utf8docdir; + fullpathname += "/"; + fullpathname += fn; + */ + MyString path; + MyString shortname; + + dl.retrieveFile(fn,path,shortname); + FILE* f= fopen(path.c_str(),"rb"); + if (!f) continue; + fseek(f,0,SEEK_END); + int si = ftell(f); + + + fseek(f,0,SEEK_SET); + char *buf = new char[si+1]; + memset(buf,0,si+1); + fread(buf,1,si,f); + simplexml* p = new simplexml(buf); + if (!p) + { + delete buf; + continue; + } + if (!strcasecmp(p->key(),"config")) + { + MyString temp; + xmltostring(p,temp); + printf("%s",temp.c_str()); + tempXML += temp.c_str(); + + // rajoute les images dans une liste blackliste + for(int i=0;inumber_of_children();i++) + { + simplexml* child = p->child(i); + if (!strcmp(child->key(),"image")) + { + int order; + MyString path; + int isLocal = dl.parseFilenameAndMakeAbsolute(child->value(), order, path); + if (isLocal) + { + ignoreList+="?"; + ignoreList+=getfile(path); + ignoreList+="?"; + // printf("ignoring:%s",getfile(path.c_str())); + } + } + } + } + delete buf; + fclose(f); + } + + // parse les autres fichiers + for (NSString *s in fileList) + { + const char* fn = [s UTF8String]; + const char* ext = getext(fn); + + if ( strcasecmp(ext,"zip") + && strcasecmp(ext,"2mg") + && strcasecmp(ext,"raw") + && strcasecmp(ext,"dsk") + && strcasecmp(ext,"po") + && strcasecmp(ext,"do") + && strcasecmp(ext,"nib") + && strcasecmp(ext,"bin")) + continue; + + // si le fichier est dans la liste des blacklistée : ignore + MyString pat; + pat.Format("?%s?",fn); + if (ignoreList.Find(pat)!=-1) + continue; + + /* + MyString fullpathname = utf8docdir; + fullpathname += "/"; + fullpathname += fn; + */ + + MyString path; + MyString shortname; + // CDownload dl; + // dl.bNotifyDownloadFailure = true; + dl.retrieveFile(fn,path,shortname); + FILE* f= fopen(path.c_str(),"rb"); + if (!f) continue; + fseek(f,0,SEEK_END); + int si = ftell(f); + + int slot; + if (si < 800*1024) + slot = 6; + else + if (si < 900*1024) + slot = 5; + else + slot = 7; + + tempXML += ""; + tempXML += ""; + tempXML += getfilenoext(fn); + tempXML += ""; + + if (slot==6) + tempXML += "APPLE 2"; + else + tempXML += "2GS"; + + tempXML += ""; +// tempXML += utf8docdir; +// tempXML += "/"; + tempXML += getfilenoext(fn); + tempXML += ".png"; + + tempXML += ""; + tempXML += fn; + tempXML += ""; + tempXML += ""; + tempXML += slotstr; + tempXML += ""; + tempXML += ""; + + + fclose(f); + } + + tempXML+=""; + printf(tempXML.c_str()); +} + +- (simplexml*)addList:(const char*)_listPath +{ + + double currTime = [[NSDate date] timeIntervalSince1970]; + + MyString path; + MyString shortname; +// const char* pxmlstring ; +// char* s = NULL; + MyString xmlString; + + + list.reset(); + + if (!(filter & DOC_LIST)) + { + list.loadFromFile(listPath.c_str()); + } + else + { + MyString baseURL; + [self retrieveDocumentList:xmlString withBaseURL:baseURL]; + list.pathName = baseURL; + list.processString(xmlString.c_str()); + + } + + + NSString* name = [NSString stringWithUTF8String:list.sourceName]; + NSString* rev = [NSString stringWithUTF8String:list.sourceRevision]; + self.sourceName=name; + self.sourceRevision=rev; + + printf("nb element before filter %d\n",list.elements.size()); + for(int i=0;ielement = el; + if ( (filter & ALL) + || (filter & ALL_NO_INDEX) + ||(filter & ONLY_APPLE2 && !el->is2GS) + || (filter & ONLY_2GS && el->is2GS) ) + [self.listOfItems addObject:ic]; + ic = nil; + } + double d = [[NSDate date] timeIntervalSince1970] - currTime; + printf("loaded %s in %f\n",listPath.c_str(),d); + //return pXMLList; + return NULL; +} + + + +static NSInteger compareImagesUsingSelector(id p1, id p2, void *context) +{ + itemClass* obj1 = p1; + itemClass* obj2 = p2; + const char* c1 = obj1->element->name.c_str(); + const char* c2 = obj2->element->name.c_str(); + int ret = strcasecmp(c1,c2); + if (ret>0) + return NSOrderedDescending; + else + if (!ret) + return NSOrderedSame; + else + return NSOrderedAscending; +} + +- (void)addListAsync:(NSTimer*)timer +{ + + + [self addList:listPath.c_str()]; + + if (!(filter & ALL_NO_INDEX)) + [self.listOfItems sortUsingFunction:compareImagesUsingSelector context:nil]; + + [(activegsViewController*)[pManager getBrowserView] activateLoader:FALSE]; + +#ifdef ACTIVEGS_ENABLE_DOCUMENT + if (( filter & DOC_LIST) && [self.listOfItems count]==0) + { + CGSize s = self.view.frame.size; + + CGRect r = CGRectMake((s.width-LABELWIDTH)/2,(s.height-LABELHEIGHT)/2,LABELWIDTH,LABELHEIGHT); + self.warningLabel = [[[UILabelMargin alloc]initWithFrame:r ] autorelease]; + self.warningLabel.backgroundColor = [UIColor colorWithWhite:0.8 alpha:0.5]; + self.warningLabel.lineBreakMode = UILineBreakModeWordWrap; + self.warningLabel.numberOfLines = 0; + // label.textAlignment = UITextAlignmentCenter; + self.warningLabel.font = [UIFont systemFontOfSize:(CGFloat)12.0]; + self.warningLabel.text = @"To add Apple II/2GS disk images :\n\n1- Connect your device to iTunes\n2- Go the 'Apps' tab\n3- Copy files (.2MG, .DSK, .ZIP, ...) to the ActiveGS Documents directory\n4- Click on the \"Refresh\" button to update the list!\n\nMore info on the ActiveGS website."; + /* + [[warningLabel layer] setCornerRadius:8]; + [[warningLabel layer] setMasksToBounds:NO]; + [[warningLabel layer] setShadowColor:[UIColor blackColor].CGColor]; + [[warningLabel layer] setShadowOpacity:1.0f]; + [[warningLabel layer] setShadowRadius:6.0f]; + [[warningLabel layer] setShadowOffset:CGSizeMake(0, 3)]; + */ + [self.view addSubview:self.warningLabel]; + + } + + activegsViewController* v = (activegsViewController*)[pManager getBrowserView]; + + if ([self.listOfItems count]==0) + [(UIButton*)v.navItem.titleView setTitle:@"Refresh" forState:UIControlStateNormal]; + else + [(UIButton*)v.navItem.titleView setTitle:self.sourceName forState:UIControlStateNormal]; + + [(UIButton*)v.navItem.titleView setHidden:NO]; +#endif + + // regarde si on doit raffraichir la liste + + if (!versionPath.IsEmpty()) + { + [[[AsyncCommand alloc] initCommand:versionPath.c_str() withObject:self withSelector:@selector(checkUpdateCallback:)] autorelease]; + } + + bLoaded = 1; + [(UITableView*)self.view reloadData]; + [self viewWillAppear:FALSE]; + + +} + + +-(void)checkUpdateCallback:(NSData*)_data +{ + + if (_data) + { + + char buffer[1024]; + memset(buffer,0,1024); + [_data getBytes:buffer length:1023]; + + NSString* remoteVersion = [[NSString stringWithUTF8String:buffer] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + // NSString* remoteVersion = @"1.08"; + + // vérifie que ca correspond bien à une version + if ([remoteVersion characterAtIndex:1] == '.') + { + NSLog(@"source: %@ current:%@ vs.remote:%@ ",self.sourceName,self.sourceRevision,remoteVersion); + + if (![self.sourceRevision isEqualToString:remoteVersion]) + { + printf("need to upgrade\n"); + [(activegsViewController*)[pManager getBrowserView] updateDialog:remoteVersion]; + } + else + printf("nothing to update\n"); + } + else + printf("bad format"); + + } + else + printf("callback failed."); +} + + +/* + + // DOES NOT WORK ON UITABLEVIEW + +-(void)viewWillAppear:(BOOL)animated +{ + NSLog(@"viewWillAppear -- activegsList"); + // change le titre + [pManager getBrowserView]->navItem.title = sourceName; + +} + */ + + +-(void)reloadData:(BOOL)_forceDownload +{ + //Initialize the array. + self.listOfItems = [[[NSMutableArray alloc] init] autorelease]; + + list.reset(); +// pXML = NULL; + + [(activegsViewController*)[pManager getBrowserView] activateLoader:TRUE]; + + //Set the title + //self.navigationItem.title = @"IIGS"; + + bLoaded = 0; + + // élimine le warning + if (self.warningLabel) + { + [self.warningLabel removeFromSuperview]; + self.warningLabel= nil; + } + + // force le rafraichissement de la liste + [(UITableView*)self.view reloadData]; + + + if (_forceDownload) + { + CDownload dl("***ERR***"); + if (!(filter & DOC_LIST)) + { + dl.deleteCachedFile(listPath.c_str()); + } + } + +#ifdef ACTIVEGS_BACKGROUNDIMAGE + self.tableView.backgroundColor = [UIColor clearColor]; + self.tableView.opaque = NO; +#endif + + [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(addListAsync:) userInfo:nil repeats:NO]; + +// [self performSelectorOnMainThread:@selector(addListAsync:)withObject:self waitUntilDone:NO]; + + +} + +- (void)viewWillAppear:(BOOL)animated +{ + NSLog(@"activeGSList viewWillAppear %@",self); + + + if (self.sourceName) + { +#ifndef ACTIVEGS_BACKGROUNDIMAGE + [(UIButton*)[pManager getBrowserView].navItem.titleView setTitle:self.sourceName forState:UIControlStateNormal]; +#else + ((UILabel*)[pManager getBrowserView].navItem.titleView).text = self.sourceName; +#endif + } +} + +- (void)viewDidLoad { + + + NSLog(@"activeGSList viewDidLoad"); + + + [super viewDidLoad]; + + + // IOS8 ISSUE !!!!! DefaultRawHeight = UITableViewAutomaticDimension + + CGFloat h = 44 * [pManager resolutionRatio]; + self.tableView.rowHeight = h; + self.tableView.delegate = self; + self.tableView.dataSource = self; + + + self.searchArray = [NSArray arrayWithObjects: + @"#", @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", + @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Z",nil]; + + + + [self reloadData:NO]; + + +} + +- (int)findIndexFromRowSection:(int)row section:(char)section +{ + + if (filter & ALL_NO_INDEX) + return row; + + // cherche le premier + int count = 0; + int index = 0; + int nb = [self.listOfItems count]; + for(int i=0;ielement->name.at(0); + + if (c>='0' && c<='9') c='#'; + if (c>='a' && c<='z') c+='A'-'a'; + if (c==section) + { + + if (count == row) + { + index = i; + break; + } + else count++; + } + } + return index; +} + + +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + // remets le thumbnail en top priorité + [[asyncImageQueue sharedQueue] prioritizeItem:cell.imageView]; + + int row = [indexPath row]; + if (row & 1) + cell.backgroundColor = [UIColor colorWithWhite:0.8 alpha:0.6]; + else + cell.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.6]; + + } + + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + + NSInteger row = [indexPath row]; + NSInteger section = [indexPath section]; + int index = [self findIndexFromRowSection:row section:*[[self.searchArray objectAtIndex:section] UTF8String]]; + + NSLog(@"cellForRowAtIndexPath cell %d %d %d",(int)row,(int)section,index); + itemClass* ic = [self.listOfItems objectAtIndex:index]; + NSString* cellValue = [NSString stringWithUTF8String: ic->element->name.c_str()]; + NSString *CellIdentifier = [NSString stringWithFormat:@"Cell_%@",cellValue]; + + UITableViewCell *cell = nil; + + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell != nil) + return cell; + + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + + cell.textLabel.text = cellValue; + + cell.textLabel.font = [UIFont fontWithName:@"ShastonHi640" size:16*[pManager resolutionRatio]]; + + cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; + + if ( ic->element->is2GS) + cell.imageView.image = defaultImage2GS; + else + cell.imageView.image = defaultImageII; + + + + AsyncImageView* asyncImage = [[AsyncImageView alloc] autorelease]; + float s = [pManager resolutionRatio]*[pManager dpiRatio]; + [asyncImage initImage:ic->element->thumb.c_str() target:cell.imageView width:64*s height:40*s]; +// [asyncImage performSelectorOnMainThread:@selector(loadImage:) withObject:nil waitUntilDone:NO]; + [asyncImage loadImage:self]; + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + int row = [indexPath row]; + int section = [indexPath section]; + int index = [self findIndexFromRowSection:row section:*[[self.searchArray objectAtIndex:section] UTF8String]]; + itemClass* ic = [self.listOfItems objectAtIndex:index]; + [pManager launchDiskImage:ic->element pathname:list.pathName.c_str() trackername:list.trackerName.c_str()]; + +} + +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath +{ + int row = [indexPath row]; + int section = [indexPath section]; + int index = [self findIndexFromRowSection:row section:*[[self.searchArray objectAtIndex:section] UTF8String]]; + itemClass* ic = [self.listOfItems objectAtIndex:index]; + detailViewController* dv = [pManager getDetailView]; + dv->diskSelected = ic->element ; + dv->list = &(self->list) ; + + [pManager doStateChange:[pManager getDetailView] type:kCATransitionPush sens:kCATransitionFromRight]; + +} + + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { + + NSLog(@"sectionIndexTitlesForTableView"); + + if (!bLoaded) + return nil; + else + if (filter & ALL_NO_INDEX) + return nil; + else + return self.searchArray; +} + +- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { + + NSLog(@"sectionForSectionIndexTitle %d",(int)index); + if (!bLoaded) + return -1; + else + return index; + +} + + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + NSLog(@"numberOfSectionsInTableView"); + if (!bLoaded) + return 1; + else + if (filter & ALL_NO_INDEX) + return 1; + else + return [self.searchArray count]; +} + + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + if (!bLoaded) + return nil; + else + if (filter & ALL_NO_INDEX) + return nil; + else + return [self.searchArray objectAtIndex:section]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + NSLog(@"numberOfRowsInSection"); + + if (!bLoaded) + return 0; + if (filter & ALL_NO_INDEX) + return [self.listOfItems count]; + + const char* search = [[self.searchArray objectAtIndex:section] UTF8String]; + // cherche le premier + int count = 0; + NSInteger nb = [self.listOfItems count]; + + for(int i=0;ielement->name.at(0); + if (c>='0' && c<='9') c='#'; + if (c>='a' && c<='z') c+='A'-'a'; + if (c==*search) + count++; + else + if (count) + { + // printf("count: %s = %d\n",search,count); + return count; + } + } + return count; +} + +- (void)dealloc +{ + /* + if (pXML) + { + delete pXML; + pXML = NULL; + } + */ + list.reset(); + + [super dealloc]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return YES; +} + +- (BOOL)shouldAutorotate +{ + return YES; +} + +@end diff --git a/Common.iphone/activegsViewController.h b/Common.iphone/activegsViewController.h new file mode 100644 index 0000000..36150c4 --- /dev/null +++ b/Common.iphone/activegsViewController.h @@ -0,0 +1,52 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#include "activegsAppDelegate.h" +#include "../kegs/iOS/emulatorView.h" +#import "activegsList.h" + +/* +@interface activeUITabBarController : UITabBarController + +@end + +@interface activeUINavigationBar : UINavigationBar + +@end +*/ + +@interface activegsViewController : UIVIEWCONTROLLERROOT +{ + + // NSMutableArray* listViews; + UITabBarController* _tabView; + UINavigationBar* _navView; + UIActivityIndicatorView* _loader; + activegsList* _docList; // pour retrouver le label! + activegsList* _l0; + UINavigationItem* _navItem; + +} + +@property (retain,nonatomic) UINavigationItem* navItem; +@property (retain,nonatomic) UINavigationBar* navView; +@property (retain,nonatomic) UITabBarController* tabView; +@property (retain,nonatomic) UIActivityIndicatorView* loader; +@property (retain,nonatomic) activegsList* docList; +@property (retain,nonatomic) activegsList* l0; + +- (void)loadView; +-(void)updateView; +-(void)swipeLeft :(UISwipeGestureRecognizer*)_rec ; +-(void)swipeRight :(UISwipeGestureRecognizer*)_rec ; +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation ; +-(void)activateLoader:(BOOL)_on; +//+(void)initialize; +-(void)updateDialog:(NSString*) newVersion; + +@end + diff --git a/Common.iphone/activegsViewController.mm b/Common.iphone/activegsViewController.mm new file mode 100644 index 0000000..f855f7f --- /dev/null +++ b/Common.iphone/activegsViewController.mm @@ -0,0 +1,555 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "activegsAppDelegate.h" +#import "activegsViewController.h" +#import "activegslist.h" +#include "../Kegs/Src/sim65816.h" + + +@implementation activegsViewController +@synthesize navItem = _navItem; +@synthesize navView = _navView; +@synthesize docList = _docList; +@synthesize l0 = _l0; +@synthesize loader = _loader; +@synthesize tabView = _tabView; + + +-(void)viewWillAppear:(BOOL)animated +{ + NSLog(@"viewWillAppear -- activegsViewController"); + [self updateView]; +} + + +-(void)activateLoader:(BOOL)_on +{ + if (_on) + { + [self.loader startAnimating]; + self.loader.hidden=false; + + } + else + { + [self.loader stopAnimating]; + self.loader.hidden=true; + } + +} + +/* +- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController +*/ + +- (void)UITabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController +{ + + activegsList* l = (activegsList*)viewController; +#ifndef ACTIVEGS_BACKGROUNDIMAGE + if (l.sourceName) + [(UIButton*)self.navItem.titleView setTitle:l.sourceName forState:UIControlStateNormal]; +#endif + [self updateView]; +#ifdef ACTIVEGS_SAVELASTTAB + // sauve la config + option.setIntValue(OPTION_LASTTAB,tabBarController.selectedIndex); + option.saveOptions(1); + #endif +} + + +//#define WHEELSIZEREF 100 +//float WHEELSIZE = WHEELSIZEREF ; + +- (void)loadView +{ + NSLog(@"activeGSViewController -- loadView"); + + [super loadView]; + + CGRect r = [UIScreen mainScreen].applicationFrame; + +#if 0 + float s = [pManager resolutionRatio]; + WHEELSIZE = WHEELSIZEREF*s; + CGRect rl = CGRectMake((self.view.frame.size.width - WHEELSIZE)/2,(self.view.frame.size.height -WHEELSIZE)/2,WHEELSIZE,WHEELSIZE); + self.loader = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease]; + + [self.loader.layer setValue:[NSNumber numberWithFloat:2.0f*s] forKeyPath:@"transform.scale"]; + self.loader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + + [self.loader setFrame:rl]; + +#endif + self.loader = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease]; + + [self.view addSubview:self.loader]; + + [self.loader startAnimating]; + self.loader.hidden=false; + + + + + self.navView = [[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, r.size.width, BARVIEW_HEIGHT)] autorelease]; + self.navView.barStyle = UIBarStyleBlack; + // self.navView.delegate = self; + self.navItem = [[[UINavigationItem alloc] initWithTitle:@ACTIVEGS_TITLE] autorelease]; + +#ifdef ACTIVEGS_BACKGROUNDIMAGE + [self.view addSubview:pManager.backgroundView]; + UILabel* label = [[[UILabel alloc]initWithFrame:CGRectMake(0,0,r.size.width, BARVIEW_HEIGHT)] autorelease]; + label.text = @ACTIVEGS_TITLE; + label.font = [UIFont systemFontOfSize:(CGFloat)16.0]; + label.backgroundColor = [UIColor clearColor]; + label.textColor = [UIColor whiteColor]; + label.textAlignment = UITextAlignmentCenter; + + self.navItem.titleView=label; +#else + UIButton* titleButton = [UIButton buttonWithType:(UIButtonType)100]; + [titleButton addTarget:self action:@selector(titleButton:) forControlEvents:UIControlEventTouchUpInside]; + [titleButton setTitle:@ACTIVEGS_TITLE forState:UIControlStateNormal]; + self.navItem.titleView = titleButton; + self.navItem.titleView.hidden=YES; +#endif + [self.navView pushNavigationItem:self.navItem animated:FALSE]; + + // Rectangle +#if 0 + UIBarButtonItem *browseItem = [[[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered + target:self + action:@selector(backButton:)] autorelease]; +#else + // left Arrow + UIButton* backButton = [UIButton buttonWithType:(UIButtonType)101]; // left-pointing shape! + [backButton addTarget:self action:@selector(backButton:) forControlEvents:UIControlEventTouchUpInside]; + [backButton setTitle:@"Back" forState:UIControlStateNormal]; + + // create button item -- possible because UIButton subclasses UIView! + UIBarButtonItem* browseItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease]; +#endif + + self.navItem.leftBarButtonItem = browseItem; + + UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight]; + [infoButton addTarget:self action:@selector(infoButton:) forControlEvents:UIControlEventTouchUpInside]; + UIBarButtonItem* infoItem = [[[UIBarButtonItem alloc] initWithCustomView:infoButton] autorelease]; + + self.navItem.rightBarButtonItem = infoItem; + + [self.view addSubview:self.navView]; + + r.origin.y = self.navView.frame.size.height; + r.size.height -= r.origin.y; + + self.tabView = [[[UITabBarController alloc] init] autorelease]; + [self.tabView.view setFrame:r]; + self.tabView.delegate = self; + NSString *imgSource; + + self.l0 = [[activegsList alloc] autorelease]; + //imgSource = [[NSBundle mainBundle] pathForResource:@ACTIVEGS_FIRSTTABLIST ofType:@"activegsxml"] ; + self.l0->listPath = pManager->firstTabXML.c_str(); + self.l0->filter= ALL_NO_INDEX ; + self.l0->trackerName = ACTIVEGS_FIRSTTABTRACKER; + imgSource = [[NSBundle mainBundle] pathForResource:@ACTIVEGS_FIRSTTABICON ofType:@"png"]; + self.l0.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@ACTIVEGS_FIRSTTABTITLE image:[UIImage imageWithContentsOfFile: imgSource] tag:0] autorelease]; + +#ifdef ACTIVEGS_SINGLETAB + [self.l0.view setFrame:r]; + [self.view addSubview:self.l0.view]; +#else + activegsList* l3 = [[activegsList alloc] autorelease]; + l3->listPath = "http://www.freetoolsassociation.com/xml/list.activegsxml"; + l3->versionPath = "http://www.freetoolsassociation.com/xml/version.dat"; + l3->filter= ALL; + l3.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"FTA Website" image:[UIImage imageWithContentsOfFile: imgSource] tag:0] autorelease]; ; + l3->trackerName = "FTA"; + + activegsList* l1 = [[activegsList alloc] autorelease]; + l1->listPath = "http://www.virtualapple.org/xmlfiles/list.zip"; + l1->versionPath = "http://www.virtualapple.org/xmlfiles/version.dat"; + l1->filter = ONLY_APPLE2 ; + l1->trackerName = "VirtualApple2"; + /*NSString */imgSource = [[NSBundle mainBundle] pathForResource:@"Tab][" ofType:@"png"]; + l1.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Apple II" image:[UIImage imageWithContentsOfFile: imgSource] tag:0] autorelease]; + + activegsList* l2 = [[activegsList alloc] autorelease]; + l2->listPath = "http://www.virtualapple.org/xmlfiles/list.zip";; + // l2.title = @"Apple IIGS"; + l2->filter = ONLY_2GS; + l2->trackerName = "VirtualApple2GS"; + imgSource = [[NSBundle mainBundle] pathForResource:@"Tab2GS" ofType:@"png"]; + l2.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Apple IIGS" image:[UIImage imageWithContentsOfFile: imgSource] tag:0] autorelease]; + +#ifndef ACTIVEGS_ENABLE_DOCUMENT + self.docList= nil; +#else + self.docList = [[activegsList alloc] autorelease]; + self.docList->listPath.Empty(); + self.docList->filter = (int)(ALL_NO_INDEX|DOC_LIST); + self.docList->trackerName = "My2GS"; + //docList.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"My 2GS" image:[UIImage imageWithContentsOfFile: imgSource] tag:0] autorelease]; + self.docList.tabBarItem = [[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFavorites tag:0] autorelease]; +#endif + + [self.tabView setViewControllers:[NSArray arrayWithObjects:self.l0, l3, l1, l2, self.docList,nil]]; + option.loadOptions(); + self.tabView.selectedIndex=option.getIntValue(OPTION_LASTTAB); + + [self.view addSubview:self.tabView.view]; +#endif // SINGLETAB + + + // Swipe left to go back to browsing + UISwipeGestureRecognizer* grswipeleft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)]; + grswipeleft.direction = UISwipeGestureRecognizerDirectionLeft; + [self.view addGestureRecognizer:grswipeleft]; + [grswipeleft release]; + + // Swipe right to go back to browsing + UISwipeGestureRecognizer* grswiperight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)]; + grswiperight.direction = UISwipeGestureRecognizerDirectionRight; + [self.view addGestureRecognizer:grswiperight]; + [grswiperight release]; + + // pour etre sur qu'il soit visible + [self.view bringSubviewToFront:self.loader]; + + +} + +-(void)viewDidUnload +{ + + self.tabView.delegate = nil; + self.tabView = nil; + self.navItem = nil; + self.navView = nil; + self.loader = nil; + + [super viewDidUnload]; +} + + +-(void)updateDialog:(NSString*) newVersion +{ + + activegsList* l = (activegsList*) self.tabView.selectedViewController; + NSString* fmt = [NSString stringWithFormat:@"Database version v%@ is available!\n(current installed version is v%@)\n\nDo you want to update ?",newVersion,l.sourceRevision]; + + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:l.sourceName message:fmt delegate:self cancelButtonTitle:@"Later" otherButtonTitles:@"Update Now",nil] autorelease]; + [alert show]; +} + +- (void)titleButton:(id)sender +{ + + activegsList* l = (activegsList*) self.tabView.selectedViewController; + NSString* fmt = @"No Database present"; + NSString* title = @"ActiveGS"; + if (l.sourceName) + { + fmt = [NSString stringWithFormat:@"Database v%@\n\nPress Refresh to reload the database.",l.sourceRevision]; + title = l.sourceName; + } + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title message:fmt delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Refresh",nil] autorelease]; + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex +{ + if (buttonIndex==1) + { + + activegsList* l = (activegsList*) self.tabView.selectedViewController; + if (!l) l=self.l0; // BestOfFTA + + // Force redownloading of asset + [l reloadData:YES]; + + + } + +} + + +-(void)updateView +{ + + CGRect rv2 = [[UIScreen mainScreen] applicationFrame]; + if (abs([pManager getAngle])!=90) + { + float t = rv2.size.width; + rv2.size.width = rv2.size.height; + rv2.size.height = t; + } + + // Ajuste la barre de navigation + CGRect rc = self.navView.frame; + rc.size.width = rv2.size.width; + [self.navView setFrame:rc]; + + // Ajuste la position du loader + CGRect r = self.loader.frame; + r = CGRectMake((rv2.size.width - r.size.width)/2,(rv2.size.height -r.size.height)/2,r.size.width,r.size.height); + [self.loader setFrame:r]; + +#ifdef ACTIVEGS_ENABLE_DOCUMENT + // ajuste la position du warning + if (self.docList.warningLabel) + { + CGSize s = CGSizeMake(rv2.size.width,rv2.size.height-44.0*2); + CGRect r = CGRectMake((s.width-LABELWIDTH)/2,(s.height-LABELHEIGHT)/2,LABELWIDTH,LABELHEIGHT); + self.docList.warningLabel.frame = r; + [self.docList.warningLabel.superview bringSubviewToFront:self.docList.warningLabel]; + } +#else + // ajuste la position du background + CGRect rb = pManager.backgroundImageView.frame; + rb.origin.x = (rv2.size.width - rb.size.width)/2; + rb.origin.y = (rv2.size.height - rb.size.height)/2; + pManager.backgroundImageView.frame = rb ; + pManager.backgroundView.frame = rv2; +#endif + + [pManager updateNotificationView:rv2]; + + /* + activegsList* l = self ; //(activegsList*)viewController; + if (l.sourceName) + [(UIButton*)self.navItem.titleView setTitle:l.sourceName forState:UIControlStateNormal]; + */ + +} + + +-(void)swipeLeft :(UISwipeGestureRecognizer*)_rec +{ + if (_rec.state == UIGestureRecognizerStateEnded) + { + + [pManager doStateChange:[pManager getEmulatorView] type:kCATransitionPush sens:kCATransitionFromRight]; + } +} + +-(void)swipeRight :(UISwipeGestureRecognizer*)_rec +{ + if (_rec.state == UIGestureRecognizerStateEnded) + { + [pManager doStateChange:[pManager getEmulatorView]type:kCATransitionPush sens:kCATransitionFromLeft]; + } +} + +- (void)backButton:(id)sender { + +#ifdef ACTIVEGS_IMAGEREQUIRED + // vérifie que l'émulateur fonctionne + if (!pMac) + { + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"ActiveGS" message:@"Select a program in the list first." delegate:nil cancelButtonTitle:@"Done" otherButtonTitles:nil] autorelease]; + [alert show]; + return ; + } + +#endif + [pManager doStateChange:[pManager getEmulatorView] type:kCATransitionPush sens:kCATransitionFromLeft]; + +} + +- (void)infoButton:(id)sender { + + [pManager doStateChange:[pManager getInfoView] type:kCATransitionFade sens:kCATransitionFromLeft]; +} + + +// IOS 5 Compatibility + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return YES; +} + +// IOS6 +- (BOOL)shouldAutorotate +{ + return YES; +} + + + +@end + + + +void x_config_load_roms() +{ + extern byte *g_rom_fc_ff_ptr; + extern byte *g_rom_fc_ff_ptr; + extern unsigned char gsrom01[]; + extern unsigned char apple2e_rom[]; + extern unsigned char apple2e_disk[]; + + g_sim65816.g_mem_size_base = 256*1024; + memset(&g_rom_fc_ff_ptr[0], 0, 2*65536); + +#ifndef ACTIVEGS_MANUAL_ROM + +#ifdef USE_APPLE2_ROM + // main + memcpy(&g_rom_fc_ff_ptr[4*65536-16*1024], &apple2e_rom[16*1024],16*1024); + + // aux + memcpy(&g_rom_fc_ff_ptr[3*65536-16*1024], &apple2e_rom[0],16*1024); + + // disk + memcpy(&g_rom_fc_ff_ptr[3*65536+0xC600], &apple2e_disk[0],1*256); + g_sim65816.g_rom_version = -2; + +#ifdef ACTIVEGS_NOAPPLEBRANDING + for(int i =0;i<9;i++) + g_rom_fc_ff_ptr[0x03ff0A+i]=0xA0; // Apple //e + for(int i =0;i<3;i++) + g_rom_fc_ff_ptr[0x03fbe9+i]=0xEA; // System sound +#endif + +#else + extern unsigned char gsrom01[]; + memcpy(&g_rom_fc_ff_ptr[2*65536], gsrom01,128*1024); + + // Patch la rom + +#ifdef ACTIVEGS_NOAPPLEBRANDING + +#define TOGS(MEM,STR) \ +{ \ +char* d = (char*)MEM; \ +const char* s = STR; \ +char c; \ +while((c=*s++)!=0) *d++=(c|0x80); \ +*d=0; \ +} + + + // g_rom_fc_ff_ptr[0x03bb97]=0x60; // Ret == fully disable display + g_rom_fc_ff_ptr[0x03bb11]=0x0D; // Number of space + TOGS(&g_rom_fc_ff_ptr[0x03bb13],"Please Wait..."); + g_rom_fc_ff_ptr[0x03bb8e]=0x0B; // Center Line + g_rom_fc_ff_ptr[0x03bbb8]=0x60; // Abort display +#endif + g_sim65816.g_rom_version = 1; + +#endif + +#else + extern int readROMFromFile(); + + int ret = readROMFromFile(); + if (!ret) + { + fatal_printf("ROM file not found\n"); + x_fatal_exit("You need to install first a file named \"ROM\" containing a dump of an Apple IIGS™ ROM01 (128KB).\nConnect your device to your computer, and from iTunes, copy the ROM file to MyDevice>Apps\n>ActiveGS>Documents directory.\n\nMore info on the ActiveGS website."); + return ; + } + g_sim65816.g_rom_version = 1; + +#endif + +} + + +#ifdef ACTIVEGS_MANUAL_ROM + +MyString romPath; + +void initRomPath() +{ + NSArray *dopaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [dopaths objectAtIndex:0]; + romPath = [documentsDirectory UTF8String]; + romPath += '/'; + romPath += "ROM"; + +} + +const char* getRomPath() +{ + return romPath.c_str(); +} + + + +int readROMFromFile() +{ + + extern byte* g_rom_fc_ff_ptr; + + const char* rp = getRomPath(); + if (!rp) + { + printf("ROM Path missing\n"); + return 0; + } + + int fd = open(rp, O_RDONLY | O_BINARY); + if(fd < 0) + { + printf("Open ROM file %s failed:%d, errno:%d\n",rp , fd, errno); + return 0; + } + struct stat stat_buf; + int ret = fstat(fd, &stat_buf); + if(ret != 0) + { + printf("fstat returned %d on fd %d, errno: %d\n",ret, fd, errno); + close(fd); + return 0; + } + + int len = stat_buf.st_size; + if(len != 128*1024) + { + printf("Only ROM01 is supported\n"); + close(fd); + return 0; + } + + + ret = read(fd, &g_rom_fc_ff_ptr[2*65536], len); + if(ret != len) + { + printf("error while reading not ROM: %d\n", errno); + close(fd); + return 0; + } + + close(fd); + + // calcul un checksum rapide sur + int crc=0; + int l = 0; + const char* ptr = (const char*)&g_rom_fc_ff_ptr[2*65536]; + int nb = len; + while(nb) + { + crc ^= *ptr << (l%24); + ptr++; + l+=3; + nb--; + } + if (crc != 0xFE2CE93D) + { + printf("ROM01 checksum failed : only original ROM01 is supported!"); + return 0; + } + + return 1; +} + +#endif diff --git a/Common.iphone/activegsViewController.xib b/Common.iphone/activegsViewController.xib new file mode 100644 index 0000000..0c6953a --- /dev/null +++ b/Common.iphone/activegsViewController.xib @@ -0,0 +1,110 @@ + + + + 1552 + 13F34 + 6254 + 1265.21 + 698.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 6247 + + + IBProxyObject + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + {320, 460} + + 3 + MC43NQA + + 2 + + + NO + + IBUISimulatedFreeformSizeMetricsSentinel + Freeform + + IBCocoaTouchFramework + + + + + + + view + + + + 7 + + + + + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + + + + + activegsViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 7 + + + 0 + IBCocoaTouchFramework + NO + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + + diff --git a/Common.iphone/asynccommand.h b/Common.iphone/asynccommand.h new file mode 100644 index 0000000..20460f5 --- /dev/null +++ b/Common.iphone/asynccommand.h @@ -0,0 +1,24 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + + +@interface AsyncCommand : NSObject +{ +NSMutableData* _data; +NSURLConnection* _theConnection; +NSString *_url; +id callbackObj; +SEL callbackSel; +} +@property (retain,nonatomic) NSMutableData* data; +@property (retain,nonatomic) NSURLConnection* theConnection; +@property (retain,nonatomic) NSString *url; + +- (AsyncCommand*)initCommand: (const char*)url withObject:(id)_obj withSelector:(SEL)_sel; + +@end diff --git a/Common.iphone/asynccommand.mm b/Common.iphone/asynccommand.mm new file mode 100644 index 0000000..20dcbc4 --- /dev/null +++ b/Common.iphone/asynccommand.mm @@ -0,0 +1,78 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "activegsAppDelegate.h" +#include "../common/CEmulatorCtrl.h" +#include "asynccommand.h" + +@implementation AsyncCommand + +@synthesize theConnection = _theConnection; +@synthesize url = _url; +@synthesize data = _data; + +- (void)dealloc +{ + self.data = nil; + self.theConnection = nil; + self.url = nil; + [super dealloc]; +} + +- (AsyncCommand*)initCommand: (const char*)_myurl withObject:(id)_obj withSelector:(SEL)_sel +{ + + callbackObj = _obj; + callbackSel = _sel; + + self.url = [NSString stringWithUTF8String:_myurl]; + + NSURL* urlnoescape = [[[NSURL alloc] initWithString:[self.url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] autorelease]; + + NSURLRequest* request = [NSURLRequest requestWithURL:urlnoescape cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; + self.theConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; + + + if (!self.theConnection) + { + printf("NSURLConnection failed\n"); + // appelle la callback + [callbackObj performSelector:callbackSel withObject:nil]; + return nil; + } + { + [self retain]; // ajoute une référence + return self; + } +} + + +//the URL connection calls this repeatedly as data arrives +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incrementalData { + if (self.data==nil) { self.data = [[[NSMutableData alloc] initWithCapacity:2048] autorelease]; } + [self.data appendData:incrementalData]; +} + +//the URL connection calls this once all the data has downloaded +- (void)connectionDidFinishLoading:(NSURLConnection*)connection { + + printf("callback received\n"); + [callbackObj performSelector:callbackSel withObject:self.data]; + self.data=nil; + [self release]; + +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + + printf("callback failed\n",[self.url UTF8String]); + [callbackObj performSelector:callbackSel withObject:nil]; + self.data=nil; + [self release]; +} + +@end diff --git a/Common.iphone/asyncimageview.h b/Common.iphone/asyncimageview.h new file mode 100644 index 0000000..e9f32ee --- /dev/null +++ b/Common.iphone/asyncimageview.h @@ -0,0 +1,50 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#include "activegsList.h" + + +@interface asyncImageQueue : NSObject +{ + NSURLConnection* _theConnection ; + NSMutableArray* _theQueue ; +} + + +@property (retain,nonatomic) NSURLConnection* theConnection ; +@property (retain,nonatomic) NSMutableArray* theQueue ; + +-(void)prioritizeItem:(UIImageView*)_mytarget; ++(void) initialize; +- (void)nextDownload; ++(asyncImageQueue*)sharedQueue; +@end + + +@interface AsyncImageView : NSObject +{ + NSMutableData* _data; + UIImageView* _target; + NSString *_url; + int width,height; + MyString thumb; + MyString cachedURL; +} + +@property (retain,nonatomic) NSMutableData* data; +@property (retain,nonatomic) UIImageView* target; +@property (retain,nonatomic) NSString *url; + + +- (void)processDownload; +- (void)initImage:(const char*)_thumb /*theCell:(UITableViewCell*)_cell*/ target:(UIImageView*)_target width:(int)_width height:(int)_height; +-(void)loadImage:(id)_sender; ++(UIImage*)processImage:(UIImage*)_img width:(int)_width height:(int)_height; +-(void)setImageForCell:(UIImage*) _img; + + +@end diff --git a/Common.iphone/asyncimageview.mm b/Common.iphone/asyncimageview.mm new file mode 100644 index 0000000..fac4426 --- /dev/null +++ b/Common.iphone/asyncimageview.mm @@ -0,0 +1,380 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "activegsAppDelegate.h" +#import "AsyncImageView.h" +#include "../common/CEmulatorCtrl.h" + + +static asyncImageQueue* queue = nil; +static UIActivityIndicatorView* asyncloader=nil; + + +@implementation asyncImageQueue + +@synthesize theQueue = _theQueue; +@synthesize theConnection = _theConnection; + + ++(void) initialize{ + + // singleton + queue = [[asyncImageQueue alloc] init]; + queue.theQueue = [[[NSMutableArray alloc] init ] autorelease]; + queue.theConnection = nil; + + asyncloader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + + +} + ++(asyncImageQueue*)sharedQueue +{ + return queue; +} + +- (void)dealloc { + +// [self.theConnection cancel]; //in case the URL is still downloading + self.theConnection = nil; + self.theQueue = nil; + + [super dealloc]; +} + +-(void)prioritizeItem:(UIImageView*)_mytarget { + + int nb = [self.theQueue count]; + for(int i=0;i 7 && [[str substringToIndex:7] compare:@"http://"]) + { + NSString *str2; + if (thumb.at(0) != '/') + { + // ressource image + str2 = [[NSBundle mainBundle] pathForResource:str ofType:nil]; + } + else + { + // absolute path + str2 = str ; //[NSString stringWithUTF8String:str]; + } + imageView = [[UIImage imageWithContentsOfFile:str2] retain]; // to mimic init + if (!imageView) + { + printf("init image failed (%s)\n",[str2 UTF8String]); + return ; + } + debug_printf("image loaded from resource %s\n",getfile([str2 UTF8String])); + + } + else + { + self.url = str; + + // regarde si l'image est dans le cache + + dl.getPersistentDirectoryFile([self.url UTF8String],IPHONETHUMB,cache); + NSString* strcache = [NSString stringWithUTF8String:cache.c_str()]; + imageView = [[UIImage imageWithContentsOfFile:strcache] retain]; + if (imageView) + { + debug_printf("image loaded from cache %s\n",getfile(cache.c_str())); + } + else + { + + asyncImageQueue* q = [asyncImageQueue sharedQueue]; + [q.theQueue addObject:self]; + [q nextDownload]; + + return ; + } + + } + + [self setImageForCell:imageView]; + + +} + + +//the URL connection calls this repeatedly as data arrives +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incrementalData { + if (self.data==nil) { self.data = [[[NSMutableData alloc] initWithCapacity:2048] autorelease]; } + [self.data appendData:incrementalData]; +} + +//the URL connection calls this once all the data has downloaded +- (void)connectionDidFinishLoading:(NSURLConnection*)connection { + + [asyncloader removeFromSuperview]; + [asyncloader stopAnimating]; + + UIImage* imageView = [[UIImage alloc] initWithData:self.data] ; + if (!imageView) + { + printf("init image failed (%s)\n",[self.url UTF8String]); + } + else + { + // process l'image + NSData * png = self.data; + MyString cache; + CDownload dl("***ERROR***"); + dl.getPersistentDirectoryFile([self.url UTF8String],IPHONETHUMB,cache); + FILE* f = fopen(cache.c_str(),"wb"); + if (f) + { + fwrite(png.bytes,1,png.length,f); + fclose(f); + } + else + { + printf("cannot update cache %s\n",cache.c_str()); + } + + debug_printf("image downloaded (%s)\n",getfile([self.url UTF8String])); + [self performSelectorOnMainThread:@selector(setImageForCell:) withObject:imageView waitUntilDone:NO]; + + } + + self.data=nil; + + [[asyncImageQueue sharedQueue] removeObject:self]; + +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + printf("didFailWithError (%s)\n",[self.url UTF8String]); + + [asyncloader removeFromSuperview]; + [asyncloader stopAnimating]; + + self.data=nil; + + [[asyncImageQueue sharedQueue] removeObject:self]; + +} + ++(UIImage*)processImage:(UIImage*)_img width:(int)_width height:(int)_height +{ +#define IMAGESCALE 1 +#define SHADOW 2 +#define LEFTMARGIN 6 +#define BOTTOMMARGIN 0 +#define TOPMARGIN 0 + + const float s = [pManager dpiRatio]; + + CGRect r = CGRectMake(0,0,_width*s,_height*s); + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(nil, (int)r.size.width,(int)r.size.height, 8, (int)r.size.width*4,colorSpace,kCGImageAlphaPremultipliedLast/*kCGImageAlphaNone*/); + + float ovalWidth=14*s,ovalHeight=14*s; + CGContextSaveGState(context); + CGContextTranslateCTM (context, CGRectGetMinX(r), CGRectGetMinY(r)); + CGContextScaleCTM (context, ovalWidth, ovalHeight); + float fw = CGRectGetWidth (r) / ovalWidth; + float fh = CGRectGetHeight (r) / ovalHeight; + CGContextMoveToPoint(context, fw, fh/2); + CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); + CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); + CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); + CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); + CGContextClosePath(context); + CGContextRestoreGState(context); + CGContextClip(context); + //CGContextSetInterpolationQuality(context,kCGInterpolationHigh); + CGContextDrawImage(context,r,[_img CGImage]); + CGImageRef imageRef2 = CGBitmapContextCreateImage(context); + // Crée une nouvelle image pour le shadow + CGRect r2 = CGRectMake(0,0,r.size.width+(LEFTMARGIN+SHADOW)*s,r.size.height+(SHADOW*2+BOTTOMMARGIN+TOPMARGIN)*s); + CGContextRef context2 = CGBitmapContextCreate(nil,(int)r2.size.width,(int)r2.size.height, 8, (int)r2.size.width*4,colorSpace,kCGImageAlphaPremultipliedLast/*kCGImageAlphaNone*/); + + CGContextSaveGState(context2); + CGContextSetShadowWithColor(context2, CGSizeMake(SHADOW*s, -SHADOW*s), 4, [[UIColor grayColor] CGColor]); + + CGRect rdest = r; + rdest.origin.x = LEFTMARGIN*s; + rdest.origin.y = (BOTTOMMARGIN+SHADOW)*s; + //CGContextSetInterpolationQuality(context2,kCGInterpolationHigh); + + CGContextDrawImage(context2,rdest,imageRef2); + CGContextRestoreGState(context2); + + CGImageRef imageRef = CGBitmapContextCreateImage(context2); + UIImage* newImage = [UIImage imageWithCGImage:imageRef]; + + CGColorSpaceRelease(colorSpace); + CGContextRelease(context); + CFRelease(imageRef); + CGContextRelease(context2); + CFRelease(imageRef2); + + return newImage; + +} + +-(void)setImageForCell:(UIImage*) _img +{ + debug_printf("setImageForCell"); + + UIImage* img2 = [AsyncImageView processImage:_img width:width height:height]; + + [self.target setNeedsDisplay]; + + [UIView beginAnimations:@"ToggleSiblings" context:nil]; + [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft /*UIViewAnimationTransitionCurlUp*/ forView:self.target cache:YES]; + [UIView setAnimationDuration:1.0]; + self.target.image = img2; + [UIView commitAnimations]; + + // sauve dans le cache + NSData *png = UIImagePNGRepresentation(img2); + + FILE* f = fopen(cachedURL.c_str(),"wb"); + if (f) + { + fwrite(png.bytes,1,png.length,f); + fclose(f); + } + else + { + printf("cannot update cache %s\n",cachedURL.c_str()); + } + + [_img release]; + +} +@end diff --git a/Common.iphone/detailViewController.h b/Common.iphone/detailViewController.h new file mode 100644 index 0000000..491d294 --- /dev/null +++ b/Common.iphone/detailViewController.h @@ -0,0 +1,62 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#import "activegsAppDelegate.h" +#import "activegsList.h" + + + +@interface detailViewController : UIVIEWCONTROLLERROOT { + + NSURL* requestURL ; + + +// Properties + UINavigationItem* _navItem; + + UILabel* _diskName; + UILabel* _diskYear; + UILabel* _diskCompany; + UITextView* _diskDescription; + UIImageView* _diskApple2; + UIImageView* _diskApple2GS; + UIWebView* _diskWebView; + UIImageView* _screenShot1; + UIImageView* _screenShot2; + UIImageView* _screenShot3; + UINavigationBar* _navView; + /* + itemClass* _diskSelected; + activegsList* _list; + */ +@public + ActiveGSElement* diskSelected; + ActiveGSList* list; +} + + +@property (nonatomic, retain) IBOutlet UILabel* diskName; +@property (nonatomic, retain) IBOutlet UILabel* diskYear; +@property (nonatomic, retain) IBOutlet UILabel* diskCompany; +@property (nonatomic, retain) IBOutlet UITextView* diskDescription; +@property (nonatomic, retain) IBOutlet UIImageView* diskApple2; +@property (nonatomic, retain) IBOutlet UIImageView* diskApple2GS; +@property (nonatomic, retain) IBOutlet UIWebView* diskWebView; +@property (nonatomic, retain) IBOutlet UIImageView* screenShot1; +@property (nonatomic, retain) IBOutlet UIImageView* screenShot2; +@property (nonatomic, retain) IBOutlet UIImageView* screenShot3; +@property (nonatomic, retain) IBOutlet UINavigationBar* navView; +/* +@property (nonatomic, retain) itemClass* diskSelected; +@property (nonatomic, retain) activegsList* list; + */ +@property (nonatomic, retain) UINavigationItem* navItem; + + +- (IBAction) launchButton:(id)_sender; + +@end \ No newline at end of file diff --git a/Common.iphone/detailViewController.mm b/Common.iphone/detailViewController.mm new file mode 100644 index 0000000..7c3009d --- /dev/null +++ b/Common.iphone/detailViewController.mm @@ -0,0 +1,208 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "activegsAppDelegate.h" +#import "detailViewController.h" +#import "activegsList.h" +#include "../Common/svnversion.h" +#import "asyncimageview.h" +#import "activegsViewController.h" + + +@implementation detailViewController + +@synthesize diskName=_diskName; +@synthesize diskCompany = _diskCompany; +@synthesize diskYear=_diskYear; +@synthesize diskDescription = _diskDescription; +@synthesize diskApple2 = _diskApple2; +@synthesize diskApple2GS = _diskApple2GS; +@synthesize diskWebView = _diskWebView; +@synthesize screenShot1 = _screenShot1; +@synthesize screenShot2 = _screenShot2; +@synthesize screenShot3 = _screenShot3; +@synthesize navView = _navView; +@synthesize navItem = _navItem; +/* +@synthesize diskSelected = _diskSelected; +@synthesize list = _list; + */ + +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType +{ + + requestURL = [[ request URL ] retain]; + + // Check to see what protocol/scheme the requested URL is. + if ( ( [ [ requestURL scheme ] isEqualToString: @"http" ] + || [ [ requestURL scheme ] isEqualToString: @"https" ] ) + && ( navigationType == UIWebViewNavigationTypeLinkClicked ) ) { + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"iPhone" message:@"Link will open in Safari, continue?" delegate:self cancelButtonTitle:@"Yes" otherButtonTitles:@"No",nil] autorelease]; + [alert show]; + return NO; + } + + return YES; +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex +{ + if (buttonIndex==0) + [[ UIApplication sharedApplication ] openURL: requestURL ]; + +} + +- (void)viewWillAppear:(BOOL)animated +{ + + printf("settitle2:%s\n",self->diskSelected->name.c_str()); + + [self.navItem setTitle:[NSString stringWithUTF8String: self->diskSelected->name.c_str()]]; + self.diskName.text = [NSString stringWithUTF8String: self->diskSelected->name.c_str()]; + self.diskCompany.text = [NSString stringWithUTF8String: self->diskSelected->publisher.c_str()]; + NSString* desc = [NSString stringWithUTF8String: self->diskSelected->desc.c_str()]; + float rr = [pManager resolutionRatio]; + float fs1 = .9 * rr; + float fs2 = 1.5 ;//* rr; + NSString* html = [NSString stringWithFormat:@"

%@

",fs1,fs2,desc]; + + [self.diskWebView loadHTMLString:html baseURL:nil]; + + self.diskYear.text = [NSString stringWithUTF8String: self->diskSelected->year.c_str()]; + +#ifdef ACTIVEGS_NOAPPLEBRANDING + self.diskApple2.hidden = TRUE; + self.diskApple2GS.hidden = TRUE; +#else + self.diskApple2.hidden = (self->diskSelected->is2GS); + self.diskApple2GS.hidden = !(self->diskSelected->is2GS); +#endif + self.screenShot1.image = nil; + self.screenShot2.image = nil; + self.screenShot3.image = nil; + + AsyncImageView* asyncImage1 = [[AsyncImageView alloc] autorelease] ; + [asyncImage1 initImage:self->diskSelected->screenShots[0].c_str() target:self.screenShot1 width:128 height:80]; + [asyncImage1 loadImage:nil]; + + AsyncImageView* asyncImage2 = [[AsyncImageView alloc] autorelease]; + [asyncImage2 initImage:self->diskSelected->screenShots[1].c_str() target:self.screenShot2 width:128 height:80]; + [asyncImage2 loadImage:nil]; + + AsyncImageView* asyncImage3 = [[AsyncImageView alloc] autorelease] ; + [asyncImage3 initImage:self->diskSelected->screenShots[2].c_str() target:self.screenShot3 width:128 height:80]; + [asyncImage3 loadImage:nil]; + + self.diskWebView.backgroundColor = [UIColor whiteColor]; + + +} + +- (void)backButton:(id)sender { + + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromLeft]; + +} + +- (void)launchButton +{ + + [pManager launchDiskImage:self->diskSelected pathname:self->list->pathName trackername:self->list->trackerName]; + +} + +// IOS 5 Compatibility + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return YES; +} + +// IOS6 +- (BOOL)shouldAutorotate +{ + return YES; +} + + +- (void)dealloc +{ + + [requestURL release]; + [super dealloc]; +} + + + +-(void)viewDidLoad { + + + CGRect r = [UIScreen mainScreen].applicationFrame; + self.navItem = [[[UINavigationItem alloc] initWithTitle:@"Detail"] autorelease]; + [self.navView pushNavigationItem:self.navItem animated:FALSE]; + + [self.view setFrame:r]; + + // Rectangle +#if 0 + UIBarButtonItem *browseItem = [[UIBarButtonItem alloc] initWithTitle:@"DETAIL" style:UIBarButtonItemStyleBordered + target:self + action:@selector(backButton:)]; +#else + // left Arrow + UIButton* backButton = [UIButton buttonWithType:(UIButtonType)101]; // left-pointing shape! + [backButton addTarget:self action:@selector(backButton:) forControlEvents:UIControlEventTouchUpInside]; + [backButton setTitle:@"List" forState:UIControlStateNormal]; + + // create button item -- possible because UIButton subclasses UIView! + UIBarButtonItem* browseItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease]; +#endif + + self.navItem.leftBarButtonItem = browseItem; + + // Swipe left to go back to browsing + UISwipeGestureRecognizer* grswipeleft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)] ; + grswipeleft.direction = UISwipeGestureRecognizerDirectionLeft; + grswipeleft.cancelsTouchesInView = NO; + [self.view addGestureRecognizer:grswipeleft]; + [grswipeleft release]; + + + // Swipe Right to launch + UISwipeGestureRecognizer* grswiperight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)] ; + grswiperight.direction = UISwipeGestureRecognizerDirectionRight; + grswiperight.cancelsTouchesInView = NO; + [self.view addGestureRecognizer:grswiperight]; + [grswiperight release]; + + +} + +-(void)swipeRight :(UISwipeGestureRecognizer*)_rec +{ + + if (_rec.state == UIGestureRecognizerStateEnded) + { + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromLeft]; + } +} + +-(void)swipeLeft :(UISwipeGestureRecognizer*)_rec +{ + if (_rec.state == UIGestureRecognizerStateEnded) + { + [pManager doStateChange:[pManager getEmulatorView] type:kCATransitionPush sens:kCATransitionFromRight]; + } +} + + +- (IBAction) launchButton:(id)_sender +{ + + [pManager launchDiskImage:self->diskSelected pathname:self->list->pathName.c_str() trackername:self->list->trackerName.c_str()]; +} + +@end diff --git a/Common.iphone/detailViewController.xib b/Common.iphone/detailViewController.xib new file mode 100644 index 0000000..8d56f6c --- /dev/null +++ b/Common.iphone/detailViewController.xib @@ -0,0 +1,517 @@ + + + + 1536 + 11G63 + 2844 + 1138.51 + 569.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 1930 + + + YES + IBProxyObject + IBUIButton + IBUIImageView + IBUILabel + IBUINavigationBar + IBUIView + IBUIViewController + IBUIWebView + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 287 + + YES + + + 269 + {{119, 435}, {78, 37}} + + NO + IBCocoaTouchFramework + 0 + 0 + 1 + Launch + + 3 + MQA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MC41AA + + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + + + + + 293 + {{129, 53}, {62, 25}} + + NO + YES + 4 + YES + IBCocoaTouchFramework + + NSImage + icon_APPLE 2GS.png + + + + + 293 + {{130, 55}, {60, 21}} + + NO + YES + 4 + YES + IBCocoaTouchFramework + + NSImage + icon_APPLE 2.png + + + + + 292 + {{8, 53}, {114, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Company + + 1 + MCAwIDAAA + darkTextColor + + + 1 + 10 + + Helvetica + Helvetica + 0 + 12 + + + Helvetica + 12 + 16 + + + + + 289 + {{238, 53}, {73, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + 1988 + + + 1 + 10 + 2 + + + + + + 274 + {{8, 84}, {303, 278}} + + + 1 + MSAxIDEAA + + IBCocoaTouchFramework + 2 + + + + 268 + {{8, 370}, {91, 57}} + + NO + IBCocoaTouchFramework + + + + 269 + {{114, 370}, {91, 57}} + + NO + IBCocoaTouchFramework + + + + 265 + {{220, 370}, {91, 57}} + + NO + IBCocoaTouchFramework + + + + 290 + {320, 44} + + NO + IBCocoaTouchFramework + 1 + + YES + + + + {320, 480} + + + 3 + MQA + + 2 + + + IBCocoaTouchFramework + + + detailViewController + + + 1 + 1 + + IBCocoaTouchFramework + NO + + + + + YES + + + view + + + + 6 + + + + diskApple2GS + + + + 13 + + + + diskApple2 + + + + 14 + + + + diskCompany + + + + 19 + + + + diskYear + + + + 20 + + + + diskWebView + + + + 28 + + + + screenShot1 + + + + 32 + + + + screenShot2 + + + + 33 + + + + screenShot3 + + + + 34 + + + + navView + + + + 67 + + + + launchButton: + + + 7 + + 9 + + + + delegate + + + + 27 + + + + + YES + + 0 + + + + + + 1 + + + YES + + + + + + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 8 + + + + + 10 + + + + + 11 + + + + + 15 + + + + + 16 + + + + + 24 + + + + + 26 + + + + + 29 + + + + + 30 + + + + + 31 + + + + + 54 + + + YES + + + + + + + YES + + YES + -1.CustomClassName + -1.IBPluginDependency + -2.CustomClassName + -2.IBPluginDependency + 1.IBPluginDependency + 10.IBPluginDependency + 11.IBPluginDependency + 15.IBPluginDependency + 16.IBPluginDependency + 24.CustomClassName + 24.IBPluginDependency + 26.IBPluginDependency + 29.IBPluginDependency + 30.IBPluginDependency + 31.IBPluginDependency + 54.IBPluginDependency + 8.IBPluginDependency + + + YES + detailViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + detailViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 67 + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + + YES + + YES + icon_APPLE 2.png + icon_APPLE 2GS.png + + + YES + {62, 23} + {62, 25} + + + 1930 + + diff --git a/Common.iphone/disk_35_1.png b/Common.iphone/disk_35_1.png new file mode 100644 index 0000000..14a5faf Binary files /dev/null and b/Common.iphone/disk_35_1.png differ diff --git a/Common.iphone/disk_35_2.png b/Common.iphone/disk_35_2.png new file mode 100644 index 0000000..54b2624 Binary files /dev/null and b/Common.iphone/disk_35_2.png differ diff --git a/Common.iphone/disk_525_1.png b/Common.iphone/disk_525_1.png new file mode 100644 index 0000000..0a82d03 Binary files /dev/null and b/Common.iphone/disk_525_1.png differ diff --git a/Common.iphone/disk_525_2.png b/Common.iphone/disk_525_2.png new file mode 100644 index 0000000..dd35512 Binary files /dev/null and b/Common.iphone/disk_525_2.png differ diff --git a/Common.iphone/fta20-ipad.png b/Common.iphone/fta20-ipad.png new file mode 100644 index 0000000..ef98f76 Binary files /dev/null and b/Common.iphone/fta20-ipad.png differ diff --git a/Common.iphone/fta20.png b/Common.iphone/fta20.png new file mode 100644 index 0000000..ce4c96e Binary files /dev/null and b/Common.iphone/fta20.png differ diff --git a/Common.iphone/fta20@2x.png b/Common.iphone/fta20@2x.png new file mode 100644 index 0000000..28b0c2a Binary files /dev/null and b/Common.iphone/fta20@2x.png differ diff --git a/Common.iphone/fta20_2x.png b/Common.iphone/fta20_2x.png new file mode 100644 index 0000000..28b0c2a Binary files /dev/null and b/Common.iphone/fta20_2x.png differ diff --git a/Common.iphone/icon_APPLE 2.png b/Common.iphone/icon_APPLE 2.png new file mode 100644 index 0000000..b940348 Binary files /dev/null and b/Common.iphone/icon_APPLE 2.png differ diff --git a/Common.iphone/icon_APPLE 2GS.png b/Common.iphone/icon_APPLE 2GS.png new file mode 100644 index 0000000..d1469d4 Binary files /dev/null and b/Common.iphone/icon_APPLE 2GS.png differ diff --git a/Common.iphone/infoViewController.h b/Common.iphone/infoViewController.h new file mode 100644 index 0000000..bca1ade --- /dev/null +++ b/Common.iphone/infoViewController.h @@ -0,0 +1,27 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + +@interface infoViewController : UIVIEWCONTROLLERROOT { + +// Properties + UIView* _portraitView; + UIView* _landscapeView; + UILabel* _versionUI; + UILabel* _versionUILandscape; +} + +@property (nonatomic, retain) IBOutlet UILabel* versionUILandscape; +@property (nonatomic, retain) IBOutlet UILabel* versionUI; +@property (nonatomic, retain) IBOutlet UIView* portraitView; +@property (nonatomic, retain) IBOutlet UIView* landscapeView; + +- (void)updateView:(UIDeviceOrientation)_orientation ; +- (IBAction) doneButton:(id)_sender; +- (IBAction) parametersButton:(id)_sender; +- (IBAction) emailButton:(id)_sender; +@end diff --git a/Common.iphone/infoViewController.mm b/Common.iphone/infoViewController.mm new file mode 100644 index 0000000..6689619 --- /dev/null +++ b/Common.iphone/infoViewController.mm @@ -0,0 +1,152 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "activegsAppDelegate.h" +#import "infoViewController.h" +#import "activegsList.h" +#include "../Common/svnversion.h" +#import "asyncimageview.h" +#import "activegsViewController.h" +#include "../xcodebuild.h" + +@implementation infoViewController + +@synthesize versionUI=_versionIU; +@synthesize versionUILandscape=_versionUILandscape; +@synthesize portraitView= _portraitView; +@synthesize landscapeView = _landscapeView; + +- (void)dealloc { + [super dealloc]; +} + + +-(void)viewDidLoad +{ + + + NSString *AppVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; + NSString *buildVersion = [NSString stringWithUTF8String:xcodebuild]; + + + self.versionUILandscape.text= + self.versionUI.text = [NSString stringWithFormat: @"v%@#%@ -- ActiveGS "TOSTRING(ACTIVEGSMAJOR)"."TOSTRING(ACTIVEGSMINOR)"."TOSTRING(ACTIVEGSBUILD)"",AppVersion,buildVersion]; + + [self.portraitView setFrame:[[UIScreen mainScreen] bounds] ]; + [self.landscapeView setFrame:[[UIScreen mainScreen] bounds] ]; + + // [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; +} + +-(void)viewDidAppear:(BOOL)animated +{ + printf("viewDidAppear"); + + + // Swipe left to go back to browsing + UISwipeGestureRecognizer* grswipeleft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)]; + grswipeleft.direction = UISwipeGestureRecognizerDirectionLeft; + grswipeleft.cancelsTouchesInView = NO; + [self.view addGestureRecognizer:grswipeleft]; + [grswipeleft release]; + + // Swipe Right to go back to browsing + UISwipeGestureRecognizer* grswiperight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)]; + grswiperight.direction = UISwipeGestureRecognizerDirectionRight; + grswiperight.cancelsTouchesInView = NO; + [self.view addGestureRecognizer:grswiperight]; + [grswiperight release]; + +} + + +-(void)updateView:(UIDeviceOrientation)_orientation +{ + debug_printf("updateView infoViewController"); + + + BOOL isPortrait = abs([pManager getAngle])==90.0f ; + + if (isPortrait) + self.view = self.portraitView; + else + self.view = self.landscapeView; + +// self.view = self.portraitView; + + + CGAffineTransform matv = CGAffineTransformIdentity; + matv = CGAffineTransformRotate (matv,(270-[pManager getAngle])*M_PI/180); //Avec + self.view.transform = matv; + + CGRect rv2 = [[UIScreen mainScreen] applicationFrame]; + CGRect rv3 = CGRectApplyAffineTransform(rv2,matv); + rv3.origin.x = 0; + rv3.origin.y = 0; + [self.view setBounds:rv3]; + + CGRect rscreen = [[UIScreen mainScreen] applicationFrame]; + CGRect vscreen = self.view.frame; + + vscreen.origin.x = (rscreen.size.width - self.view.frame.size.width)/2; + vscreen.origin.y = (rscreen.size.height-self.view.frame.size.height)/2; + [self.view setFrame:vscreen]; + + // pour réactiver les gestures + [self viewDidAppear:FALSE]; + +} + + +-(void)swipeLeft :(UISwipeGestureRecognizer*)_rec +{ + + if (_rec.state == UIGestureRecognizerStateEnded) + { + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromRight]; + } +} + +-(void)swipeRight :(UISwipeGestureRecognizer*)_rec +{ + if (_rec.state == UIGestureRecognizerStateEnded) + { + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionPush sens:kCATransitionFromLeft]; + } +} + +- (IBAction) doneButton:(id)_sender; +{ + [pManager doStateChange:[pManager getBrowserView] type:kCATransitionFade sens:kCATransitionFromLeft]; + +} + +- (IBAction) emailButton:(id)_sender; +{ + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.facebook.com/groups/187271854617450/"]]; + +} + +- (IBAction) parametersButton:(id)_sender +{ + UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"ActiveGS" message:@"Not implemented yet" delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil] autorelease]; + [alert show]; + +} + +// IOS 5 Compatibility + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return NO; +} + +- (BOOL)shouldAutorotate +{ + return NO; +} + +@end diff --git a/Common.iphone/kbdlayout.h b/Common.iphone/kbdlayout.h new file mode 100644 index 0000000..d576b24 --- /dev/null +++ b/Common.iphone/kbdlayout.h @@ -0,0 +1,28 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + + +@interface kbdlayout : UIView +{ + int iKbd; +} + +@end + + +@interface kbdselected : UIView +{ + const char* v; + int time; +// int iKbd; +} +//@property(nonatomic,getter=getikbd) int iKbd; + +- (void) setParam: (const char*)_v; ++ (kbdselected*) getSelected; +@end diff --git a/Common.iphone/kbdlayout.mm b/Common.iphone/kbdlayout.mm new file mode 100644 index 0000000..e12ebf0 --- /dev/null +++ b/Common.iphone/kbdlayout.mm @@ -0,0 +1,310 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "kbdlayout.h" +#import "keyboard.h" +#import "activegsAppDelegate.h" +#include "../src91/protos_macdriver.h" +extern void add_event_key(int,int); + +// http://farm3.static.flickr.com/2448/3825169053_859571c493_o.jpg + + +#define KBDWIDTH 22 +#define KBDWIDTHTAB 25 +#define KBDWIDTHCTRL 30 +#define KBDWIDTHRET 30 +#define KBDWIDTHSHIFT 42 +#define KBDWIDTHAPPLE 30 +#define KBDWIDTHSPACE 100 +struct kbdDefinition kbdDefinitions[]= +{ +{ KBDWIDTH,"esc",0x35,0,0 }, +{ KBDWIDTH,"1",0x12,"!",0 }, +{ KBDWIDTH,"2",0x13,"@",0 }, +{ KBDWIDTH,"3",0x14,"#",0 }, +{ KBDWIDTH,"4",0x15,"$",0 }, +{ KBDWIDTH,"5",0x17,"%",0 }, +{ KBDWIDTH,"6",0x16,"^",0 }, +{ KBDWIDTH,"7",0x1A,"&",0 }, +{ KBDWIDTH,"8",0x1C,"*",0 }, +{ KBDWIDTH,"9",0x19,"(",0 }, +{ KBDWIDTH,"0",0x1D,")",0 }, +{ KBDWIDTH,"-",0x1B,"_",0 }, +{ KBDWIDTH,"=",0x18,"+",0 }, +{ KBDWIDTHTAB,"delete",0x33,0,0 }, +{ -1,0,0,0,0 }, +{ KBDWIDTHTAB,"tab",0x30,0,0 }, +{ KBDWIDTH,"q",0x0C,"Q",0 }, +{ KBDWIDTH,"w",0x0D,"W",0 }, +{ KBDWIDTH,"e",0x0E,"E",0 }, +{ KBDWIDTH,"r",0x0F,"R",0 }, +{ KBDWIDTH,"t",0x11,"T",0 }, +{ KBDWIDTH,"y",0x10,"Y",0 }, +{ KBDWIDTH,"u",0x20,"U",0 }, +{ KBDWIDTH,"i",0x22,"I",0 }, +{ KBDWIDTH,"o",0x1F,"O",0 }, +{ KBDWIDTH,"p",0x23,"P",0 }, +{ KBDWIDTH,"[",0x21,"{",0 }, +{ KBDWIDTH,"]",0x1E,"}",0 }, + { KBDWIDTHTAB,"menu",-1,0,0 }, +{ -1,0,0,0,0 }, +{ KBDWIDTHCTRL,"control",0x36,0,0 }, +{ KBDWIDTH,"a",0x00,"A",0 }, +{ KBDWIDTH,"s",0x01,"S",0 }, +{ KBDWIDTH,"d",0x02,"D",0 }, +{ KBDWIDTH,"f",0x03,"F",0 }, +{ KBDWIDTH,"g",0x05,"G",0 }, +{ KBDWIDTH,"h",0x04,"H",0 }, +{ KBDWIDTH,"j",0x26,"J",0 }, +{ KBDWIDTH,"k",0x28,"K",0 }, +{ KBDWIDTH,"l",0x25,"L",0 }, +{ KBDWIDTH,";",0x29,":",0 }, +{ KBDWIDTH,"'",0x27,"\"",0 }, +{ KBDWIDTHRET,"return",0x24,0,0 }, +{ -1,0,0,0,0 }, + { KBDWIDTHSHIFT,"shift",0x38,0,0 }, + { KBDWIDTH,"z",0x06,"Z",0 }, + { KBDWIDTH,"x",0x07,"X",0 }, + { KBDWIDTH,"c",0x08,"C",0 }, + { KBDWIDTH,"v",0x09,"V",0 }, + { KBDWIDTH,"b",0x0B,"B",0 }, + { KBDWIDTH,"n",0x2D,"N",0 }, + { KBDWIDTH,"m",0x2E,"M",0 }, + { KBDWIDTH,",",0x2B,"<",0 }, + { KBDWIDTH,".",0x2F,">",0 }, + { KBDWIDTH,"/",0x2C,"?",0 }, + { KBDWIDTHSHIFT,"shift",0x38,0,0 }, + { -1,0,0,0,0 }, + { KBDWIDTH,"caps",0x39,0,0 }, + { KBDWIDTH,"option",0x37,0,0 }, + { KBDWIDTHAPPLE,"",0x3A,0,0 }, + { KBDWIDTH,"`",0x12,0,0 }, + { KBDWIDTHSPACE," ",0x31,0,0 }, + { KBDWIDTH,"x",0x13,0,0 }, + { KBDWIDTH,"->",0x3C,0,0 }, + { KBDWIDTH,"<-",0x3B,0,0 }, + { KBDWIDTH,"^",0x5B,0,0 }, + { KBDWIDTH,"v",0x13,0,0 }, + + { 0,0,0,0,0 } + +}; + +static kbdselected* sharedKBDSelected = nil; + +int findCode(const char* _s) +{ + int i =0; + while(kbdDefinitions[i].w) + { + if (kbdDefinitions[i].k1 && !strcmp(kbdDefinitions[i].k1,_s)) + return kbdDefinitions[i].code1; + if (kbdDefinitions[i].k2 && !strcmp(kbdDefinitions[i].k2,_s)) + return (kbdDefinitions[i].code1 + shiftKey); + i++; + } + return -1; + +} + +@implementation kbdselected + + +- (void)drawRect:(CGRect)rect { + // Drawing code + CGContextRef g = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(g, [UIColor whiteColor].CGColor); + CGContextFillRect(g, rect); + + //draw text in black. + CGContextSetFillColorWithColor(g, [UIColor blackColor].CGColor); + int size; + NSString* str = [NSString stringWithFormat:@"%s", v]; + + if ([str length]==1) + size =12; + else { + size = 8; + } + + [str drawAtPoint:CGPointMake(2.0, 2.0) withFont:[UIFont systemFontOfSize:size]]; + +} + +- (void) setParam: (const char*)_v +{ + v = _v; +} + ++ (kbdselected*)getSelected { + return sharedKBDSelected; +} +@end + + +@implementation kbdlayout + + +- (id)initWithFrame:(CGRect)frame { + + if (self = [super initWithFrame:frame]) { + // Initialization code + + int y = 1; + int x = 0; + int i = 0; + int w; + while( w = kbdDefinitions[i].w ) + { + if (w==-1) + { + x=0; + y+=KBDHEIGHT; + } + kbdDefinitions[i].posx = x; + kbdDefinitions[i].posy = y; + + CGRect r = CGRectMake(x,y,w,KBDHEIGHT); + x += w/*+1*/; + keyboard * kbd = [[keyboard alloc] initWithFrame:r]; + [kbd setUserInteractionEnabled:FALSE]; + [kbd setParam:kbdDefinitions[i].k1]; + [self addSubview:kbd]; + [kbd release]; + i++; + } + + CGRect r = CGRectMake(100,100,32.0,30.0); + kbdselected * sel = [[kbdselected alloc] initWithFrame:r]; + [sel setUserInteractionEnabled:FALSE]; + sharedKBDSelected = sel; + sel.hidden = true; + iKbd = 0; + [self addSubview:sel]; + [sel release]; + + + } + return self; +} + + +- (void)drawRect:(CGRect)rect { + // Drawing code + CGContextRef g = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(g, [UIColor whiteColor].CGColor); + CGContextFillRect(g, rect); +} + + +- (void)dealloc { + [super dealloc]; +} + +int findKey(int _x,int _y) +{ + int found=0; + int posx,posy; + // cherche le clavier le plus proche + int i = 0; + int w; + while( w = kbdDefinitions[i].w ) + { + if (w==-1) + continue; + posx = kbdDefinitions[i].posx ; + posy = kbdDefinitions[i].posy ; + if (_x>=posx && _x<(posx+w) && _y>=posy && _y<(posy+KBDHEIGHT)) + { + found = i; + break; + } + i++; + } + return found; +} + +- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + CGPoint pt = [[touches anyObject] locationInView:self]; + + int i = findKey(pt.x,pt.y); + if (iKbd && i != iKbd) + [self touchesEnded:touches withEvent:event]; + + if (!i) + { + iKbd = 0; + return ; + } + + if (i==iKbd) + return ; + iKbd= i; + + printf("Down : %s (%X)\n",kbdDefinitions[i].k1,kbdDefinitions[i].code1); + if (kbdDefinitions[i].code1==-1) + { + + // activegsList* vl = nil; + // UIView* vl = [[[pManager getBrowserView]viewList]view]; + [pManager doStateChange:[pManager getBrowserView] sens:kCATransitionFromRight]; + return ; + } + add_event_key(kbdDefinitions[i].code1,0); + + int posx = kbdDefinitions[i].posx ; + int posy = kbdDefinitions[i].posy ; + +// startLocation = pt; + kbdselected* sel =[kbdselected getSelected]; + [[self superview] bringSubviewToFront:sel]; + CGRect frame = [self frame]; + CGRect framesel = [sel frame]; + + framesel.origin.x =/* frame.origin.x + */posx,0; + framesel.origin.y = /*frame.origin.y +*/ posy - 30.0; + + /* + framesel.origin.x = pt.x -10,0; + framesel.origin.y = pt.y - 50.0; + */ + framesel.size.width = kbdDefinitions[i].w; +// framesel.size.height = frame.size.height*2.0; + [sel setFrame:framesel]; + + [sel setParam:kbdDefinitions[i].k1]; + [sel setNeedsDisplay]; + sel.hidden=false; + +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + + kbdselected* sel =[kbdselected getSelected]; + sel.hidden=true; + if (iKbd) + { + add_event_key(kbdDefinitions[iKbd].code1,1); + printf("Up : %s (%x)\n",kbdDefinitions[iKbd].k1,kbdDefinitions[iKbd].code1); + } + iKbd= 0; +} + + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self touchesBegan:touches withEvent:event]; + + + +} + + +@end diff --git a/Common.iphone/keyboard.h b/Common.iphone/keyboard.h new file mode 100644 index 0000000..bdb158e --- /dev/null +++ b/Common.iphone/keyboard.h @@ -0,0 +1,29 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + +struct kbdDefinition +{ + int w; + const char* k1; + int code1; + const char* k2; + int code2; + int posx,posy; +}; + +extern struct kbdDefinition kbdDefinitions[]; + +#define KBDHEIGHT 20 + +@interface keyboard : UIView { + CGPoint startLocation; + const char* v; +} +- (void)setParam:(const char*) _v; + +@end diff --git a/Common.iphone/keyboard.mm b/Common.iphone/keyboard.mm new file mode 100644 index 0000000..ce70a1a --- /dev/null +++ b/Common.iphone/keyboard.mm @@ -0,0 +1,109 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "keyboard.h" +#import "kbdlayout.h" + + +@implementation keyboard + + +- (id)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + // Initialization code + } + return self; +} + +- (void)setParam:(const char*) _v +{ + v = _v; + +} + +- (void)drawRect:(CGRect)rect { + // Drawing code + CGContextRef g = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(g, [UIColor grayColor].CGColor); + CGContextFillRect(g, rect); + + //draw text in black. + CGContextSetFillColorWithColor(g, [UIColor blackColor].CGColor); + int size; + NSString* str = [NSString stringWithFormat:@"%s", v]; + if ([str length]==1) + size =12; + else { + size = 8; + } + + [str drawAtPoint:CGPointMake(2.0, 2.0) withFont:[UIFont systemFontOfSize:size]]; + + +} + + +- (void)dealloc { + [super dealloc]; +} + +- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + CGPoint pt = [[touches anyObject] locationInView:self]; + startLocation = pt; + kbdselected* sel =[kbdselected getSelected]; + [[self superview] bringSubviewToFront:sel]; + CGRect frame = [self frame]; + CGRect framesel = [sel frame]; + + + framesel.origin.x = frame.origin.x -10,0; + framesel.origin.y = frame.origin.y - 40.0; + + /* + framesel.origin.x = pt.x -10,0; + framesel.origin.y = pt.y - 50.0; + */ + framesel.size.width = frame.size.width * 2.0; + framesel.size.height = frame.size.height*2.0; + [sel setFrame:framesel]; + + [sel setParam:v]; + [sel setNeedsDisplay]; + sel.hidden=false; + +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + kbdselected* sel =[kbdselected getSelected]; + sel.hidden=true; + /* + CGRect frame = [self frame]; + frame.origin.x += 10.0; + frame.origin.y += 30.0; + frame.size.width /=2.0; + frame.size.height /=2.0; + [self setFrame:frame]; + */ +} + + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + /* + CGPoint pt = [[touches anyObject] locationInView:self]; + CGRect frame = [self frame]; + frame.origin.x += pt.x - startLocation.x; + frame.origin.y += pt.y - startLocation.y; + [self setFrame:frame]; + */ + + +} + +@end diff --git a/Common.iphone/logo_apple2.png b/Common.iphone/logo_apple2.png new file mode 100644 index 0000000..5dba7d6 Binary files /dev/null and b/Common.iphone/logo_apple2.png differ diff --git a/Common.iphone/logo_apple2.psd b/Common.iphone/logo_apple2.psd new file mode 100644 index 0000000..a66caef Binary files /dev/null and b/Common.iphone/logo_apple2.psd differ diff --git a/Common.iphone/logo_apple2@2x.png b/Common.iphone/logo_apple2@2x.png new file mode 100644 index 0000000..5dba7d6 Binary files /dev/null and b/Common.iphone/logo_apple2@2x.png differ diff --git a/Common.iphone/logo_apple2gs.png b/Common.iphone/logo_apple2gs.png new file mode 100644 index 0000000..585ee8d Binary files /dev/null and b/Common.iphone/logo_apple2gs.png differ diff --git a/Common.iphone/mouseView.h b/Common.iphone/mouseView.h new file mode 100644 index 0000000..1be5292 --- /dev/null +++ b/Common.iphone/mouseView.h @@ -0,0 +1,14 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import + + +@interface mouseView : UIView { + CGPoint pt; +} + +@end diff --git a/Common.iphone/mouseView.mm b/Common.iphone/mouseView.mm new file mode 100644 index 0000000..2343627 --- /dev/null +++ b/Common.iphone/mouseView.mm @@ -0,0 +1,56 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import "mouseView.h" +#include "emulatorView.h" + +@implementation mouseView + + +- (id)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + // Initialization code + } + return self; +} + + +- (void)drawRect:(CGRect)rect { + // Drawing code +} + +/* +- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + pt = [[touches anyObject] locationInView:self]; + + +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + + } + + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self touchesBegan:touches withEvent:event]; + + CGPoint ptdef = [[touches anyObject] locationInView:self]; + //CGPoint delta = ptdef - pt; + mac_add_event_mouse(ptdef.x-pt.x,ptdef.y-pt.y,0,1); + +} +*/ + +- (void)dealloc { + [super dealloc]; +} + + +@end diff --git a/Common.iphone/parametersView.xib b/Common.iphone/parametersView.xib new file mode 100644 index 0000000..2b55469 --- /dev/null +++ b/Common.iphone/parametersView.xib @@ -0,0 +1,272 @@ + + + + 1056 + 10H574 + 823 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 132 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + YES + + + 292 + {{196, 20}, {94, 27}} + + NO + IBCocoaTouchFramework + 0 + 0 + YES + + + + 292 + {{37, 20}, {91, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Music + + 1 + MCAwIDAAA + + + 3 + MQA + + 1 + 10 + + + + 292 + {{194, 72}, {98, 23}} + + NO + IBCocoaTouchFramework + 0 + 0 + 1 + 2 + NO + + + + 292 + {{37, 72}, {101, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Refresh Rate + + + 1 + 10 + + + + 292 + {{37, 119}, {145, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Reload Documents + + + 1 + 10 + + + {320, 460} + + + 3 + MQA + + 2 + + + + IBCocoaTouchFramework + + + + + YES + + + + YES + + 0 + + + + + + 1 + + + YES + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + + + YES + + YES + -2.CustomClassName + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 3.IBPluginDependency + 3.IBViewBoundsToFrameTransform + 4.IBPluginDependency + 5.IBPluginDependency + 5.IBViewBoundsToFrameTransform + 6.IBPluginDependency + 6.IBViewBoundsToFrameTransform + 7.IBPluginDependency + 7.IBViewBoundsToFrameTransform + + + YES + UIResponder + {{354, 376}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDRAAAwjQAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDQgAAwrgAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCFAAAwrQAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCFAAAwwAAAA + + + + + YES + + + YES + + + + + YES + + + YES + + + + 8 + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + + 3 + 132 + + diff --git a/Common.osx/ActiveDownloadMac.cpp b/Common.osx/ActiveDownloadMac.cpp new file mode 100644 index 0000000..76c0ad8 --- /dev/null +++ b/Common.osx/ActiveDownloadMac.cpp @@ -0,0 +1,354 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../common.osx/cemulatorctrlmac.h" +#include "activedownload.h" +#include +#include +#include "../common/ki.h" +#include "../kegs/Src/sim65816.h" + +#ifdef DRIVER_IOS +#include +#include +#include +#endif + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +#define ACTIVEGSDOMAIN kUserDomain +MyString homePath; + +extern const char * activegsdownloaddir; +extern const char * activegspersistentdir; + +#define MAX_PATH 1024 + +bool CDownload::GetFile( const char *url, const char *filename) +{ + + bool bSuccess=false; + + CFStringRef rawCFString=NULL; + CFStringRef normalizedCFString=NULL; + CFStringRef escapedCFString=NULL; + CFURLRef urlRef=NULL; + CFHTTPMessageRef messageRef = NULL; + CFReadStreamRef readStreamRef = NULL; + + #define HTTPBUFLEN 4096 + UInt8 httpbuff[HTTPBUFLEN]; + CFIndex numbytes ; + FILE* f = NULL; + int nbread=0; + int dwLength = 0 ; + int pourcent=0; + MyString str; + + if (filename) + showProgress(url,0); + + if ( strlen( url ) < 12 ) + goto Bail; + + rawCFString = CFStringCreateWithCString( NULL, url, CFStringGetSystemEncoding() ); + if ( rawCFString == NULL ) goto Bail; + normalizedCFString = CFURLCreateStringByReplacingPercentEscapes( NULL, rawCFString, CFSTR("") ); + if ( normalizedCFString == NULL ) goto Bail; + escapedCFString = CFURLCreateStringByAddingPercentEscapes( NULL, normalizedCFString, NULL, NULL, kCFStringEncodingUTF8 ); + if ( escapedCFString == NULL ) goto Bail; + + urlRef= CFURLCreateWithString( kCFAllocatorDefault, escapedCFString, NULL ); + + CFRelease( rawCFString ); + CFRelease( normalizedCFString ); + CFRelease( escapedCFString ); + if ( urlRef == NULL ) + { + goto Bail; + } + + messageRef = CFHTTPMessageCreateRequest( kCFAllocatorDefault, CFSTR("GET"), urlRef, kCFHTTPVersion1_1 ); + if ( messageRef == NULL ) goto Bail; + + + CFRelease(urlRef); + urlRef = NULL; + + // Create the stream for the request. + readStreamRef = CFReadStreamCreateForHTTPRequest( kCFAllocatorDefault, messageRef ); + if ( readStreamRef == NULL ) goto Bail; + + + if (!CFReadStreamOpen(readStreamRef)) + goto Bail; + /* + tr = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStreamRef, kCFStreamPropertyHTTPResponseHeader); + if (tr) + { + sizeStr = CFHTTPMessageCopyHeaderFieldValue (tr, CFSTR("Content-Length")); + if (sizeStr) + str = CFStringGetCStringPtr(sizeStr,CFStringGetSystemEncoding()); + } + */ + + + + if (filename) + { + f =fopen(filename,"wb"); + if (!f) + { + printf("cannot write file %s\n",filename); + goto Bail; + } + } + + + while ( (numbytes = CFReadStreamRead (readStreamRef,httpbuff,HTTPBUFLEN ) ) != 0 ) + { + + /* + tr = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStreamRef, kCFStreamPropertyHTTPResponseHeader); + if (tr) + { + dic = CFHTTPMessageCopyAllHeaderFields (tr); + + char *the_pcKeys[50],*the_pcValues[50]; + + CFDictionaryGetKeysAndValues(dic, (const void + **)&the_pcKeys, (const void **)&the_pcValues); + + sizeStr = CFHTTPMessageCopyHeaderFieldValue (tr, CFSTR("Content-Length")); + if (sizeStr) + str = CFStringGetCStringPtr(sizeStr,CFStringGetSystemEncoding()); + } + */ + + if (numbytes<0) + { + // CFErrorRef err = CFReadStreamCopyError (readStreamRef); + + goto Bail; + } + nbread+=numbytes; + + if (f) + fwrite(httpbuff,1,numbytes,f); + + if (dwLength) + pourcent = (nbread*100)/dwLength; + else + pourcent = -nbread ; //(pourcent+5)%100; + + if (filename) + showProgress(url,pourcent); + if (r_sim65816.should_emulator_terminate()) + { + outputInfo("Download aborted (%s)\n",url); + goto Bail; + } + //usleep(2000); + } + + if (nbread) + bSuccess=true; + + { + Bail: + { + if (f) fclose(f); + if (filename && !bSuccess) deleteFile(filename); + + if ( messageRef != NULL ) CFRelease( messageRef ); + if ( readStreamRef != NULL ) + { + //CFReadStreamSetClient( readStreamRef, kCFStreamEventNone, NULL, NULL ); + //CFReadStreamUnscheduleFromRunLoop( readStreamRef, CFRunLoopGetCurrent(), kCFRunLoopCommonModes ); + CFReadStreamClose( readStreamRef ); + CFRelease( readStreamRef ); + } + if ( urlRef != NULL ) + CFRelease( urlRef ); + + } + } +#ifdef DRIVER_IOS + if (!bSuccess && bNotifyDownloadFailure) + { + extern void x_notify_download_failure(const char*); + x_notify_download_failure(url); + } +#endif + return bSuccess; +} + +bool CDownload::retrievePersistentZippedFile(const char* url,int _order,MyString& _path, MyString& _short) +{ + + MyString dir = getPersistentDir(url); + DIR* pdir = opendir(dir.c_str()); + if (!pdir) + return false; + struct dirent* dp; + MyString search; + search.Format("%d_",_order); + while( (dp=readdir(pdir)) != NULL ) + { + if (strstr(dp->d_name,search.c_str())==dp->d_name) + { + _path = dir; + _path += ACTIVEGS_DIRECTORY_SEPARATOR ; + _path += dp->d_name ; + _short = dp->d_name; + closedir(pdir); + return true; + } + } + closedir(pdir); + return false; + +} + + +void CDownload::deleteFile(const char* _dir) +{ + remove(_dir); + +} + +void CDownload::deleteDirectory(const char* _dir,int keepdir) +{ + + DIR* pdir = opendir(_dir); + if (!pdir) + return ; + struct dirent* dp; + while( (dp=readdir(pdir)) != NULL ) + { + MyString name=_dir; + name+=ACTIVEGS_DIRECTORY_SEPARATOR; + name+=dp->d_name; + printf("delete file:%s\n",name.c_str()); + deleteFile(name.c_str()); + } + closedir(pdir); + + if (!keepdir) + rmdir(_dir); + +} + +void CDownload::createDirectory(const char *_subdir) +{ + +#ifdef DRIVER_IOS + // rend le chemin absolu + if (strstr(_subdir,homePath.c_str())==_subdir) + _subdir += homePath.length()+1; + MyString fullpath(homePath.c_str()); + fullpath+='/'; + fullpath+=_subdir; + if (mkdir(fullpath.c_str(),0777)) + { + // printf("cannot create %s\n",fullpath.c_str()); + } +#else + UniChar nameData[1024]; + OSStatus err; + FSRef domain; + + // limine le chemin absolu + if (strstr(_subdir,homePath.c_str())==_subdir) + _subdir += homePath.length()+1; + + err = FSFindFolder(kUserDomain, kDomainTopLevelFolderType ,kDontCreateFolder, &domain); + + const char* file = getfile(_subdir); + // cherche le chemin parent + if (file!=_subdir) + { + + MyString dir; + UniChar ename[1024]; + FSRef subdomain; + + getdir(_subdir,dir); + CFStringRef ed = __CFStringMakeConstantString(dir.c_str()); + int l = CFStringGetLength(ed); + CFStringGetCharacters(ed, CFRangeMake(0, l), ename); + + err = FSMakeFSRefUnicode (&domain, l, (const UniChar*)ename,0,&subdomain); + + domain = subdomain; + _subdir = file; + } + + + CFStringRef sd = __CFStringMakeConstantString(_subdir); + int lend = CFStringGetLength(sd); + CFStringGetCharacters(sd, CFRangeMake(0, lend), nameData); + err = FSCreateDirectoryUnicode(&domain, lend, nameData, 0, NULL, NULL, NULL, NULL); + if (err !=0) + printf("cannot create %s\n",_subdir); + else + printf("%s created\n",_subdir); + +#endif +} + + +void CDownload::initPersistentSystemPath(MyString& path) +{ + + extern void x_init_persistent_path(MyString& hp); + + x_init_persistent_path(homePath); + + if (homePath.GetAt(homePath.GetLength()-1)=='/') + { + MyString tmp (homePath.Left(homePath.GetLength()-1)); + homePath = tmp; + } + + path = homePath; + /* + CDownload::createDirectory(activegspersistentdir); + + MyString c; + c = activegspersistentdir; + c +='/'; + c += activegsdownloaddir ; + + CDownload::createDirectory(c.c_str()); + + persistentPath = homePath.c_str() ; + persistentPath += '/'; + persistentPath += activegspersistentdir; + + printf("mac persistent directory :%s\n",persistentPath.c_str()); +// CDownload::setPersistentPath(persistentPath.c_str()); + */ +} + +#ifndef DRIVER_IOS +void x_init_persistent_path(MyString& hp) +{ + + OSStatus err; + FSRef homeDir; + + err = FSFindFolder(ACTIVEGSDOMAIN, kDomainTopLevelFolderType,kDontCreateFolder, &homeDir); + + CFURLRef url = CFURLCreateFromFSRef (NULL,&homeDir); + + CFStringRef fullpath = CFURLCopyFileSystemPath (url,kCFURLPOSIXPathStyle); + + hp = CFStringGetCStringPtr(fullpath,CFStringGetSystemEncoding()); +} +#endif \ No newline at end of file diff --git a/Common.osx/CEmulatorCtrlMac.cpp b/Common.osx/CEmulatorCtrlMac.cpp new file mode 100644 index 0000000..ca6ecc0 --- /dev/null +++ b/Common.osx/CEmulatorCtrlMac.cpp @@ -0,0 +1,191 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../common.osx/CEmulatorCtrlMac.h" +#include "../common/svnversion.h" +#include +#include "../kegs/Src/sim65816.h" +#include +extern int macUsingCoreGraphics; + +extern int calcCRC(const char* ptr); + + + +#undef printf +extern "C" int outputInfo(const char* format,...) +{ + va_list argptr; + va_start( argptr, format ); + MyString st; + st.FormatV(format,argptr); + va_end(argptr); + puts(st.c_str()); + return 1; +} + +int outputInfoInternal(const char* _str) +{ + puts(_str); + return 1; +} + +extern "C" int fOutputInfo(FILE*,const char* format,...) +{ + return 1; +} + +#define printf outputInfo + + +void* PosixThreadMainRoutine(void* data) +{ + CEmulatorMac* p = (CEmulatorMac*)data; + p->theThread(); + return NULL; +} + + + +void CEmulatorMac::x_LaunchThread() +{ + + +// lance le thread +pthread_attr_t attr; +pthread_t posixThreadID; + +assert(!pthread_attr_init(&attr)); +assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); + +/*int threadError =*/ pthread_create(&posixThreadID, &attr, &PosixThreadMainRoutine, this); + +assert(!pthread_attr_destroy(&attr)); +} + +void CEmulatorMac::x_WaitForEndThread() +{ + while(bInThread) + usleep(100); + +} + + + +extern void my_exit(int); + + +void mac_get_resource_path(const char *_path,MyString& _resPath) +{ + CFURLRef resourceURL; + _resPath.Empty(); + + // Look for the resource in the main bundle by name and type. + +#ifdef ACTIVEGSPLUGIN + CFBundleRef bundle = CFBundleGetBundleWithIdentifier(__CFStringMakeConstantString("com.freetoolsassociation.activegs")); +#else + CFBundleRef bundle = CFBundleGetMainBundle(); + +#endif + CFStringRef ce = CFStringCreateWithCString( + NULL, + _path, + kCFStringEncodingASCII); + resourceURL = CFBundleCopyResourceURL( + bundle, + ce, + NULL, + NULL + ); + + if(!resourceURL) + { + printf("Failed to locate a file in the loaded bundle! (%s)",_path); + return; + } + + char fileurl[1024]; + + if(!CFURLGetFileSystemRepresentation( + resourceURL, + true, + (UInt8*) + fileurl, + 1024)) + + { + printf("Failed to turn a bundle resource URL into a filesystem path representation!"); + return; + } + + + + _resPath = fileurl; + + +} + + +CEmulatorMac::CEmulatorMac(CEmulator** _parent, int _usingCoreGraphics,PluginInstance* _pi) : CEmulator(_parent) +{ + + + macUsingCoreGraphics = _usingCoreGraphics; + pi = _pi; + + +} + + + +CEmulatorMac::~CEmulatorMac() +{ + outputInfo("~CEmulatorMac (%X)\n",this); +} + +void CEmulatorMac::loadingInProgress(int _motorOn,int _slot, int _drive) +{ +#ifdef DRIVER_IOS + extern void x_loadinginprogress(int,int,int); + x_loadinginprogress(_motorOn,_slot,_drive); +#endif +} + +void CEmulatorMac::getEngineString(MyString& engine) +{ + + if (macUsingCoreGraphics) + { +#if defined(ACTIVEGSPLUGIN) && !defined(DRIVER_IOS) + if (isEventCocoa) + engine="CG/Cocoa"; + else + engine="CG/Carbon"; +#else + engine="CG"; +#endif + } + else + engine = "QD"; +} + +void CEmulatorMac::showStatus(const char* _str) +{ +#ifdef ACTIVEGSPLUGIN + extern MyString messageLine; + extern int messageLineVBL; + + messageLine = _str; + if (_str) + { + messageLineVBL=100; + x_refresh_video(); + } + +#endif +} + diff --git a/Common.osx/CEmulatorCtrlMac.h b/Common.osx/CEmulatorCtrlMac.h new file mode 100644 index 0000000..aefff3e --- /dev/null +++ b/Common.osx/CEmulatorCtrlMac.h @@ -0,0 +1,70 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + + +#if defined(__LP64__) || defined(DRIVER_IOS) || defined(ACTIVEGSPLUGIN) || defined(ACTIVEGSCOCOA) +#else + #define ENABLEQD +#endif + +#ifndef DRIVER_IOS +#ifdef ACTIVEGSPLUGIN +#include "../common.xpi/npapiPlugin.h" +#endif +#endif + +#include "../Common/CEmulatorCtrl.h" + +#ifdef DRIVER_IOS + +#include +#include +#include +//extern void retrievePersistentPath(MyString&,CFStringRef); +#else +#include +#include +#include +extern int isEventCocoa; +//extern void retrievePersistentPath(MyString&); +#endif + +void x_invalidrect(); +//extern int x_video_need_to_be_refreshed; + +#ifdef ENABLEQD +extern CGrafPtr mac_window_port; +#endif + +class PluginInstance; + +class CEmulatorMac : public CEmulator +{ +public: +// int usingCoreGraphics; + PluginInstance* pi; + CGContextRef theContext; +// void* npWindow; +#ifdef ENABLEQD + CGrafPtr window_port; +#endif + int bInit; +// virtual void writeOptions(COption& _option); +// virtual COption loadOptions() ; +// virtual void x_terminateEmulator(); +// virtual void x_launchEmulator(); + // To be defined in son + virtual void x_LaunchThread() ; + virtual void x_WaitForEndThread() ; + + CEmulatorMac(CEmulator** _parent, int usingCoreGraphics=0,PluginInstance* pi=NULL); + void getEngineString(MyString& engine); + virtual void loadingInProgress(int _motorOn,int _slot, int _drive); + virtual void showStatus(const char* _msg) ; + ~CEmulatorMac(); +}; \ No newline at end of file diff --git a/Common.res/ActiveGS.png b/Common.res/ActiveGS.png new file mode 100644 index 0000000..1504cb8 Binary files /dev/null and b/Common.res/ActiveGS.png differ diff --git a/Common.res/Apple_2_Disk_Drive_Sounds.txt b/Common.res/Apple_2_Disk_Drive_Sounds.txt new file mode 100644 index 0000000..558075c --- /dev/null +++ b/Common.res/Apple_2_Disk_Drive_Sounds.txt @@ -0,0 +1,130 @@ + +Apple 2 Disk Drive Sounds Copyright (C) Moose O'Malley, +-------------------------- January 2011. + + +===========================================================+ + | T A B L E O F C O N T E N T S | + +===========================================================+ + | * Introduction | + | * Other Projects Using These Sounds | + | * License / Limitations / Restrictions | + | * Amendment History | + | * Contacting the Program's Author | + +===========================================================+ + +Introduction : +-------------- + +This ZIP file contains the Apple 2 disk drive sounds that I recorded for +use with my "Apple 2 Disk Drive Sound Simulator" program (Windows 95 / 98 / +ME / NT / 2000 / XP, Vista, etc). + + + +About the Disk Drive Sounds: (from my "Apple 2 Disk Drive Sound Simulator" program's readme). +----------------------------- + +As people may know from the Apple 2 Emulation section of my WEB pages : + + At the best of times, the Apple 2 disk drive used to make horrible + grunting and scrapping sounds as it loaded programs. When I used to go + to the local Burleigh Heads library and used the Apple 2 there, everyone + in the library would stop and stare (and sometimes glare !) at us + whenever the Apple 2 was reading floppy disks - the grunts and groans + from the drive were *that* loud !! + + N.B. These terrible sounds were perfectly normal for Apple 2 drives, + and they were quite loud as well, even when using brand new floppy + disks and brand new floppy drives. + +However, people today didn't believe me about the sounds or how loud they +really were. + +So now, a short MP3 of some Apple 2 disk drive sounds is available from my +WEB page. + +And, in addition, I have written this program to simulate some Apple 2 +disk drive sounds. + +All of the Apple 2 disk drive sounds were recorded by me on April 10 and 11, +2000. To record the sounds, I used a cheap microphone hooked up to my +Windows 98 PC, which was running Goldwave a good sound editing program. +I placed the microphone at the entrance to the Apple 2 floppy drive, and +then proceeded to record the loading sounds the drive made for a bunch +of games and programs. (I own an Apple ][c with both internal and +external drives). + +Finally, in December 2001, I again listened carefully to the sounds I recorded +18 months ago, and edited out some of the more common sound bytes. + +Then, I wrote a Delphi program to play them back, and compiled all of the +sounds into a single resource file, which was later compiled and compressed +into the Executable program. That is why there are no WAV files accompanying +this program - they are all contained inside the EXE file !! (See my +"Apple 2 Disk Drive Sound Simulator" program). + +The "squeak" was a sound that the disk drive makes very occassionally +when (I think) it is swinging its read head backwards and forwards +very quickly and the rubber belt slips - not sure about how it happens +but it does happen. It is definitely a sound the drive makes - not +the door on the drive. I rember it happening on all of the Apple ]['s I +used in the early 1980's and it still happens on my Apple ][c - but it is +very occasional. + +The "Ghostbusters" digitised speech sound is not a disk drive sound, +but I thought it would be fun to add this sound in as well to show +what digitised speech on the Apple ][ sounded like. Back in the +early 80's, this speech was state of the art and I remember +times when people used to crowd around my Apple ][ just to +hear it say "Ghostbusters" !! + + +Other Projects Using These Sounds : +------------------------------------ + +See the readme file that accompanies my "Apple 2 Disk Drive Sound Simulator" +program. + + +License / Limitations / Restrictions : +--------------------------------------- + +These sounds are freeware - which means they are copyrighted, but +any person and any company is welcome to use them in your own programs / +projects, subject to one condition. + +I am a friendly guy and I like supporting / helping other software +developers. If you want to use these sounds in your own programs / +projects, then that is fine: all I ask is that you add a credit to me +on your projects's web page, the credits screen, the help file, +or similar. A credit something like this would be perfect: + + Apple ][ disk drive sounds courtesy of + Moose's Software Valley: http://move.to/moose + +Please don't just rip off my work / take my work without giving me +any credit. + +Hope this is OK. + +Long Live the Apple ][ !!! + + +Amendment History : +-------------------- + +Vers Date Description + +1.0 25-Jan-2011 First Public Release of these sounds on their own. + + +If this ZIP file was not downloaded from my Home Page, then +it is possibly an old version. The latest version of this +ZIP file is available from my WEB page - see below. + + Mike "Moose" O'Malley +____________________________________________________ + Moose's Software Valley - Established July, 1996. + WEB: http://move.to/moose +____________________________________________________ + \ No newline at end of file diff --git a/Common.res/Search Skip Search 1.wav b/Common.res/Search Skip Search 1.wav new file mode 100644 index 0000000..ca203f6 Binary files /dev/null and b/Common.res/Search Skip Search 1.wav differ diff --git a/Common.res/Search Skip Search 2.wav b/Common.res/Search Skip Search 2.wav new file mode 100644 index 0000000..0d87532 Binary files /dev/null and b/Common.res/Search Skip Search 2.wav differ diff --git a/Common.res/Search Skip Search 3.wav b/Common.res/Search Skip Search 3.wav new file mode 100644 index 0000000..fbab1d3 Binary files /dev/null and b/Common.res/Search Skip Search 3.wav differ diff --git a/Common.res/Search Skip Search 4.wav b/Common.res/Search Skip Search 4.wav new file mode 100644 index 0000000..a4240a7 Binary files /dev/null and b/Common.res/Search Skip Search 4.wav differ diff --git a/Common.res/Search Skip Search 5.wav b/Common.res/Search Skip Search 5.wav new file mode 100644 index 0000000..e111207 Binary files /dev/null and b/Common.res/Search Skip Search 5.wav differ diff --git a/Common.res/ShastonHi640.ttf b/Common.res/ShastonHi640.ttf new file mode 100644 index 0000000..ff6148e Binary files /dev/null and b/Common.res/ShastonHi640.ttf differ diff --git a/Common.res/Spin Up Search 1.wav b/Common.res/Spin Up Search 1.wav new file mode 100644 index 0000000..468f6f7 Binary files /dev/null and b/Common.res/Spin Up Search 1.wav differ diff --git a/Common.res/Spin Up Search 2.wav b/Common.res/Spin Up Search 2.wav new file mode 100644 index 0000000..a822ac0 Binary files /dev/null and b/Common.res/Spin Up Search 2.wav differ diff --git a/Common.res/disk.png b/Common.res/disk.png new file mode 100644 index 0000000..ee4625f Binary files /dev/null and b/Common.res/disk.png differ diff --git a/Common.res/disk_35_1.png b/Common.res/disk_35_1.png new file mode 100644 index 0000000..14a5faf Binary files /dev/null and b/Common.res/disk_35_1.png differ diff --git a/Common.res/disk_35_2.png b/Common.res/disk_35_2.png new file mode 100644 index 0000000..54b2624 Binary files /dev/null and b/Common.res/disk_35_2.png differ diff --git a/Common.res/disk_525_1.png b/Common.res/disk_525_1.png new file mode 100644 index 0000000..0a82d03 Binary files /dev/null and b/Common.res/disk_525_1.png differ diff --git a/Common.res/disk_525_2.png b/Common.res/disk_525_2.png new file mode 100644 index 0000000..dd35512 Binary files /dev/null and b/Common.res/disk_525_2.png differ diff --git a/Common.res/facebook-logo.png b/Common.res/facebook-logo.png new file mode 100644 index 0000000..7d723bd Binary files /dev/null and b/Common.res/facebook-logo.png differ diff --git a/Common.res/floppy_eject.wav b/Common.res/floppy_eject.wav new file mode 100644 index 0000000..770bdd3 Binary files /dev/null and b/Common.res/floppy_eject.wav differ diff --git a/Common.res/logo_apple2.png b/Common.res/logo_apple2.png new file mode 100644 index 0000000..5dba7d6 Binary files /dev/null and b/Common.res/logo_apple2.png differ diff --git a/Common.res/logo_apple2gs.png b/Common.res/logo_apple2gs.png new file mode 100644 index 0000000..585ee8d Binary files /dev/null and b/Common.res/logo_apple2gs.png differ diff --git a/Common/3rdpartylib/simplexml.cpp b/Common/3rdpartylib/simplexml.cpp new file mode 100644 index 0000000..354462a --- /dev/null +++ b/Common/3rdpartylib/simplexml.cpp @@ -0,0 +1,567 @@ +/***************************************************************************** + + This file is part of SimpleXML, a simplified C++ tree based parser + of XML 1.0 documents. + Copyright (C) 2003 by Brian Ecker. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*****************************************************************************/ + +#include +#include + +#include "simplexml.h" +#include "../cemulatorctrl.h" + + +#undef debug_printf +#define debug_printf(X,...) + + const char* lastxmlerror=NULL; + +simplexml::simplexml(const char *encoded, const simplexml *parent) +{ + const char *sptr, *tptr /*, *uptr*/; + char *buf, *end, lastc; + long len; + keyvalue_rec *ptr; + + _parent = parent; + + _key = NULL; + _value = NULL; + _properties = NULL; + _children = NULL; + + ptr = NULL; + + // decode the xml string + + sptr = strchr(encoded,'<'); + if (sptr==NULL) + return; + + if (!parent && strncmp(sptr," \t\r\n"); // og + if (sptr[len-1]=='/') + len--; + + + _key = new char[len+1]; + strncpy(_key,sptr,len); + +// _key = (char*)sptr; + _key[len] = 0; + + + + + debug_printf("found tag:%s\n",_key); + + sptr += len; + lastc = sptr[0]; + //OG Manage autoclosing tag before entering the parsing loop + if (lastc=='/') + return ; + + /** Parse parameters ************************************************/ + while (sptr && sptr[0] && lastc != '>' /*&& lastc != '/'*/) { + len = nskiptok(sptr,"> \t\r\n"); + lastc = sptr[len-1]; + sptr += len; + + + if (lastc=='>' || sptr==NULL) + break; +/* + if (lastc=='/' && sptr[0]=='>') { + sptr += 2; + break; + } +*/ + if (sptr[0]=='/' && sptr[1]=='>') + { + return; + /* + sptr+=2; + break; + */ + } + + len = ntotok(sptr,"="); + if (sptr[len]=='=' && sptr[len+1]) { + if (_properties==NULL) { + _properties = new keyvalue_rec; + ptr = _properties; + } else { + ptr->next = new keyvalue_rec; + ptr = ptr->next; + } + ptr->next = NULL; + long l = ntotok(sptr,"\r\n\t ="); + ptr->key = new char[l+1]; + strncpy(ptr->key, sptr, l); + ptr->key[l] = 0; + + debug_printf("found property:[%s]\n",ptr->key); + + sptr += len+1; + len = nskiptok(sptr," \t\r\n"); + sptr+=len; + if (sptr[0]=='"') { + sptr++; + len = ntotok(sptr,"\""); + ptr->value = new char[len+1]; + strncpy((char *)ptr->value,sptr,len); + ((char *)ptr->value)[len] = 0; + sptr += len+1; + } else { + delete ptr->key; + ptr->key=NULL; + ptr->value=NULL; + SETXMLERROR("misformed xml 3\n"); + return ; + /* + len = ntotok(sptr,"> \t\r\n"); + ptr->value = new char[len+1]; + strncpy((char *)ptr->value,sptr,len); + ((char *)ptr->value)[len] = 0; + sptr += len; + */ + } + + debug_printf("found property value:%s\n",ptr->value); + + // OG avance + len = nskiptok(sptr," \t\r\n"); + sptr += len; + + lastc = sptr[0]; + /* + if (sptr) + { + lastc = sptr[0]; + } + */ + } + } + + // Empty tag? + if (lastc=='/') { + return; + } +/* + if (lastc=='>') { +#ifdef _DEBUG + printf("ignore\n"); +#endif + // sptr++; + } +*/ + len = nskiptok(sptr,"> \t\r\n"); + + if (!sptr[len]) + return; + + debug_printf("%c%c%c%c%c\n",sptr[len],sptr[len+1],sptr[len+2],sptr[len+3],sptr[len+4]); + // skip comments before determining tag type + while (strncasecmp(&sptr[len],"") + 3; + ASSERT(sptr); + len = 0; + } + + if (sptr[len]=='<') { + + debug_printf("key:%s",_key); + sptr += len; + buf = new char[strlen(_key) + 4]; // 4 => "\0" + sprintf(buf,"",_key); + + while (sptr && strncasecmp(sptr,buf,strlen(buf))) { + tptr = strchr(sptr,'<'); + if (tptr==NULL) { + delete[] buf; + return; + } + tptr++; + len = ntotok(tptr,"> \t\r\n"); + + // OG Autoclosing Tagfix + if (tptr[len-1]=='/') + len--; + + if (tptr[0]=='/') + { + SETXMLERROR("misformed xml 1"); + return ; + } + char* keyn = (char*)new char[len+1]; + strncpy(keyn,tptr,len); + keyn[len] = 0; + + if (!strcmp(keyn,"![CDATA[")) + { + delete keyn, + keyn=NULL; + // trim + tptr += 8; //strlen("![CDATA["); + + const char* ed = stristr(tptr,"]]>"); + if (!ed) + printf("CDATA does not end"); + + int trimleft = nskiptok(tptr," \t\r\n"); + tptr+=trimleft; + int len2 = ed-tptr; + _value = new char[len2+1]; + strncpy(_value,tptr,len2); + _value[len2] = 0; + debug_printf("found CDATA value: %s",_value); + + // closing tag + delete buf; + buf=NULL; + + tptr = ed+3; + sptr = tptr; + // skip + return ; + } + else + if (!strcmp(keyn,"!--")) + { + delete keyn; + keyn=NULL; + debug_printf("found comment"); + const char* ed = stristr(tptr,"-->"); + if (!ed) + printf("comment does not end"); + + tptr = ed+3; + sptr = tptr; + // skip + //return ; + + } + + else + { + + if (_children==NULL) { + _children = new keyvalue_rec; + ptr = _children; + } else { + ptr->next = new keyvalue_rec; + ptr = ptr->next; + } + ptr->next = NULL; + + ptr->key = keyn; + + + debug_printf("adding key:%s\n",ptr->key); + ptr->value = new simplexml(sptr,this); + + + // OG Autoclosing Tag Fix + int l = ntotok(sptr+1,"><"); + if ( (sptr[l]=='/') && (sptr[l+1]=='>') ) + { + // autoclosing tag) + sptr += l+2; + } + else + { + end = new char[len + 4]; // 4 => "\0" + sprintf(end,"",keyn); + + sptr = stristr(sptr,end); + if (sptr) + { + sptr += strlen(end); + delete[] end; + } + else + { + delete[] end; + SETXMLERROR("misformed XML\n"); + return ; + } + } + } + + sptr = strchr(sptr,'<'); + } + + delete[] buf; + + } else { + + // OG skip trailing space + sptr+=len; + + buf = new char[strlen(_key) + 4]; // 4 => "\0" + sprintf(buf,"",_key); + tptr = stristr(sptr,buf); +// ASSERT(tptr); + delete[] buf; + + if (tptr==NULL) + len = strlen(sptr); + else + len = tptr - sptr; + + len = removeendingspace(sptr,len); + _value = new char[len+1]; + strncpy(_value,sptr,len); + _value[len] = 0; + + debug_printf("found value:%s\n",_value); + } +} + +// trim ending space +int removeendingspace(const char *str,int len) +{ + if (!str) return 0; + while(len) + { + if (strchr(" \t\r\n",str[len-1])==NULL) + break; + len--; + } + return len; +} + +long ntotok(const char *str, const char *tokens) +{ + long i; + + if (str==NULL) + return -1; + + if (tokens==NULL) + return 0; + + for (i=0; str[i] && strchr(tokens,str[i])==NULL; i++); + + return i; +} + +long nskiptok(const char *str, const char *tokens) +{ + long i; + + if (str==NULL) + return -1; + + if (tokens==NULL) + return 0; + + const char* p; + for (i=0; str[i] && (p=strchr(tokens,str[i]))!=NULL; i++); +/* + for (i=0; str[i] ; i++) + { + const char* p = strchr(tokens,str[i]); + if (p!=NULL) break; + } +*/ + return i; +} + +const char *stristr(const char *haystack, const char *needle) +{ + long i, n; + + for (i=0; haystack[i]; i++) { + if (tolower(haystack[i])==tolower(needle[0])) { + for (n=0; + haystack[i+n] && needle[n] + && tolower(haystack[i+n])==tolower(needle[n]); + n++); + if (n==strlen(needle)) + return(&haystack[i]); + } + } + return NULL; +} + +simplexml::~simplexml(void) +{ + keyvalue_rec *ptr,*last; + + if (_key!=NULL) { + delete[] _key; + } + + if (_value!=NULL) { + delete[] _value; + } + + if (_properties!=NULL) { + for (ptr=_properties->next, last=_properties; + ptr!=NULL; + last=ptr, ptr=ptr->next) { + delete[] last->key; + delete[] (char *) last->value; + delete last; + } + delete[] last->key; + delete[] (char *) last->value; + delete last; + } + + if (_children!=NULL) { + for (ptr=_children->next, last=_children; + ptr!=NULL; + last=ptr, ptr=ptr->next) { + delete[] last->key; + delete (simplexml *) last->value; + delete last; + } + delete[] last->key; + delete (simplexml *) last->value; + delete last; + } +} + +const simplexml *simplexml::parent(void) +{ + return((const simplexml *) _parent); +} + +const char *simplexml::key(void) +{ + return((const char *) _key); +} + +const char *simplexml::value(void) +{ + return((const char*) _value); +} + +int simplexml::number_of_properties(void) +{ + int i; + keyvalue_rec *ptr; + + for (i=0, ptr=_properties; ptr!=NULL; i++, ptr=ptr->next); + + return i; +} + +const char *simplexml::property(int property_number) +{ + int i; + keyvalue_rec *ptr; + + for (i=0, ptr=_properties; + i!=property_number && ptr!=NULL; + i++, ptr=ptr->next); + + if (ptr) + return (const char *) ptr->value; + else + return NULL; +} + +const char *simplexml::property(const char *key, int iter) +{ + int i; + keyvalue_rec *ptr; + + for (ptr=_properties; ptr!=NULL; ptr=ptr->next) { + if (strcmp(ptr->key,key)==0) { + for (i=0; inext); + if (ptr) + return (const char *) ptr->value; + else + return NULL; + } + } + return NULL; +} + +int simplexml::number_of_children(void) +{ + int i; + keyvalue_rec *ptr; + + for (i=0, ptr=_children; ptr!=NULL; i++, ptr=ptr->next); + + return i; +} + +simplexml *simplexml::child(int child_number) +{ + int i; + keyvalue_rec *ptr; + + for (i=0, ptr=_children; + i!=child_number && ptr!=NULL; + i++, ptr=ptr->next); + + if (ptr) + return (simplexml *) ptr->value; + else + return NULL; +} + +simplexml *simplexml::child(const char *key, int iter) +{ + int i; + keyvalue_rec *ptr; + + for (ptr=_children; ptr!=NULL; ptr=ptr->next) { + if (strcmp(ptr->key,key)==0) { + for (i=0; inext); + if (ptr) + return (simplexml *) ptr->value; + else + return NULL; + } + } + return NULL; +} diff --git a/Common/3rdpartylib/simplexml.h b/Common/3rdpartylib/simplexml.h new file mode 100644 index 0000000..09a9f4f --- /dev/null +++ b/Common/3rdpartylib/simplexml.h @@ -0,0 +1,84 @@ +/***************************************************************************** + + This file is part of SimpleXML, a simplified C++ tree based parser + of XML 1.0 documents. + Copyright (C) 2003 by Brian Ecker. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*****************************************************************************/ + +#ifndef SIMPLEXML_H +#define SIMPLEXML_H + +#include + +#if defined(WIN32) && !defined(UNDER_CE) + #define strncasecmp _strnicmp + #define strcasecmp _stricmp +#endif + +extern const char* lastxmlerror; +#define SETXMLERROR(STR) lastxmlerror=STR; +#define RESETXMLERROR() lastxmlerror=NULL; +#define GETXMLERROR() lastxmlerror +typedef struct keyvalue { + + char *key; + void *value; + + struct keyvalue *next; + +} keyvalue_rec; + + +class simplexml +{ +public: + simplexml( const char *encoded, const simplexml *parent=NULL); + ~simplexml(void); + + const simplexml *parent(void); + + const char *key(void); + const char *value(void); + + int number_of_properties(void); + const char *property(int property_number); + const char *property(const char *key, int iter=0); + keyvalue_rec* properties() { return _properties; }; + + int number_of_children(void); + simplexml *child(int child_number); + simplexml *child(const char *key, int iter=0); + +// simplexml::print(MyString& _output); + +private: + const simplexml *_parent; + + char *_key; + char *_value; + + keyvalue_rec *_properties; + keyvalue_rec *_children; +}; + +long ntotok(const char *str, const char *tokens); +long nskiptok(const char *str, const char *tokens); +const char *stristr(const char *haystack, const char *needle); +int removeendingspace(const char *str,int len); + +#endif /* SIMPLEXML_H */ diff --git a/Common/ActiveDownload.cpp b/Common/ActiveDownload.cpp new file mode 100644 index 0000000..630e631 --- /dev/null +++ b/Common/ActiveDownload.cpp @@ -0,0 +1,627 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "activedownload.h" +//#include + +#include "ki.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +const char * activegsdownloaddir = "_DOWNLOADCACHE"; +const char * activegspersistentdir = "ActiveGSLocalData"; + + +MyString CDownload::persistentPath ; +//CDownload g_download; + +int calcCRC(const MYCHAR* ptr) +{ + int crc=0; + int l = 0; + while(*ptr) + { + crc ^= *ptr << (l%24); + ptr++; + l+=3; + } + return crc; +} + + +MyString getfilenoext(const MYCHAR *url) +{ + MyString tmp(getfile(url)); + int pos = tmp.ReverseFind('.'); + return tmp.substr(0,pos); +} + + +MyString CDownload::getPersistentDir(const char* url) +{ + MyString dir; +// dir.Format("%s"ACTIVEGS_DIRECTORY_SEPARATOR"%s.%08X",getPersistentPath(),getfilenoext(url),calcCRC(url)); + + dir = getPersistentPath(); + dir += ACTIVEGS_DIRECTORY_SEPARATOR; + dir += getfilenoext(url) ; +/* + MyString urldir; + getdir(url,urldir); +*/ + MyString temp; + temp.Format(".%08X",calcCRC(url)); + dir += temp.c_str(); + return dir ; +} + +bool CDownload::retrieveZippedFile(const MYCHAR* url,int _order,MyString& _path,MyString& _short) +{ + return retrievePersistentZippedFile(url,_order,_path,_short); + /* + + if (bUsePersistentPath) + return retrievePersistentZippedFile(url,_order,_path,_short); + else + return retrieveCachedZippedFile(url,_order,_path,_short); + */ +} + + +// ***************************************************************** + + +// ***************************************************************** + + +CDownload::CDownload(const char* _baseURL) +{ + requiredExt = NULL; + bTestOnly = false; + bNotifyDownloadFailure = true; +#if defined(DRIVER_ANDROID) + fromMainThread = true; +#endif + setBaseURL(_baseURL); + + +} + +void CDownload::deleteDownloadDirectory() +{ + // détruit le répertoire de téléchargement + MyString dir; + dir = getPersistentPath(); + dir += ACTIVEGS_DIRECTORY_SEPARATOR; + dir += activegsdownloaddir; + deleteDirectory(dir.c_str(),1); + +} + +CDownload::~CDownload() +{ +} + +bool CDownload::retrieveDistantFile(const char* _url,int _order,MyString& _path, MyString& _short) +{ + + MyString url; + normalize(_url,url); + + + MyString ext(getext(url.c_str())); + bool bZip = !ext.CompareNoCase("zip"); + bool bRet; + + if (bZip) + { + // essaie de rÈcupÈrer la version existante ? + + bRet = retrieveZippedFile(url.c_str(),_order,_path,_short); + + if (!bRet) + { + if (bTestOnly) + return false; + + // essaie de downloader + bRet = downloadHTTPFile(url.c_str(),_path); + + if (bRet) + { + if (!unzipFile(url.c_str(),_path.c_str())) + { + // unzip failed... + outputInfo("unzip failed (%s)\n",getfile(url.c_str())); + bRet=false; + deleteFile(_path.c_str()); + outputInfo("deleting file (%s) for recovery next time \n",getfile(_path.c_str())); + + } + + if (bRet) + bRet = retrieveZippedFile(url.c_str(),_order,_path,_short); + } + } + } + else + { + + // if (bUsePersistentPath) + { + // fichier distant non zip + MyString dir; + MyString local; + + dir = getPersistentDir(url.c_str()); + createDirectory(dir.c_str()); + local = dir.c_str(); + local += ACTIVEGS_DIRECTORY_SEPARATOR; + local += getfile(url.c_str()) ; + + // regarde si le fichier existe ? + // QUID SI LE FICHIER EST CORROMPU ? + + FILE* f = fopen(local.c_str(),"rb"); + if (f) + { + fclose(f); + bRet=true; + } + else + { + // retlcharge le fichier + if (bTestOnly) + return false; + bRet = GetFile(url.c_str(),local.c_str()); + + } + if (bRet) + _path = local; + } + /* + else + bRet = downloadHTTPFile(url.c_str(),_path); + */ + + if (bRet) + _short = getfile(_path.c_str()); + + } + + if (!bRet) + { + // showProgress(url.c_str(),-1); + ::showStatus("Failed to download %s\n",getfile(url.c_str())); + } + return bRet; + +} + +int CDownload::fileExists(const char * _path) +{ + FILE* f = fopen(_path,"rb"); + if (f) + { + fclose(f); + return 1; + } + else + return 0; +} +// ***************************************************************** + +long CDownload::retrieveLocalFile(const MYCHAR* _url,int _order,MyString& _path, MyString& _short) +{ + + MyString url = _url; + + MyString ext(getext(url)); + + if (!ext.CompareNoCase("zip")) + { + + if (!retrieveZippedFile(url,_order,_path,_short)) + { + if (!unzipFile(url,url)) + { + // unzip failed... + outputInfo("unzip failed (%s)\n",_url); + return 0; + } + if (!retrieveZippedFile(url,_order,_path,_short)) + { + outputInfo("could not find zip (%s)\n",_url); + return 0; + } + } + + } + else + { + _path = url; + + _short = getfile(url); + } + + + + FILE* f = fopen(_path.c_str(),"rb"); + if (f) + { + /*int err =*/ fseek(f,0,SEEK_END); + long size = ftell(f); + fclose(f); + return size; + } + else + { + outputInfo("could not find file (%s)\n",_url); + ::showStatus("Failed to load %s",getfile(_url)); + return 0; + } + +} + +bool CDownload::makeAbsolutePath(const char* _myp, const char* _base,MyString& _dest) +{ + + MyString p = _myp; + MyString header5 = p.Left(5); + MyString header17 = p.Left(17); + MyString header8 = p.Left(8); + MyString header7 = p.Left(7); + + bool bAbsolute= true; + + // OG 190110 Added \ for WinCE devices + if ( ( p[0]=='\\') || ( p[0]=='/') || ( p[1]==':') || (!header5.CompareNoCase("http:")) ) + _dest = p; // absolute path + else + if (!header17.CompareNoCase("file://localhost/")) + _dest = p.substr(17,p.length()-17); // absolute path for opera + else + if (!header8.CompareNoCase("file:///")) +#ifdef WIN32 + _dest = p.substr(8,p.length()-8); // absolute path +#else + _dest = p.substr(7,p.length()-7); // keep the / on mac +#endif + else + if (!header7.CompareNoCase("file://")) + _dest = p.substr(7,p.length()-7); // absolute path + else + { + // newurl.Format("%s"ACTIVEGS_DIRECTORY_SEPARATOR"%s",baseURL,p.c_str()); + _dest = _base; + _dest += ACTIVEGS_DIRECTORY_SEPARATOR; + _dest += p.c_str(); + bAbsolute = false; + } + + return bAbsolute; +} + + +int CDownload::parseFilenameAndMakeAbsolute(const char* _myp, int& _order, MyString &newurl) +{ + + MyString p(_myp); + + // ignore #id= dans l'url + int pos = p.ReverseFind("#id="); + if (pos!=-1) + p = p.Left(pos); + + // récupère le #order si présent + pos = p.ReverseFind("#pos="); + if (pos!=-1) + { + MyString orderstr = p.Mid(pos+5).c_str(); + _order = atoi(orderstr.c_str()); + if (_order<0 || _order>9) + _order = 0; + p = p.Left(pos); + } + else + _order = 0; + + ASSERT (!baseURL.IsEmpty()); + makeAbsolutePath(p.c_str(),baseURL.c_str(),newurl); + + // OG 03-NOV-03 + // Added files network support + if ( (newurl[0]=='/') || (newurl[1]==':') || ( (newurl[0]=='\\') /*&& (newurl[1]=='\\')*/ ) ) + return 1; //localPath = true; + else + return 0; + +} + +// ***************************************************************** + +size_t CDownload::retrieveFile(const char* _myp,MyString& _path,MyString& _short) +{ + size_t ret; + + + _path.clear(); + if (!_myp || !_myp[0] ) return false; + + int _order; + MyString newurl ; + int localPath = parseFilenameAndMakeAbsolute(_myp,_order,newurl); + + /* + MyString normalized; + normalize(newurl.c_str(),normalized); + */ + + if (localPath) + ret = retrieveLocalFile(newurl.c_str(),_order,_path,_short); + else + { + /* + if (_bSizeOnly) + { + outputInfo("size only not implemented for distant file (%s)\n",newurl.c_str()); + return 0; + } + */ + ret = retrieveDistantFile(newurl.c_str(),_order,_path,_short); + } + return ret; +} + + + + + +const char* getext(const char* _filename) +{ + MyString tmp(_filename); + int pos = tmp.ReverseFind('.'); + return _filename+pos+1; +} + + +void geturldomain(const char* p,MyString& _domain) +{ + if (strncasecmp(p,"http:",5)) + _domain = "(local)"; + else + { + int l = 7; + while(p[l] && p[l]!='/') l++; + char ldir[1024]; + strncpy(ldir,p+7,l-7); + ldir[l-7]=0; + _domain = ldir; + } +} + + + +void geturldir(const char* p,MyString& _dir) +{ + // avance jusqu'à un possible'?' + int l = 0; + while(p[l] && p[l]!='#') l++; + if (!l) return ; // chaine vide + l--; +// int l=(int)strlen(p)-1; + while(l>=0) { + if ( (p[l]=='\\') || (p[l]=='/') ) + break; + l--; + } + char ldir[1024]; + if (l<0)l=0; + strncpy(ldir,p,l); + ldir[l]=0; + _dir = ldir; + +} + + +void getdir(const char* p,MyString& _dir) +{ + int l=(int)strlen(p)-1; + while(l>=0) { + if ( (p[l]=='\\') || (p[l]=='/') ) + break; + l--; + } + char ldir[512]; + if (l<0)l=0; + strncpy(ldir,p,l); + ldir[l]=0; + _dir = ldir; + +} + +const MYCHAR* getfile(const MYCHAR* p) +{ + MyString tmp(p); + int lastslash = tmp.ReverseFind('\\'); + int lastantislash = tmp.ReverseFind('/'); + int pos = lastslash>lastantislash?lastslash:lastantislash; + return p+pos+1; + +} + +void normalize(const MYCHAR* file,MyString& dest) +{ + MyString work(file); + work.Replace("\\","/"); + + /* + // TODO + const MYCHAR*p; + + const MYCHAR* find=_MYT("/../"); + while(1) //p=strstr(work.c_str(),find)) + { + int index = work.Find(find); + if (index==-1) break; + + MyString before(work.Left(index)); + + int last = work.ReverseFind('/'); + if (last==-1) break ; + + + MyString after(work.Mid(index + 4 )); //4=strlen(find) + + work = before.Left((last-(const MYCHAR*)before.c_str())+1); + work += after; + } + */ + + dest=work; +} +/* +const char* CDownload::retrieveURL() +{ + return myURL.c_str(); +} +void CDownload::setURL(const char* _url ) +{ + myURL = _url; + myURL.Replace("%20"," "); +} +*/ + +void CDownload::setBaseURL(const char* _baseURL) +{ + if (!strncasecmp(_baseURL,"file:///",8)) +#ifdef WIN32 + _baseURL+=8; +#else + _baseURL+=7; // keep the / on mac +#endif + else + if (!strncasecmp(_baseURL,"file://",7)) + _baseURL+=7; // absolute path + + baseURL = _baseURL ; +// baseURL.Replace("%20"," "); + + printf("CDownload::baseURL set to %s\n",_baseURL); +} + +const char* CDownload::getPersistentPath() +{ + if (persistentPath.IsEmpty()) + { + x_fatal_exit("missing persistent path!"); + return NULL; + } + //this->initPersistentPath(); + + const char* p = persistentPath.c_str(); + return p; +} + + +void CDownload::initPersistentPath() +{ + if (!persistentPath.IsEmpty()) + return ; + + MyString systemPath ; + initPersistentSystemPath(systemPath); + createDirectory(systemPath.c_str()); + + systemPath += ACTIVEGS_DIRECTORY_SEPARATOR; + systemPath += activegspersistentdir; + createDirectory(systemPath.c_str()); + + persistentPath = systemPath; + + systemPath += ACTIVEGS_DIRECTORY_SEPARATOR; + systemPath += activegsdownloaddir; + createDirectory(systemPath.c_str()); + +} + +/* +bool CDownload::createCacheEntryName(const char* _url, const char* _pathname, int _index, MyString& _cacheEntryName) +{ + _cacheEntryName.Format("%s_%d_%s",_url,_index,_pathname); + return true; +} +*/ + +void CDownload::deleteCachedFile(const MYCHAR* _path) +{ + + MyString url ; + int order; + int localPath = parseFilenameAndMakeAbsolute(_path,order,url); + if (!localPath) + { + // détruit le fichier downloadé + MyString downloaded; + getPersistentDownloadedFile(_path,downloaded); + printf("delete getPersistentDownloadedFile %s\n",downloaded.c_str()); + deleteFile(downloaded.c_str()); + } + + + MyString ext(getext(url)); + if (!localPath || !ext.CompareNoCase("zip")) + { + // détruit le répertoire d'extraction + MyString dir = getPersistentDir(url); + printf("delete dir %s\n",dir.c_str()); + deleteDirectory(dir.c_str()); + } +} + +void CDownload::getPersistentDirectoryFile(const char* _file, const char* _dir, MyString &dir) +{ + dir = getPersistentPath(); + dir += ACTIVEGS_DIRECTORY_SEPARATOR; + dir += _dir; + dir += ACTIVEGS_DIRECTORY_SEPARATOR; + + MyString fnoext =getfilenoext(getfile(_file)); + MyString temp; + temp.Format("%s.%08X.%s",fnoext.c_str(),calcCRC(_file),getext(_file)); + dir += temp.c_str(); +} + + +void CDownload::getPersistentDownloadedFile(const char* _file, MyString &dir) +{ + + return getPersistentDirectoryFile(_file,activegsdownloaddir,dir); + +} + + +bool CDownload::downloadHTTPFile(const char* filename,MyString& _gotfile) +{ + outputInfo("downloadHTTPFile %s\n",filename); + + getPersistentDownloadedFile(filename,_gotfile); + + // regarde si le fichier existe + FILE* f = fopen(_gotfile.c_str(),"rb"); + if (f) + { + fclose(f); + // _gotfile = _gotfile; + return true; + } + + return GetFile(filename,_gotfile.c_str()); + +} + diff --git a/Common/ActiveDownload.h b/Common/ActiveDownload.h new file mode 100644 index 0000000..c541c92 --- /dev/null +++ b/Common/ActiveDownload.h @@ -0,0 +1,118 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + + +#ifdef _WIN32 +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +//#define ssnprintf _ssnprintf +#endif + +#include "../kegs/Src/StdString.h" + + + +#ifdef UNICODE + #define TOSYSTEMCHAR(X,Y) CStdStringW Y(X); + #define TOSINGLECHAR(X) (X) +#else + #define TOSYSTEMCHAR(X,Y) CStdStringA Y(X); + #define TOSINGLECHAR(X) (X) +#endif + +#define MYCHAR char + +#define ACTIVEGSCACHEPATH "_DOWNLOADCACHE" + +#ifdef _WIN32 +#define ACTIVEGS_DIRECTORY_SEPARATOR "\\" +#else +#define ACTIVEGS_DIRECTORY_SEPARATOR "/" +#endif + + +const char* getfile(const char* p); +const char* getext(const char* filename); +void getdir(const char* p,MyString& _dir); +void normalize(const char* file,MyString& dest); +void removeext(char* filename); + MyString getfilenoext(const char *url); +int calcCRC(const char* ptr); + + +class CDownload +{ +private: + + static void initPersistentSystemPath(MyString& path); + static MyString persistentPath; + +public: + static void initPersistentPath(); + + + MyString baseURL; // URL of the calling page + + const MYCHAR* requiredExt; + + bool retrieveDistantFile(const MYCHAR* url,int _order,MyString& _path, MyString& _short); + long retrieveLocalFile(const MYCHAR* url,int _order,MyString& _path,MyString& _short); + bool downloadHTTPFile(const MYCHAR* filename,MyString& _path); + + bool unzipFile(const MYCHAR* _url,const MYCHAR* _zipPath); + + bool retrieveZippedFile(const MYCHAR* url,int _order,MyString& _path, MyString& _short); +// bool retrieveCachedZippedFile(const MYCHAR* url,int _order,MyString& _path, MyString& _short); + bool retrievePersistentZippedFile(const MYCHAR* url,int _order,MyString& _path, MyString& _short); + +public: + void getPersistentDirectoryFile(const char* _file, const char* _dir, MyString &dir); + void getPersistentDownloadedFile(const char* _file, MyString &dir); + + + CDownload(const char* _baseURL); + ~CDownload(); + + void setRequiredExt(const MYCHAR* _ext) { requiredExt = _ext; } + + MyString getPersistentDir(const MYCHAR* url); + static void setPersistentPath(const char* path); +// MyString getPersistentPathname(const char* _subdir,const char* url); + + + size_t retrieveFile(const MYCHAR* name, MyString& path,MyString& file); + bool GetFile(const char *url, const char *filename); + + // cache + /* + bool commitCacheEntry(const char* cacheEntryName, const char* _cacheEntryPath); + bool createCacheEntry(const char* cacheEntryName, MyString& cacheEntryPath); + bool createCacheEntryName(const char* _url, const char* _pathname, int _index, MyString& cacheEntryName); + */ + + void setBaseURL(const char* _baseURL); + static const char* getPersistentPath(); + static void createDirectory(const MYCHAR* _dir); + static void deleteFile(const MYCHAR* _dir); + static int fileExists(const char*); + void deleteDirectory(const MYCHAR* _dir, int keepDir=0); + void deleteDownloadDirectory(); + static bool makeAbsolutePath(const MYCHAR* _myp, const MYCHAR* _base,MyString& _dest); + bool bNotifyDownloadFailure; + bool bTestOnly; + + int parseFilenameAndMakeAbsolute(const char* _myp, int& _order, MyString &newurl); + void deleteCachedFile(const MYCHAR* _path); + + +#if defined(DRIVER_ANDROID) + bool fromMainThread; +#endif +}; + +//extern CDownload g_download; diff --git a/Common/ActiveDownloadNoCache.cpp b/Common/ActiveDownloadNoCache.cpp new file mode 100644 index 0000000..43e37d4 --- /dev/null +++ b/Common/ActiveDownloadNoCache.cpp @@ -0,0 +1,20 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../common/cemulatorctrl.h" +#include "activedownload.h" +#include +#ifdef MAC +#include +#endif +#include "../common/ki.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +extern const char * activegscachedir ; +extern const char * activegsdownloaddir ; diff --git a/Common/ActiveGSList.cpp b/Common/ActiveGSList.cpp new file mode 100644 index 0000000..cb14baf --- /dev/null +++ b/Common/ActiveGSList.cpp @@ -0,0 +1,229 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "ActiveGSList.h" +#include "activedownload.h" + +ActiveGSList::~ActiveGSList() +{ + if (rootXML) + { + delete rootXML ; + rootXML = NULL; + } + +} + +void ActiveGSList::reset() +{ + elements.clear(); + sourceName.Empty(); + sourceRevision.Empty(); + pathName.Empty(); + + if (rootXML) + { + delete rootXML; + rootXML=NULL; + } +} + +ActiveGSList::ActiveGSList() +{ + rootXML = NULL; + reset(); +} + +int ActiveGSList::loadFromFile(const char* _url) +{ + MyString path; + MyString shortname; + + CDownload dl("*absolute*"); + dl.bNotifyDownloadFailure = false; // sera traité avec l'existence du fichier + dl.setRequiredExt("activegsxml"); + + if (!dl.retrieveFile(_url,path,shortname)) + { + printf("could not load config %s\n",_url); + return 0; + } + + printf("processing config %s\n",_url); + pathName = _url; + + FILE* f = fopen(path.c_str(),"rb"); + if (!f) + { + printf("cannot open config%s\n",path.c_str()); + return 0 ; + } + fseek(f,0,SEEK_END); + int si = ftell(f); + if (!si) + { + fclose(f); + printf("cannot open config%s (file empty)\n",path.c_str()); + return 0; + } + fseek(f,0,SEEK_SET); + char* s = new char[si+1]; + memset(s,0,si+1); + fread(s,1,si,f); + fclose(f); + + int b = processString(s); + + delete s; + return b; +} + + +int ActiveGSList::processString(const char* _str) +{ + + RESETXMLERROR(); + simplexml* root= new simplexml(_str); + if (GETXMLERROR()) + { + printf("bad xml %s\n",GETXMLERROR()); + return 0; + } + + if (!root->key()) + { + printf("xml empty\n"); + return 0 ; + } + // regarde si c'est un type list + if (!strcasecmp(root->key(),"list")) + { + + int child = root->number_of_children(); + for(int i=0;ichild(i); + if (!strcasecmp(ptr->key(),"source")) + { + const char* name = ptr->value(); + if (name) + sourceName = name; + const char* revision = ptr->property("revision"); + if (revision) + sourceRevision = revision; + } + else + if (!strcasecmp(ptr->key(),"config")) + { + ActiveGSElement el ; + if ( el.fillFromXML(ptr) ) + elements.push_back (el); + } + } + } + else + { + // 1 seul + ActiveGSElement el ; + if ( el.fillFromXML(root) ) + elements.push_back (el); + } + + rootXML= root; + return 1; + +} + + + +int ActiveGSElement::fillFromXML(simplexml* ptrconfig) +{ +static int baseid=0; + + const char* ver = ptrconfig->property("version"); + if (!ver || atoi(ver)!=2) + { + printf("invalid xml version - xml config skipped\n"); + return 0; + } + + + // default Apple2 + is2GS = 0; + + // attribue un id + + const char* _id = ptrconfig->property("id"); + if (_id) + theid = _id; + else + theid.Format("Image%d",baseid++); + + + int child = ptrconfig->number_of_children(); + for(int i=0;ichild(i); + + if (!strcasecmp(ptr->key(),"name")) + { + const char* s = ptr->value(); + name = s; + } + else + if (!strcasecmp(ptr->key(),"desc")) + { + const char* s = ptr->value(); + desc = s; + } + else + if (!strcasecmp(ptr->key(),"publisher")) + { + const char* s = ptr->value(); + publisher = s; + } + else + if (!strcasecmp(ptr->key(),"year")) + { + const char* s = ptr->value(); + year = s; + } + else + if (!strcasecmp(ptr->key(),"pic")) + { + const char* type = ptr->property("type"); + if (type && !strcasecmp(type,"thumbnail")) + { + const char* fn = ptr->value(); + if (fn && strcasecmp(fn,"http://www.virtualapple.org/images/vascreen1.jpg")) + thumb = ptr->value(); + } + else + if (type && !strcasecmp(type,"screenshot")) + { + const char* fn = ptr->value(); + + for(int i=0;ikey(),"format")) + { + const char* type = ptr->value(); + if (type && ( !strcasecmp(type,"2GS") || !strcasecmp(type,"GS") ) ) + is2GS = 1; + } + } + pXML = ptrconfig; + return 1; +} diff --git a/Common/ActiveGSList.h b/Common/ActiveGSList.h new file mode 100644 index 0000000..21e2ba1 --- /dev/null +++ b/Common/ActiveGSList.h @@ -0,0 +1,62 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once +#include + +#define MAX_SCREENSHOTS 10 +#include "../common/3rdpartylib/simplexml.h" +#include "../kegs/src/StdString.h" +#include "../kegs/src/defc.h" +#include "../common/ki.h" + + + +struct ActiveGSElement +{ + + MyString theid; + MyString thumb; + +#define MAX_SCREENSHOTS 10 + MyString screenShots[MAX_SCREENSHOTS]; + + simplexml* pXML; + int is2GS; + + + MyString uid; + MyString name; + MyString nameurl; + MyString desc; + MyString year; + MyString publisher; + MyString publisherurl; + + MyString visibleName; + + + int fillFromXML(simplexml* ptrconfig); +}; + +class ActiveGSList +{ +public: + MyString pathName; + MyString trackerName; + MyString sourceName; + MyString sourceRevision; + + + simplexml* rootXML; + std::vector elements; + + ActiveGSList(); + ~ActiveGSList(); + int loadFromFile(const char* _file); + int processString(const char* _str); + void reset(); +}; diff --git a/Common/ActiveZip.cpp b/Common/ActiveZip.cpp new file mode 100644 index 0000000..0d271b1 --- /dev/null +++ b/Common/ActiveZip.cpp @@ -0,0 +1,213 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "cemulatorctrl.h" +#include "ki.h" +#include "../Libraries/unzip101e/unzip.h" + +/* +#ifdef _DEBUG +#define new DEBUG_NEW +#endif +*/ + +bool CDownload::unzipFile(const MYCHAR* _url,const MYCHAR* _zipPath) +{ + + MyString persistentPath; + MyString filename; + MyString localPath; + MyString cacheEntryName; + + //if (bUsePersistentPath) + { + // cre la directory + persistentPath = getPersistentDir(_url); + createDirectory(persistentPath.c_str()); + } + + unzFile zf = unzOpen(_zipPath); + if (!zf) + { + outputInfo("could not open %s\n",getfile(_zipPath)); + return false; + } + outputInfo("zip: %s\n",_zipPath); + unz_global_info zinfo; + unzGetGlobalInfo(zf,&zinfo); + + unzGoToFirstFile(zf); + + int iz = 0; + do + { + char fnfull[1024]; + unz_file_info finfo; + unzGetCurrentFileInfo(zf,&finfo,fnfull,1024,NULL,0,NULL,0); + + // OG remove any subdirectory + MyString fn = getfile(fnfull); + MyString filename(fn); + filename = filename.Left(8); + if (!filename.compare("__MACOSX")) + continue ; + MyString ext(getext(fn)); + if (requiredExt) + { + if (ext.CompareNoCase(requiredExt)) + continue; + } + else + { + if ( ext.CompareNoCase("2mg") + && ext.CompareNoCase("dsk") + && ext.CompareNoCase("do") + && ext.CompareNoCase("po") + && ext.CompareNoCase("raw") + && ext.CompareNoCase("nib") + && ext.CompareNoCase("bin") + && ext.CompareNoCase("hdv") ) + continue ; + } + + // if (bUsePersistentPath) + { + // localPath.Format("%s"ACTIVEGS_DIRECTORY_SEPARATOR"%d_%s",persistentPath.c_str(),iz,(const char*)fn); + localPath = persistentPath.c_str(); + localPath += ACTIVEGS_DIRECTORY_SEPARATOR; + MyString temp; + temp.Format("%d_",iz); + localPath += temp.c_str(); + localPath += (const char*)fn.c_str(); + } + /* + else + { + createCacheEntryName(_url,fn,iz,cacheEntryName); + createCacheEntry(cacheEntryName.c_str(),localPath); + } + */ + + outputInfo("Extracting to %s\n",localPath.c_str()); + unzOpenCurrentFile(zf); + + FILE* f = fopen(localPath.c_str(),"wb"); + if (!f) + { + outputInfo("Cannot create %s\n",localPath.c_str()); + return false; + } + +#define UNZIP_LEN 16*1024 + char buf[UNZIP_LEN]; + int nbread; + int len=0; + while( (nbread=unzReadCurrentFile (zf,buf,UNZIP_LEN)) >0 ) + { + size_t nbw = fwrite(buf,1,nbread,f); + if (nbw!=nbread) + { + outputInfo("failed to write %s\n",localPath.c_str()); + fclose(f); + deleteFile(localPath.c_str()); + return false; + } + len += nbread; + } + fclose(f); + if (len==0) + { + outputInfo("failed to uncompress %s\n",_zipPath); + deleteFile(localPath.c_str()); + return false; + + } + + int err = unzCloseCurrentFile(zf); + if (UNZ_CRCERROR==err) + { + outputInfo("CRC Error for %s \n",_zipPath); + deleteFile(localPath.c_str()); + return false; + } + + /* + if (!bUsePersistentPath) + commitCacheEntry(cacheEntryName.c_str(),localPath.c_str()); + */ + + iz++; + } + while(unzGoToNextFile(zf)==UNZ_OK); + + unzClose(zf); + + + return true; +} + + +/* +bool retrieveCachedZippedFile(const char* url,int _order,MyString& _path, MyString& _short) +{ + + //outputInfo("retrieveCachedZippedFile %s %d\n",url,_order); + + int defaultSize = 4096; + BYTE* CacheEntryInfoBuffer = (BYTE*)malloc(defaultSize); + LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo = (INTERNET_CACHE_ENTRY_INFO*)CacheEntryInfoBuffer; + + MyString search; search.Format("%s_%d_",url,_order); + HANDLE hFind = NULL; + BOOL err; + while(1) + { + DWORD dwCacheEntryInfoBufferSize = defaultSize; + if (!hFind) + { + hFind = FindFirstUrlCacheEntry(NULL,lpCacheEntryInfo,&dwCacheEntryInfoBufferSize); + err = (hFind==NULL); + } + else + err = !FindNextUrlCacheEntry(hFind,lpCacheEntryInfo,&dwCacheEntryInfoBufferSize); + + if (!err) + { + if (!_strnicmp(lpCacheEntryInfo->lpszSourceUrlName,search.c_str(),search.GetLength())) + { + outputInfo("Zip Found %s (%s)\n",lpCacheEntryInfo->lpszSourceUrlName,lpCacheEntryInfo->lpszLocalFileName); + _path = lpCacheEntryInfo->lpszLocalFileName; + _short = lpCacheEntryInfo->lpszSourceUrlName+search.GetLength(); + FindCloseUrlCache(hFind); + free(CacheEntryInfoBuffer); + return true; + } + } + else + switch (GetLastError()) + { + case ERROR_NO_MORE_ITEMS: + outputInfo("Item not found : %s\n",url); + FindCloseUrlCache(hFind); + free(CacheEntryInfoBuffer); + return false; + case ERROR_INSUFFICIENT_BUFFER: + CacheEntryInfoBuffer = (BYTE*)realloc(CacheEntryInfoBuffer,dwCacheEntryInfoBufferSize); + defaultSize = dwCacheEntryInfoBufferSize; + lpCacheEntryInfo = (INTERNET_CACHE_ENTRY_INFO*)CacheEntryInfoBuffer; + break; + default: + outputInfo("failed to FindNextUrlCacheEntry : %s (%d)\n",url,GetLastError()); + FindCloseUrlCache(hFind); + free(CacheEntryInfoBuffer); + return false; + } + } + + // jamais return false; + +} +*/ diff --git a/Common/CA2Text.cpp b/Common/CA2Text.cpp new file mode 100644 index 0000000..3bb5c20 --- /dev/null +++ b/Common/CA2Text.cpp @@ -0,0 +1,119 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../common/cemulatorctrl.h" +#include "../kegs/src/sim65816.h" + +extern word32 g_font40_even_bits[0x100][8][16/4]; +extern word32 g_font40_odd_bits[0x100][8][16/4]; + +word32 lastdrawtime = 0; +//void x_need2refresh(); +#define MAXCONSOLE 1 +int curConsole=0; +MyString Console[MAXCONSOLE]; + +extern void refresh_video(int); + +void addConsole(const char* _str) +{ + MyString temp = _str; +#ifndef UNDER_CE + temp.ToLower(); +#endif + Console[curConsole++]=temp.c_str(); + if (curConsole==MAXCONSOLE) curConsole=0; +// printf(temp.c_str()); + lastdrawtime = 0; +// refresh_video(1); +} +void drawText(Kimage* _dst, const char* text,int _x,int _y); +void drawConsole(Kimage* _dst) +{ + if ( !Console[0].GetLength() ) return ; + if (!_dst) return ; + + /* + word32 curtime = g_sim65816.g_vbl_count; + if (lastdrawtime) + { + if (curtime>lastdrawtime+2*60) + { + Console[0].Empty(); + return ; + } + } + else + lastdrawtime=curtime; + */ + + int pixsize = _dst->mdepth / 8 ; + int stride =_dst->width_act* pixsize; + int x = 16, y = 16; + int w=400, h=20; + byte* ptr = _dst->data_ptr + y*stride + x*pixsize ; + while(h--) + { + memset(ptr,0x77777777,w*pixsize); + ptr+=stride; + } + + for(int i=0;imdepth / 8 ; + int stride =_dst->width_act * pixsize ; + byte* ptrline = _dst->data_ptr + _y*stride + _x*pixsize; + + while( (c=*text++) != 0 ) + { + /* + if (c==13) + { + curline++; + curpos=0; + break; + } + */ + byte* ptr = ptrline; + for(int j=0;j<8;j++) + { + word32* ptrw = (word32*)ptr; + // byte* ptr = (byte*)ptrline; + for(int i=0;i<7;i++) + { + int mask = 1 << (7-i); + int v = g_font_array[c][j] ; + int on = v & mask; + // int color = 0; + if (!on) + { + const int color = -1; + if (pixsize==1) + { + ptr[i]=color; + ptr[i+1]=color; + } + else + { + ptrw[i] = color; + ptrw[i+1] = color; + } + } + } + ptr += stride; + } + ptrline += 8*pixsize; + } +} \ No newline at end of file diff --git a/Common/CEMulatorCtrl.h b/Common/CEMulatorCtrl.h new file mode 100644 index 0000000..69a19c7 --- /dev/null +++ b/Common/CEMulatorCtrl.h @@ -0,0 +1,417 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +//#ifndef MAC +#ifdef _WIN32 + #include +#endif + +#include "../common/ActiveGSList.h" +#include "../common/activedownload.h" +#include "../common/ki.h" + +#include "../kegs/src/sound.h" + +extern int outputInfoInternal(const char*); + + +/* +#if defined(_DEBUG)|| defined(_GLIBCXX_DEBUG) +#define ADD2CONSOLE(X) +#else +extern void add2Console(const char*); +#define ADD2CONSOLE(X) addConsole(X) +#endif +*/ + +#define ACTIVEGSXMLPATH "_XML" + +#if defined(WIN32) && !defined(UNDER_CE) +#define STRING2CONSTCHAR(X) ((const char*)X) +#else +#define STRING2CONSTCHAR(X) (X.c_str()) +#endif + + +enum eParamType +{ + EMULATOR, + BRAM +}; + +struct param +{ + MyString data; + MyString value; + int hex; +}; + +class CSetStart +{ +public: + int slot; +// int addr; + MyString file; + + CSetStart() { slot=0; }; +}; + +typedef enum +{ + OPTION_ERROR = -1, + OPTION_CONFIGVERSION = 0, + OPTION_GUID, + OPTION_HALTONBADREAD, + OPTION_HALTONBADACC, + OPTION_HALTONHALTS, + OPTION_ENABLEREWIND, + OPTION_COLORMODE, + OPTION_VIDEOFX, + OPTION_JOYSTICKMODE, + OPTION_BROWSERNAME, + OPTION_BROWSERVERSION, + OPTION_LATESTRUNBUILD, + OPTION_LATESTUPDATECHECK, + OPTION_DONOTSHOWUPDATEALERT, + + OPTION_DONOTSHOWDISKSTATUS, + OPTION_PNGBORDER, + OPTION_SIMULATESPACE, + OPTION_LATESTVERSION, + + OPTION_SPEED, + OPTION_LATESTVERSIONDATE, + OPTION_AUDIORATE, + OPTION_MEMORYSIZE, + OPTION_JOYXSCALE, + OPTION_JOYYSCALE, + OPTION_DISKSOUND, + OPTION_FIXEDVBLANK, + OPTION_ADBDELAY, + OPTION_ADBRATE, + +#ifdef DRIVER_IOS + OPTION_FRAMERATE, + OPTION_LOCKZOOM, + OPTION_LASTTAB, + OPTION_DEBUGMODE, + OPTION_EXTERNALKBD, +#endif +#ifdef ACTIVEGSKARATEKA + OPTION_SHOWICONS, + OPTION_ENABLECHEAT, + OPTION_SOUNDMODE, + OPTION_KARATEKAREWIND, +#endif +#ifdef VIRTUALAPPLE + OPTION_DEBUG, + OPTION_SCORES, + OPTION_GAMECENTER, +#endif + NB_OPTIONS +} option_id; + + +typedef struct +{ + int inConfig; + int inDefault; + const char* name ; + int defaultint; + const char* defaultstr; + const char** convertTableDesc; + const char** convertTableAlias; + const int* convertTableInt; +} namevaluedef; + +class namevalue +{ +public: + const namevaluedef* def; + MyString strvalue; + int intvalue; + int confOverrided; + + namevalue() { intvalue=0;confOverrided=0; def=NULL; } + + int convertToInt(const char* _value); + int belongsToValue(int v); + void getAlias( MyString& _str); + const char* getDescription(int _value); + int getOrder(int _value); + +}; + + + +class COption +{ +public: + int initiliazed; + namevalue options[NB_OPTIONS]; + namevalue& find(option_id _id) { return options[_id]; }; + option_id findByName(const char* _name); + + void getParameterFilename(MyString& filename,int nb); + void getStrValue(MyString& str,option_id _id); + int getIntValue(option_id _id); + void setValue(option_id _id,const char* _value, int overideConf=0); + void setIntValue(option_id _id,int _value,int overideConf=0); + //void setConfValue(option_id _id,const char* _value); + //void setConfIntValue(option_id _id,int _value); + void initOptions(); + void setDefaultOptions(); + void generateGUID(MyString& guid); + void loadOptions(); + int loadParameters(int _nb); + void saveOptions(int _nb); + bool addEmulatorParam(const char* _param); + const char* getDescription(option_id _id, int _value); + COption() { initiliazed = 0; }; +/// void initOptions(); + void enableOptions(); +}; + + + +enum eslotstatus +{ + UNDEFINED, + MOUNTED, + READY2MOUNT, + EJECTED, + FAILED, + NOTHING, + DELAYEDMOUNT +}; + +enum eSetSlotPos +{ + ADD, + REPLACECURRENT +}; + +class CActiveImage +{ +public: + int iActive; + int iNb; + CActiveImage(){iActive=0; iNb=0;} +}; + +class CSlotInfo +{ +public: + +#if defined(WIN32) && !defined(UNDER_CE) + CString url; +#else + MyString url; // original url +#endif + + MyString filename; // physical name + MyString prefix; + MyString shortname; // physical filename + int patch_addr; + MyString patch_value; + int size; + int delay; + eslotstatus status; + CSlotInfo() { delay=0; size=0; status=UNDEFINED; patch_addr=0; } +}; + +#define ACTIVEGSMAXIMAGE 16 + + +#define MAX_CHECK 16 +struct ConfigBP +{ + MyString value; + char check[MAX_CHECK]; + int addr; + enum mode_breakpoint mode; +}; + +class CEmulatorConfig +{ +public: + + CActiveImage activeImages[3][MAXSLOT7DRIVES]; + + CSlotInfo localImages[3][MAXSLOT7DRIVES][ACTIVEGSMAXIMAGE]; + MyString baseURL; + CEmulatorConfig(); + int nb_bps; + ConfigBP BPs[MAX_BREAK_POINTS]; + void setBaseURL(const char* _url); + MyString uid; + MyString name; + MyString nameurl; + MyString desc; + MyString year; + MyString publisher; + MyString publisherurl; +// MyString persistentPath; + MyString visibleName; + + bool need2remount; +// bool fastConfig; // pour ignore les images dans le xml si le parametre a ÈtÈ passÈ en ligne de commande +#if defined(WIN32) && defined(_USRDLL) + LONG speed; + LONG bootslot; + CString xmlconfig; + CString emulatorParam; + CString systemParam; + CString bramParam; + CString setStartParam; +#else + int speed; + int bootslot; + MyString xmlconfig; + MyString emulatorParam; + MyString bramParam; + MyString systemParam; + MyString setStartParam; +#endif + MyString xmlEmulatorParam; + MyString xmlSystemParam; + MyString xmlBramParam; + MyString stateFilename; + + simplexml* pXML; + CSlotInfo* setSlot(int _slot, int _drive, const char* _image, eSetSlotPos _pos); + CActiveImage& getActiveImage(int _slot, int _drive); + CSlotInfo& getLocalImage(int _slot,int _drive, int _pos); + const char* getSlot(int _slot, int _drive); + int xmlAlreadyLoaded; + int processXML(const char*_path,simplexml* ptrconfig); + void loadXMLFile(); + void saveXMLFile(const char* _desc); + void processCommandLine(int argc, char** argv); + void resetConfig(); +}; + +#define EMULATOR_MAX_PARAMS 256 + + +extern COption option; + +class CEmulator +{ + +public: + CEmulator** parent; + static CEmulator* theEmulator; + +#ifdef ACTIVEGSPLUGIN + void* pInstance; + void setPluginInstance(void*); +#endif + + int lights[4]; + int tracks[4]; + void setLight(int _motorOn,int _slot, int _drive, int _curtrack); + CEmulatorConfig* config; + int nbparams; + struct param params[EMULATOR_MAX_PARAMS]; + volatile bool bInThread; + void* theWindow; // HWND or WINDOWREF + int x; + int y; + int width; + int height; + +public: + void onSpeedChanged(int _speed, bool _ignoreAcceptEvents=false); + void onBootSlotChanged(int _bootslot); + void onXMLConfigChanged(const char *_xmlconfig,simplexml* _pXML); + void onEmulatorParamChanged(const char* _param); + void addUniqueParam(struct param _p); + void sendStats(); + void checkAlerts(); + int acceptEvents(); + +public: + void setConfig(CEmulatorConfig* _config); + CSetStart setStart; + + void resetLocalIMG(); + int loadDiskImage(int _slot,int _drive); + void reloadDisk(int _slot,int _drive); + void relaunchEmulator(); + void launchEmulator(); + void terminateEmulator(); + // To be defined in son + virtual void x_LaunchThread() = 0; + virtual void x_WaitForEndThread() = 0; + + +public: +// void setURL(const char* _url); + + bool setEmulatorParam(const char* _p ) {return parseParam(_p,EMULATOR); } + MyString bramParam; + void setBramParam(const char* _p); + bool parseParam(const char* _p,eParamType _param); + bool setParam(eParamType _type, const char* _data, const char* _value); + + + bool setStartParam(); + bool extractSetStartParam(const char* run); + +public: + void mountDisks(); + void forceFocus(); + + +//protected: +public: + + CEmulator(CEmulator** _parent); + virtual ~CEmulator() ; + void destroy(); + +public: + void updateBramParameters(); + CSlotInfo& getLocalIMGInfo(int _slot,int _drive); + int getLocalMultipleIMGInfo(int _slot,int _drive,CSlotInfo& info, int pos); + int getSmartSwap(); + int smartSwap(); + int swapDisk(int _slot,int _drive, int pos=-1); + int theThread(); + void mountDisk(int _slot,int _drive, const char* _url); + int mountImages(); + int mountDelayedDisk(); + bool remainingDelayedDisk(); + void ejectDisk(int _slot,int _drive); + void readImageInfo(int _slot,int _drive, int _imagelen, int _imagestart, int _isprodos); + + MyString statusMsg; + + void initBramParam(const char* _param); + void initEmulatorParam(const char* _param); + +void processCommand(const char* _val, MyString& ret); + + virtual void refreshStatus(const char* _msg) {} ; + virtual void showLoading( int _loading,int _disk) {}; + + + virtual void showStatus(const char* _msg) {} ; + virtual void disableConsole() {} ; + virtual void loadingInProgress(int _motorOn,int _slot, int _drive) {}; + virtual int activeRead(char *buf) { buf[0]=0; return 0; } + + virtual void getEngineString(MyString& _engine) {}; +}; + +void x_display_alert(int _abort, const char* _title, const char* _message); + + + + diff --git a/Common/CEmulatorCtrl.cpp b/Common/CEmulatorCtrl.cpp new file mode 100644 index 0000000..ce064ab --- /dev/null +++ b/Common/CEmulatorCtrl.cpp @@ -0,0 +1,2995 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "cemulatorctrl.h" +#include "svnversion.h" + +#include "../kegs/src/adb.h" +#include "../kegs/src/clock.h" +#include "../kegs/src/moremem.h" +#include "../kegs/src/paddles.h" +#include "../kegs/src/sim65816.h" +#include "../kegs/src/iwm.h" +#include "../kegs/src/SaveState.h" +#include "../kegs/src/raster.h" +#include "../kegs/src/graphcounter.h" +#include "../kegs/src/driver.h" +#include "../kegs/src/video.h" +#include "../kegs/src/async_event.h" +extern void joystick_shut(); + +#define CONFIG_VERSION 3 + +const int joyint[] = { (int)JOYSTICK_TYPE_NATIVE_1, (int)JOYSTICK_TYPE_KEYPAD, (int)JOYSTICK_TYPE_MOUSE, /* JOYSTICK_TYPE_NATIVE_2,*/ JOYSTICK_TYPE_NONE, JOYSTICK_TYPE_ICADE, -1 } ; +const char* joyalias[] = { "joystick1","keypad", "mouse", /*, "Joystick2",*/ "none", "iCade", NULL }; +const char* joydesc[] = { "Joystick1","Keypad", "Mouse", /*, "Joystick2",*/ "None", "iCade", NULL }; +const int colorint[] = { (int)COLORMODE_AUTO, (int)COLORMODE_BW, (int)COLORMODE_GREEN, (int)COLORMODE_AMBER,(int)COLORMODE_MONO, -1 }; +const char* coloralias[] = { "auto", "bw", "green", "amber", "mono",NULL }; +const char* colordesc[] = { "Colors", "B&W", "Green", "Amber", "Mono", NULL }; +const char* videoalias[] = { "crt" , "lcd" ,"default", NULL }; +const char* videodesc[] = { "CRT" , "LCD",NULL, NULL }; +const int videoint[] = { (int)VIDEOFX_CRT, (int)VIDEOFX_LCD, (int)VIDEOFX_LCD, -1 }; +const char* speeddesc[] = { "Normal", "Slow", "Zip", "Unlimited", NULL }; +const char* speedalias[] = { "normal", "slow", "zip", "unlimited", NULL }; +const int speedint[] = { (int)SPEED_GS, (int)SPEED_1MHZ, (int)SPEED_ZIP, (int)SPEED_UNLIMITED, -1 }; + + +#define DEFAULT_AUDIO_RATE 44100 +#define DEFAULT_LOCKZOOM 0 +#define DEFAULT_DEBUGMODE 0 +#define DEFAULT_DISKSOUND 1 +#define DEFAULT_VIDEO VIDEOFX_CRT + +const namevaluedef defoptions[] = +{ + { 1,0, "configVersion" , CONFIG_VERSION,NULL, NULL, NULL }, + { 1,0, "guid" , 0, NULL, NULL, NULL }, + { 1,1, "haltOnBadRead" , 0, NULL, NULL, NULL }, + { 1,1, "haltOnBadAcc" , 0, NULL, NULL, NULL }, + { 1,1, "haltOnHalts" , 0, NULL, NULL, NULL }, + { 1,1, "enableRewind" ,0, NULL, NULL, NULL }, + { 1,1, "colorMode" , 0, NULL, colordesc,coloralias , colorint }, + { 1,1, "videoFX", (int)DEFAULT_VIDEO, NULL, videodesc, videoalias , videoint }, + { 1,1, "joystickMode", 0, NULL, joydesc, joyalias, joyint }, + { 0,0, "browserName" , 0, NULL, NULL, NULL }, + { 0,0, "browserVer" , 0, NULL, NULL, NULL }, + { 2,0, "latestRunBuild" , 0, NULL, NULL, NULL }, + { 2,0, "latestUpdateCheck" , 0, NULL, NULL, NULL }, + { 1,0, "doNotShowUpdateAlert" , 0, NULL, NULL, NULL }, + { 0,0, "doNotShowDiskStatus" , 0, NULL, NULL, NULL }, + { 0,0, "PNGBorder" , 16, NULL, NULL, NULL }, + { 0,0, "simulateSpace" , 0X31, NULL, NULL, NULL }, // 0X31=SPACE KEY + { 0,0, "latestVersion" , 0, NULL, NULL, NULL }, + { 0,0, "speed" , 0, NULL, speeddesc, speedalias, speedint }, + { 0,0, "latestVersionDate" , 0, NULL, NULL, NULL }, + { 1,1, "audioRate" , DEFAULT_AUDIO_RATE, NULL, NULL, NULL }, + { 1,1, "memorySize" , 2, NULL, NULL, NULL }, + { 0,0, "joyXScale" , 1000, NULL, NULL, NULL }, + { 0,0, "joyYScale" , 1000, NULL, NULL, NULL }, + { 1,1, "diskSound" , DEFAULT_DISKSOUND, NULL, NULL, NULL }, + { 0,1, "fixedVBlank" , 0, NULL, NULL, NULL }, + { 0,1, "adbDelay" , 45, NULL, NULL, NULL }, + { 0,1, "adbRate" , 3, NULL, NULL, NULL } +#ifdef DRIVER_IOS + , + { 1,1, "frameRate" , 0, NULL, NULL, NULL }, + { 1,1, "lockZoom" , DEFAULT_LOCKZOOM, NULL, NULL, NULL }, + { 1,1, "lastTab" , 0, NULL, NULL, NULL }, + { 1,1, "debugMode" , DEFAULT_DEBUGMODE, NULL, NULL, NULL }, + { 1,1, "externalKBD" , 0, NULL, NULL, NULL } +#endif +#ifdef ACTIVEGSKARATEKA + , + { 1,1, "showIcons" , 1, NULL, NULL, NULL }, + { 0,1, "enableCheats" , 0, NULL, NULL, NULL }, + { 1,1, "soundMode" , 0, NULL, NULL, NULL }, + { 1,1, "karatekaRewind" , 1, NULL, NULL, NULL }, + + +#endif +#ifdef VIRTUALAPPLE + { 1,1, "debug" , 0, NULL, NULL, NULL }, + { 1,1, "scores" , 0, NULL, NULL, NULL }, + { 1,1, "gamecenter" , 0, NULL, NULL, NULL }, +#endif +}; + +COption option; + +const char* COption::getDescription(option_id _id, int _value) +{ + namevalue& nv = find(_id);; + return nv.getDescription(_value); +} + +int namevalue::belongsToValue(int _v) +{ + if (!def->convertTableInt) return 1; + int i=0; + while(def->convertTableInt[i]!=-1) + { + if (def->convertTableInt[i]==_v) + return 1; + i++; + } + + return 0; +} + +int namevalue::getOrder(int _value) +{ + int p = 0; + while(def->convertTableInt[p] != -1) + { + if (def->convertTableInt[p]==_value) + return p; + p++; + } + return -1; +} + +const char* namevalue::getDescription(int _value) +{ + const char* ret = "n/a"; + if (!def->convertTableInt) return ret; + int o = getOrder(_value); + if (o<0) return ret; + return def->convertTableDesc[o]; +} + + +CEmulator* CEmulator::theEmulator = NULL; + +char bram_default[]={ +(char)0x00, (char)0x00, (char)0x00, (char)0x01, (char)0x00, (char)0x00, (char)0x0D, (char)0x06, (char)0x02, (char)0x01, (char)0x01, (char)0x00, (char)0x01, (char)0x00, (char)0x00, (char)0x00, +(char)0x00, (char)0x00, (char)0x07, (char)0x06, (char)0x02, (char)0x01, (char)0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x0F, (char)0x06, (char)0x06, (char)0x00, (char)0x05, (char)0x06, +(char)0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x03, (char)0x02, (char)0x02, (char)0x02, +(char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x01, (char)0x02, (char)0x03, (char)0x04, (char)0x05, (char)0x06, +(char)0x07, (char)0x00, (char)0x00, (char)0x01, (char)0x02, (char)0x03, (char)0x04, (char)0x05, (char)0x06, (char)0x07, (char)0x08, (char)0x09, (char)0x0A, (char)0x0B, (char)0x0C, (char)0x0D, +(char)0x0E, (char)0x0F, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, +(char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFF, (char)0xFD, (char)0x96, (char)0x57, (char)0x3C +}; + +void updateBramCheckSum(unsigned char* buf) // original code in FF/B61D +{ + register short int crc=0; // LDA #0 + int i; // CLC + for(i=255-4-1;i>=0;i--) // LDX #FA + { + crc = (crc << 1) | ((crc>>15) & 1); // ROL (1-bits) +#ifdef UNDER_CE + crc += buf[i]; + crc += buf[i+1]*256; +#else + crc += *(unsigned short*)(buf+i); // ADC bram,X +#endif + } // DEX + // CPX #FF + // BNE Loop + *(unsigned short*)(buf+252) = crc; // TAX + *(unsigned short*)(buf+254) = crc ^0xAAAA; // EOR #AAAA +} + + +void initializeBram(unsigned char* _bram_ptr) +{ + memcpy(_bram_ptr,bram_default,256); + updateBramParameters(_bram_ptr); + updateBramCheckSum(_bram_ptr); + +} + + +void COption::generateGUID(MyString& guid) +{ + + int crc = calcCRC(CDownload::getPersistentPath()); + + time_t now; + time( &now ); + int lowtime = (int)now; + guid.Format("%08X%08X",crc,lowtime); + +} + +void CEmulatorConfig::resetConfig() +{ + speed = SPEED_AUTO; + bootslot = -1; //auto +// fastConfig = false; +// pXML=NULL; + + // vire tous les slots + for(int i=0;i<3;i++) + { + for(int m=0;mconvertTableInt) return 0; + int i=0; + const char* str; + while( (str=def->convertTableAlias[i]) != NULL ) + { + if(!strcasecmp(_value,str)) + return def->convertTableInt[i]; + i++; + } + printf("err: could not convert %s : returning %s (%d)\n",_value,def->convertTableAlias[0],def->convertTableInt[0]); + return def->convertTableInt[0]; +} + +option_id COption::findByName(const char* _name) +{ + if (!_name) return (option_id)-1; + + for (int i=0;iname)) + return (option_id)i; + } +#ifdef _DEBUG + printf("cannot find option : %s\n",_name); +#endif + return (option_id)-1; + +} + +void COption::setValue(option_id _id,const char* _value,int _confOverrided) +{ + + + namevalue& nv = find(_id); + int isnum=1; + const char*p=_value; + while(*p) + { + if (*p<'0' || *p>'9') + { + isnum=0; + break; + } + p++; + } + int v; + if (isnum) + v=atoi(_value); + + if (!nv.def->convertTableInt) + { + + if (!isnum) + { + nv.strvalue = _value; + printf("> option %s: %s\n",nv.def->name,_value); + } + else + { + nv.intvalue = v; + printf("> option %s: (%d)\n",nv.def->name,nv.intvalue); + } + + nv.confOverrided = _confOverrided; + + } + else + { + + if (isnum && nv.belongsToValue(v)) + { + nv.intvalue = v; + nv.confOverrided = _confOverrided; + printf("> option %s: %s (%d)\n",nv.def->name,nv.getDescription(v),nv.intvalue); + } + else + { + // regarde si c'est une valeur en texte? + int pos=0; + const char* s; + while( (s = nv.def->convertTableAlias[pos]) != NULL ) + { + if (!strcasecmp(s,_value)) + { + nv.intvalue = nv.def->convertTableInt[pos]; + nv.confOverrided = _confOverrided; + printf("* option %s: %s (%d)\n",nv.def->name,_value,nv.intvalue); + return ; + } + pos++; + } + printf("non supported value:%s for option:%s\n",_value,nv.def->name); + } + } +} + + +void namevalue::getAlias(MyString& _str) +{ + if (this->strvalue.IsEmpty()) + { + // convert to int first + int v = this->intvalue; + if (!this->def->convertTableInt) + _str.Format("%d",v); + else + { + int i = getOrder(v); + _str = this->def->convertTableAlias[i]; + } + return ; + } + else + _str = this->strvalue; +} + + + +void COption::initOptions() +{ + + for(int i=0;iinDefault) + { + if (options[i].def->convertTableInt) + options[i].intvalue =options[i].def->convertTableInt[0]; + else + { + options[i].intvalue = options[i].def->defaultint; + options[i].strvalue = options[i].def->defaultstr; + } + + } + } + + if (g_driver.x_apply_default_options!=NULL) + g_driver.x_apply_default_options((void*)this); + + printf("*restored default options\n"); +} + + +void COption::setIntValue(option_id _id, int _v, int _confOverrided) +{ + MyString str; + + namevalue& nv =find(_id); + + if (!nv.belongsToValue(_v)) + { + printf("err: unrecognized value %d for %s\n",_v,nv.def->name); + return ; + } + + nv.intvalue = _v; + if (nv.def->convertTableInt) + printf("option %s set to %s (%d)\n",nv.def->name,nv.getDescription(_v),_v); + else + printf("option %s set to (%d)\n",nv.def->name,_v); + + nv.confOverrided = _confOverrided; + +} + +void COption::getStrValue(MyString& _str,option_id _id) +{ + namevalue& nv =find(_id); + + if (nv.strvalue.IsEmpty()) + { + if (nv.def->convertTableInt) + _str = nv.getDescription(nv.intvalue); + else + _str.Format("%d",nv.intvalue); + } + else + _str = nv.strvalue.c_str(); +} + +int COption::getIntValue(option_id _id) +{ + namevalue& nv =find(_id); + + if (!nv.def->convertTableInt || nv.strvalue.IsEmpty()) + return nv.intvalue; + else + { + printf("getintvalue: mismatched type for %s\n",nv.def->name); + return 0; + } +} + +void COption::saveOptions(int _nb) +{ + MyString filename; + getParameterFilename(filename,_nb); + FILE* f = fopen(filename.c_str(),"wt"); + if (!f) + { + outputInfo("cannot create %s for saving options\n",filename.c_str()); + return ; + } + for(int i=0;iinConfig == _nb) + { + MyString line; + MyString desc; + options[i].getAlias(desc); + line.Format("%s:%s\n",options[i].def->name,desc.c_str()); + fputs(line.c_str(),f); + } + } + fclose(f); + //outputInfo("options saved (%s)\n",filename.c_str()); + enableOptions(); +} + + + + +void COption::loadOptions() +{ + + int b = loadParameters(1); + if (!b) + { + // si il n'y avait pas de fichier conf - rajoute le guid au option par défaut et sauve le + MyString guid; + generateGUID(guid); + setValue(OPTION_GUID,guid.c_str()); + saveOptions(1); + } + + // vérifie le numéro de version + int v = getIntValue(OPTION_CONFIGVERSION); + if (v < CONFIG_VERSION) + { + // réinitialise + initOptions(); + setIntValue(OPTION_CONFIGVERSION,CONFIG_VERSION); + printf("upgrading config file to v" TOSTRING(CONFIG_VERSION)); + saveOptions(1); + } + + loadParameters(2); +} + +void COption::getParameterFilename(MyString& filename,int _nb) +{ + filename = CDownload::getPersistentPath(); + filename += ACTIVEGS_DIRECTORY_SEPARATOR ; + filename += "activegs"; + if (_nb==1) + filename += ".conf"; + else + filename += ".ext"; +} + +int COption::loadParameters(int _nb) +{ + + MyString filename; + getParameterFilename(filename,_nb); + + FILE* f = fopen(filename,"rt"); + if (f) + { + outputInfo("loadOptions from %s\n",filename.c_str()); + char line[1025]; + line[1024]=0; + while(fgets(line,1024,f)) + { + int i=0; + while(line[i]!=':' && line[i])i++; + if (line[i]==':') + { + line[i++]=0; + option_id id = findByName(line); + if (id == OPTION_ERROR) + outputInfo("option %s ignored\n",line); + else + { + + int vpos = i; + while( line[i] + && + (line[i]!='\t') + && + (line[i]!='\r') + && + (line[i]!='\n') + /* + && + (line[i]!=' ') */) i++; + + if (line[vpos]) + { + // trim + while(line[i-1]==' ')i--; + line[i]=0; + setValue(id,line+vpos); + } + } + } + } + fclose(f); + return 1; + } + else + return 0; +} + + +CEmulatorConfig::CEmulatorConfig() +{ + xmlAlreadyLoaded = 0; + pXML=NULL; + bramParam.Empty(); + emulatorParam.Empty(); + nb_bps=0; + resetConfig(); +} + +void CEmulatorConfig::setBaseURL(const char* _url) +{ + MyString p = _url; + + if (!strncasecmp(p.c_str(),"file://localhost/",17)) + baseURL = p.substr(16,p.length()-16); // absolute path OG 250810 - leave the trailing slash + else + if (!strncasecmp(p.c_str(),"file:///",8)) +#ifdef WIN32 + baseURL = p.substr(8,p.length()-8); // absolute path +#else + baseURL = p.substr(7,p.length()-7); // keep the / on mac +#endif + else + if (!strncasecmp(p.c_str(),"file://",7)) + baseURL = p.substr(7,p.length()-7); // absolute path + else + baseURL = p; + + baseURL.Replace("%20"," "); + printf("baseURL set to %s\n",baseURL.c_str()); + /* + CDownload dl; + dl.setBaseURL(baseURL.c_str()); + */ +} + +CSlotInfo& CEmulatorConfig::getLocalImage(int _slot, int _drive, int _pos) +{ + return localImages[_slot-5][_drive-1][_pos]; +} + +CActiveImage& CEmulatorConfig::getActiveImage(int _slot, int _drive) +{ + return activeImages[_slot-5][_drive-1]; +} + +CSlotInfo* CEmulatorConfig::setSlot(int _slot, int _disk, const char * _url_normalized, enum eSetSlotPos _pos) +{ + if (_slot<5 || _slot > 7 || _disk < 1 || (_slot==7 && _disk > MAXSLOT7DRIVES) || (_slot!=7 && _disk > 2) ) + { + printf("invalid slot : %d:%d\n",_slot,_disk); + return NULL; + } + // normalise pour garder la compatibilité avec les version < 3.5 + MyString url = _url_normalized; + int pos = url.ReverseFind('?'); + if (pos != -1 ) + { + int i = url.at(pos+1); + size_t l = url.length(); + if (l==(pos+2) && i>='0' && i<='9') + { + url = url.Left(pos); + url += "#pos="; + url += i; + } + } + + const char* _url = url.c_str(); + if (_url && !_url[0]) _url=0; + CActiveImage& ai = activeImages[_slot-5][_disk-1 ]; + + int active=0; + if (_pos==REPLACECURRENT) // posactive + { + active = ai.iActive; + if (!ai.iNb) + { + // ignore SetSlot = NULL si aucun disk n'avait été préalablement chargé + if (!_url) return NULL; + ai.iNb=1; + } + } + else + // if (_pos==ADD) + { + // regarde si le disk était déjà présent dans la liste + for(int i =0;i2048) + { + // overflow! + outputInfo("status set to FAILED(invalid length) for S%dD%d\n",_slot,_disk); + ref.status = FAILED; + } + else + { + ref.url = _url; + ref.url.Trim(); // OG Fix ending space + ref.shortname = getfile(_url); + ref.status = READY2MOUNT; + outputInfo("status set to READY2MOUNT for S%dD%d, image: %s\n",_slot,_disk,ref.shortname.c_str()); + } + } + need2remount=true; + x_refresh_panel(PANEL_DISK); + } + return &ref; +} + +const char* CEmulatorConfig::getSlot(int _slot, int _disk) +{ + if (_slot<5 || _slot > 7 || _disk < 1 || _disk > MAXSLOT7DRIVES) + return NULL; + CActiveImage active = activeImages[_slot-5][_disk-1 ]; + CSlotInfo& ref = localImages[_slot-5][_disk-1 ][active.iActive]; + return STRING2CONSTCHAR(ref.url); +} + + +void CEmulatorConfig::processCommandLine(int argc, char** argv) +{ + + for(int i=1;i.activegsxml||]", ACTIVEGSVERSIONSTRFULL,MB_OK); + ::PostQuitMessage(0); +#endif + } + else + if ((i+1)setSlot(5,1,value,ADD); + else + if (!strcasecmp(option,"slot52")) + this->setSlot(5,2,value,ADD); + else + if (!strcasecmp(option,"slot61")) + this->setSlot(6,1,value,ADD); + else + if (!strcasecmp(option,"slot62")) + this->setSlot(6,2,value,ADD); + else + if (!strcasecmp(option,"slot71")) + this->setSlot(7,1,value,ADD); + else + if (!strcasecmp(option,"slot72")) + this->setSlot(7,2,value,ADD); + else + if (!strcasecmp(option,"BootSlot")) + { + int bs = atoi(value); + this->bootslot = bs; + } + else + if (!strcasecmp(option,"Speed")) + { + int s = atoi(value); + this->speed=s; + } + else + if (!strcasecmp(option,"EmulatorParam")) + this->emulatorParam=value; + else + if (!strcasecmp(option,"SystemParam")) + this->systemParam=value; + else + if (!strcasecmp(option,"BramParam")) + this->bramParam=value; + else + if (!strcasecmp(option,"XMLConfig")) + this->xmlconfig=value; + else + if (!strcasecmp(option,"state")) + { + CDownload dl(this->baseURL); + // dl.setBaseURL(_path); + MyString path; + MyString shortn; + dl.retrieveFile(value,path,shortn); + this->stateFilename=path.c_str(); + } + } + } + else + { + // vérifie l'extension (mais strip le #) + MyString extv(argv[i]); + int l = extv.ReverseFind("#"); + if (l>0) + extv = extv.Left(l); + const char* ext = getext(extv.c_str()); + if ( !strcasecmp(ext,"activegsxml") || !strcasecmp(ext,"xml")) + { + this->xmlconfig = argv[i] ; + } + else + { + MyString path; + MyString file; + // CDownload dl; + int slot = 0; + + // dl.deleteCachedFile(argv[i]); + CDownload dl(this->baseURL); + size_t size = dl.retrieveFile(argv[i],path,file); + ext = getext(path.c_str()); + if (!strcasecmp(ext,"hdv")) + { + slot = 7; + } + else + if (!strcasecmp(ext,"2mg") || !strcasecmp(ext,"po")) + { + if (size> 819712) // OG Fix 2MG size recognitioN (CF. RASTAN 819264 & POMS 7 819712) + slot = 7; + else + slot = 5; + } + else + if ( !strcasecmp(ext,"bin") || !strcasecmp(ext,"dsk") || !strcasecmp(ext,"nib") || !strcasecmp(ext,"po") || !strcasecmp(ext,"do") ) + slot = 6; + if (slot) + { + setSlot(slot,1,path,REPLACECURRENT); + // bootslot = slot; OG Laisse la valeur par défaut! + xmlconfig.Empty(); + } + else + outputInfo("Unknown extension .%s\n",ext); + } + } + } +} + +int CEmulatorConfig::processXML(const char*_path,simplexml* ptrconfig) +{ + + const char* ver = ptrconfig->property("version"); + if (!ver || atoi(ver)!=2) + { + outputInfo("invalid xml version - xml config skipped\n"); + return 0; + } + + int child = ptrconfig->number_of_children(); + for(int i=0;ichild(i); + if (!strcasecmp(ptr->key(),"uid")) + { + const char* s = ptr->value(); + uid = s; + } + else + if (/*!fastConfig && */!strcasecmp(ptr->key(),"image")) + { + int slot = atoi(ptr->property("slot")); + int disk = atoi(ptr->property("disk")); + if ( + ( ( slot==5 || slot==6 ) && ( disk==1 || disk==2) ) + || + ( (slot==7) && ( disk>=1 || disk<=MAXSLOT7DRIVES) ) + ) + { + + MyString absp ; + const char* s = ptr->value(); + int patch_addr = 0; + const char* patch_value = NULL; + + for(int idisk=0;idisknumber_of_children();idisk++) + { + simplexml* ptrd = ptr->child(idisk); + if (!strcmp(ptrd->key(),"name")) + s = ptrd->value(); + else + if (!strcmp(ptrd->key(),"patch")) + { + const char* addr_str = ptrd->property("addr"); + if (addr_str) + { + sscanf(addr_str,"%X",&patch_addr); + patch_value = ptrd->value(); + if (strlen(patch_value)&1) + patch_value=NULL; // doit être pair + } + } + } + + if (s) + { + // CDownload dl(this->baseURL); + CDownload::makeAbsolutePath(s,_path,absp); + + CSlotInfo* pslot = setSlot(slot,disk,absp.c_str(),ADD); + if (pslot && patch_value && patch_addr) + { + pslot->patch_addr = patch_addr; + pslot->patch_value = patch_value; + pslot->patch_value.MakeUpper(); + } + } + } + } + else + if (/*!fastConfig && */!strcasecmp(ptr->key(),"bootslot")) + { + int slot = atoi(ptr->value()); + if (slot>=5 && slot<=7) + { + bootslot = slot; + } + } + else + if (!strcasecmp(ptr->key(),"runtime")) + { + const char* mode_str = ptr->property("mode"); + if (mode_str) + { + enum mode_breakpoint mode = BRK_DISABLED; + if (strchr(mode_str,'X')) + mode = (enum mode_breakpoint)(mode|BRK_X); + if (strchr(mode_str,'R')) + mode = (enum mode_breakpoint)(mode|BRK_READ); + if (strchr(mode_str,'W')) + mode = (enum mode_breakpoint)(mode|BRK_WRITE); + if (strchr(mode_str,'P')) + mode = (enum mode_breakpoint)(mode|BRK_PATCH); + if (strchr(mode_str,'B')) + mode = (enum mode_breakpoint)(mode|BRK_STOP); + if (strchr(mode_str,'S')) + mode = (enum mode_breakpoint)(mode|BRK_SLOWSPEED); + if (strchr(mode_str,'D')) + mode = (enum mode_breakpoint)(mode|BRK_DEFAULTSPEED); + if (strchr(mode_str,'M')) + mode = (enum mode_breakpoint)(mode|BRK_MESSAGE); + + + + const char* addr_str = ptr->property("addr"); + if (addr_str && !(strlen(addr_str)&1)) + { + word32 patch_addr; + sscanf(addr_str,"%X",&patch_addr); + + const char* value_str = ptr->value(); + if (value_str == NULL || !(strlen(addr_str)&1)) + { + + int bp = nb_bps; + if (bp != MAX_BREAK_POINTS) + { + + + const char* check = ptr->property("check"); + memset(BPs[bp].check,0,MAX_CHECK); + if (check!=NULL) + { + // printf("found check:%s\n",check); + int i=0; + while(i='a') + c1 -= ('a'-10); + else + if (c1>='A') + c1 -= ('A'-10); + else + c1 -= '0'; + + if (c2>='a') + c2 -= ('a'-10); + else + if (c2>='A') + c2 -= ('A'-10); + else + c2 -= '0'; + + BPs[bp].check[i++]= c1*16+c2; + } + + } + + BPs[bp].addr= patch_addr; + BPs[bp].value = value_str; + BPs[bp].mode = mode; + nb_bps++; + } + } + } + } + } + else + if (!strcasecmp(ptr->key(),"speed")) + { + int sp = atoi(ptr->value()); + if (sp>=0 && spkey(),"bramparam")) + { + const char* s = ptr->value(); + xmlBramParam = s; + } + else + if (!strcasecmp(ptr->key(),"emulatorparam")) + { + const char* s = ptr->value(); + xmlEmulatorParam = s; + } + else + if (!strcasecmp(ptr->key(),"systemparam")) + { + const char* s = ptr->value(); + xmlSystemParam = s; + } + else + if (!strcasecmp(ptr->key(),"name")) + { + const char* s = ptr->value(); + name = s; + } + else + if (!strcasecmp(ptr->key(),"desc")) + { + const char* s = ptr->value(); + desc = s; + } + else + if (!strcasecmp(ptr->key(),"publisher")) + { + const char* s = ptr->value(); + publisher = s; + } + else + if (!strcasecmp(ptr->key(),"year")) + { + const char* s = ptr->value(); + year = s; + } + if (!strcasecmp(ptr->key(),"state")) + { + const char* s = ptr->value(); + CDownload dl(_path); // ??? + MyString path; + MyString shortn; + dl.retrieveFile(s,path,shortn); + stateFilename=path.c_str(); + } + + } + + return 1; +} + + +void CEmulatorConfig::loadXMLFile() +{ + + + if (xmlconfig.IsEmpty() && !pXML) + { + xmlEmulatorParam.Empty(); + xmlSystemParam.Empty(); + xmlBramParam.Empty(); + return ; + } + + if (xmlAlreadyLoaded) + { + printf("discard xml...\n"); + return ; + } + resetConfig(); + xmlAlreadyLoaded = 1; + + + // If XML already present, use preparsed structrue + if (pXML) + { + processXML(baseURL.c_str(),pXML); + return ; + } + + MyString fullpath; + MyString fulldir; + //CDownload dl; + CDownload::makeAbsolutePath(STRING2CONSTCHAR(xmlconfig),baseURL.c_str(),fullpath); + getdir(fullpath.c_str(),fulldir); + xmlconfig = fullpath.c_str() ; + + ActiveGSList list; + if (!list.loadFromFile(STRING2CONSTCHAR(xmlconfig))) + return ; + + simplexml* ptrconfig = NULL; + if (list.elements.size()==1) + ptrconfig = list.elements.at(0).pXML; + else + { + CStdStringA xmlconfig2 = xmlconfig; + int pos = xmlconfig2.ReverseFind("#id="); + if (pos==-1) + { + printf("No key requested with .activegsxml list format\n"); + return ; + } + + MyString key = xmlconfig2.Mid(pos+4); + for(unsigned int i=0;ibaseURL.c_str(),domain); + str += "&d="; + str += domain.c_str(); + +#ifdef ACTIVEGSPLUGIN + CDownload dl; + dl.GetFile(str.c_str(),NULL); +#endif +#endif + */ +} + +void CEmulator::setConfig(CEmulatorConfig* _config) +{ + config = _config; + + sendStats(); + config->loadXMLFile(); + /* + CDownload dl; + dl.setBaseURL(config->baseURL.c_str()); + */ +} + + +char read2MG(const char* ref,int block, int byte) +{ + return ref[0x40+block*512+byte]; +} + +int find2MG(const char* ref,int block, char header, const char* str) +{ + int byte = 4; + + while (1) + { + char r = read2MG(ref,block,byte); + if (!r) return 0; + + if (r==header) + { + int c=0; + while(str[c]) + { + if (read2MG(ref,block,byte+c+1)!=str[c]) break; + c++; + } + if (!str[c]) + { + // found! + return block*512+byte; + } + } + byte+=0x27; + if (byte==0x1FF) + { + byte =4; + block = read2MG(ref,block,2) + read2MG(ref,block,3)*256; + if (!block) return 0; + } + + } + return 0; +} + + + +int findSetStart(const char* buffer) +{ + // start dir + + int sys = find2MG(buffer,2,(char)0xD6,"SYSTEM"); + if (!sys) + { + outputInfo("cannot find System dir!"); + return false; + } + + int sysbloc = buffer[sys+0x40+0x11]+buffer[sys+0x40+0x12]*256; + + int setstart = find2MG(buffer,sysbloc,0x1D,"SETSTART.DATA"); + if (!setstart) + { + outputInfo("cannot find setstart file"); + return false; + } + + return setstart; + +} + +bool CEmulator::setStartParam() +{ + // prend le nom du fichier en 71 + + int slot = setStart.slot/10; + int drive = setStart.slot%10; + CSlotInfo& ref = getLocalIMGInfo(slot,drive); + const char* filename= ref.filename.c_str(); //getLocalIMG(setStart.slot/10,setStart.slot%10); + if (!filename) return false; + FILE* f=fopen(filename,"rb"); + if (!f) return false; + + // get file size + fseek(f,0,SEEK_END); + int filesize=ftell(f); + + char* buffer=(char*)malloc(filesize); + + fseek(f,0,SEEK_SET); + fread(buffer,1,filesize,f); + fclose(f); + + // + int offset = findSetStart(buffer); + if (!offset) + { + free(buffer); + return false; + } + + char *entry = buffer+offset+0x40; + + /* + char *entry = buffer+setStart.addr; + */ + if ((entry[0]!=0x1D) || (strcmp(entry+1,"SETSTART.DATA")) ) + { + free(buffer); + return false; + } + + + + // buffer + 17 = block + int blockpos = (entry[17]+entry[18]*256)*512+64; + + // buffer + 19 = size + int size = setStart.file.length(); + entry[0x15]=(size+3)&0xFF; + entry[0x16]=((size+3)>>8)&0xFF; + entry[0x17]=0; + + + char* block = buffer+blockpos; + memset(block,0,256); + block[0]=size&0xFF; + block[1]=(size>>8)&0xFF; + strcpy(block+2,setStart.file.c_str()); + block[size+2]=0x31; // ???? + + f=fopen(filename,"wb"); + if (!f) + { + free(buffer); + return false; + } + fseek(f,0,SEEK_SET); + fwrite(buffer,1,filesize,f); + fclose(f); + free(buffer); + + struct param p; + p.data = "SetStart"; + p.value = setStart.file; + p.hex = offset+0x40; //setStart.addr; + addUniqueParam(p); + // params.push_back(p); + + x_refresh_panel(PANEL_PARAMS); + + return true; +} + + +int CEmulator::acceptEvents() +{ + return r_sim65816.get_state()==RUNNING; +} + + +void CEmulator::onEmulatorParamChanged(const char* _param) +{ + if (!acceptEvents()) + { + outputInfo("### onEmulatorParamChanged Ignored"); + return; + } + option.addEmulatorParam(_param); + setEmulatorParam(_param); + option.enableOptions(); +} + +void CEmulator::onBootSlotChanged(int _bootslot) +{ + if (!acceptEvents()) + { + outputInfo("### OnBootSlotChanged Ignored"); + return; + } + config->bootslot = _bootslot; + relaunchEmulator(); +} + +void CEmulator::relaunchEmulator() +{ + outputInfo("Trying to relaunch Emulator()\n"); + + if (this !=theEmulator) + { + outputInfo("Another instance was running in another process : killing it()\n"); + delete theEmulator; + } + + forceFocus(); + + if (bInThread) + { + outputInfo("Asking for current instance to restart\n"); + r_sim65816.restart_emulator(); + } + else + { + outputInfo("reactivate emulator!\n"); + launchEmulator(); + } +} + + +void CEmulator::onSpeedChanged(int _speed, bool _ignoreAcceptEvents) +{ + + if (!_ignoreAcceptEvents && !acceptEvents()) + { + outputInfo("### onSpeedChanged Ignored"); + return; + } + + /* + int sp = g_sim65816.set_limit_speed((speedenum)_speed); + config->speed = sp; + */ + option.setIntValue(OPTION_SPEED,_speed); + option.enableOptions(); + forceFocus(); +} + +void CEmulator::addUniqueParam(struct param _p) +{ + int i; + for(i=0;i params; + + vector::iterator v; + v = params.begin(); + while(v!=params.end()) + { + if (v->data == _p.data) + { + v->value = _p.value; + v->hex = _p.hex; + return ; + } + v++; + } + params.push_back(_p); +*/ +} + + +const char* currentBuild=TOSTRING(ACTIVEGSMAJOR)"." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD); + + + +void CEmulator::checkAlerts() +{ + + static int bRunOnlyOnce=0; + if (bRunOnlyOnce) return ; + bRunOnlyOnce=1; + +#ifdef _DEBUG + option.setValue(OPTION_LATESTVERSION,"5.1.4"); +#endif + + if (!option.getIntValue(OPTION_DONOTSHOWUPDATEALERT)) + { + MyString newestBuild; option.getStrValue(newestBuild,OPTION_LATESTVERSION); + MyString lastestUpdatedBuild; option.getStrValue(lastestUpdatedBuild,OPTION_LATESTUPDATECHECK); + if ( !newestBuild.IsEmpty() + && lastestUpdatedBuild.compare(newestBuild) + && newestBuild.compare(currentBuild) ) + { + option.setValue(OPTION_LATESTUPDATECHECK,newestBuild); + option.saveOptions(2); + + x_alert("A newer version (%s) of ActiveGS is available!\nCheck http://activegs.freetoolsassociation.com for more info.",newestBuild.c_str(),currentBuild); + + return ; + } + + + } + +} + +bool CEmulator::setParam(eParamType _type, const char* _data, const char* _value) +{ + + static const struct { const char* name; int* address; } variables[] = + { + + // boot + { "boot", (int*)0x28 }, + + // drive emulation + { "driveemulation", &g_iwm.g_fast_disk_emul }, + { "slow", (int*)0 }, + { "fast", (int*)1 }, + + // slot + { "slot6", (int*)0x26 }, + { "drive", (int*)0 }, + { "disk", (int*)0 }, + { "card",(int*)1}, + + // columns + { "columns", (int*)0x19 }, + { "40", (int*)0 }, + { "80", (int*)1 }, + + // speed + + { "forcespeed", (int*)0x20 }, + { "normal",(int*)0}, + { "fast",(int*)1}, + + { "zipspeed",&g_moremem.g_zipgs_reg_c05a}, + // { "simulatespace",&g_adb.g_simulate_space}, + { "emulate6502",&g_sim65816.g_6502_emulation }, + { "apple2erom",&g_sim65816.g_use_apple2e_rom }, + + // bram + { "font", (int*)0x1A }, + { "background", (int*)0x1B }, + { "border", (int*)0x1C }, + + { "black", (int*)0x00 }, + { "dark-blue", (int*)0x02 }, + { "dark-green", (int*)0x04 }, + { "medium-blue", (int*)0x06 }, + { "brown", (int*)0x08 }, + { "light-gray", (int*)0x0A }, + { "green", (int*)0x0C }, + { "aquamarine", (int*)0x0E }, + { "deep-red", (int*)0x01 }, + { "purple", (int*)0x03 }, + { "dark-gray", (int*)0x05 }, + { "light-blue", (int*)0x07 }, + { "orange", (int*)0x09 }, + { "pink", (int*)0x0b }, + { "yellow", (int*)0x0d }, + { "white", (int*)0x0f }, + + { "language", (int*)0x29 }, + { "keyboard", (int*)0x2a }, + { "french", (int*)0x02 }, + /* +* $0 = USA Dvorak +* $1 = UK USA +* $2 = French USA +* $3 = Danish USA +* $4 = Spanish USA +* $5 = Italian USA +* $6 = German USA +* $7 = Swedish + */ + { NULL, NULL } + }; + + int value = -1000; + int* data = 0; + + if (!strcasecmp(_data,"driveemulation")) + data=0; + + int i=0; + while(variables[i].name) + { + if (!strcasecmp(_data,variables[i].name)) + { + data = (int*)variables[i++].address; + while(variables[i].name) + { + if (!strcasecmp(_value,variables[i].name)) + { + value = (intptr_t)(variables[i].address); + break; + } + i++; + } + } + else + i++; + } + + + + if (value==-1000) + value=atoi(_value); + if (!data) + data=(int*)atoi(_data); + + if ( data && (value!=-1000)) + { + outputInfo("%s = %s (%d)\n",_data,_value,value); + + struct param p; + p.data = _data; + p.value = _value; + p.hex = value; + + if (data==&g_moremem.g_zipgs_reg_c05a) + { + g_moremem.g_zipgs_reg_c05a = ((g_moremem.g_zipgs_reg_c05a&0x0F)|(value&0x0F)<<4); + p.value.Format("%3d%%",(int)((16-((g_moremem.g_zipgs_reg_c05a>>4)&0x0F))*100/16)); + } + else + if ((intptr_t)data > 256) +// if (_type==EMULATOR) + *data = value; + else + { + // bram + int idx = (intptr_t)data; + if (idx>0 && idx<256) + g_clock.g_bram_ptr[idx]=value; + else + printf("invalid bram index : %s (%d)\n",_data,idx); + + } + + addUniqueParam(p); + } + else + { +#ifdef _DEBUG + outputInfo("unknown parameters (%s)(%s)\n",_data,_value); +#endif + } + + return true; + +} + +bool CEmulator::parseParam(const char* _param,eParamType _type) +{ + + // Format + // data=value;data2=value; + + const char* run = _param; + if (!run) return false; + + MyString data; + MyString value; + + while(1) + { + // data + data.Empty(); + + // skip ; + while (*run == ';') run++; + if (!*run) return false; // done + + while(*run!='=' && *run!=':') + { + if (!*run) return false; + data += *run; + run++; + } + run++; // passe le = + value.Empty(); + + while(*run && *run!=';') + value += *run++; + + if (!strcasecmp(data.c_str(),"setstart")) + extractSetStartParam(value.c_str()); + else + { + if (data[0]!='_') + setParam(_type,data.c_str(),value.c_str()); + } + if (!*run) break; + run++; + } + + return true; +} + + +bool COption::addEmulatorParam(const char* _param) +{ + + const char* run = _param; + if (!_param) return true; +// printf("loading system param\n"); + + MyString data; + MyString value; + + while(1) + { + // data + data.Empty(); + + // ignore the initial _ (for backward compatibility) + if (*run=='_') run++; + while(*run!='=' && *run!=':') + { + if (!*run) return false; + data += *run; + run++; + } + run++; // passe le = + value.Empty(); + + while(*run && *run!=';') + value += *run++; + + // regarde si c'est une option + option_id id = findByName(data.c_str()); + if (id!=OPTION_ERROR) + setValue(id,value.c_str(),1); + /* + if (data[0]=='_') + { + MyString data2; + data2 = data.substr(1); + option_id id = findByName(data2.c_str()); + if (id==OPTION_ERROR) + printf("could not process : %s %s\n",data2.c_str(),value.c_str()); + else + setValue(id,value.c_str(),1); + } + */ + + if (!*run) break; + run++; + } + + return true; +} + + + +bool CEmulator::extractSetStartParam(const char* run) +{ + // Format slot|file + + setStart.slot = 0; + int slot; + + MyString data; + while(*run!=':' && *run) + data += *run++; + + slot = atoi(data.c_str()); + if ( (slot!=51) && (slot!=52) && (slot!=71) && (slot!=72) ) return false; + + data.Empty(); + while(*run) + data += *run++; + + setStart.slot = slot; + setStart.file = data; + + return true; +} + +// CChildView + + +void CEmulator::updateBramParameters() +{ + if (!this) return ; + + parseParam(bramParam.c_str(),BRAM); + x_refresh_panel(PANEL_PARAMS); +} + +void CEmulator::setBramParam(const char* _p) +{ + + + if (bramParam.IsEmpty()) + bramParam = _p; + else + { + bramParam += ';'; + bramParam += _p; + } +} + + + +void CEmulator::ejectDisk(int _slot,int _drive) +{ + if (!this) return ; + CSlotInfo& ref = getLocalIMGInfo(_slot,_drive); + if (ref.status == UNDEFINED) return ; + ref.status = EJECTED ; + outputInfo("status set to EJECTED for S%dD%d\n",_slot,_drive); + config->need2remount=true; + x_refresh_panel(PANEL_DISK); + + if(g_sim65816.g_enable_disk_sound) + play_sound(SOUND_EJECTION); +} + + +void CEmulator::reloadDisk(int _slot,int _drive) +{ + if (!this) return ; + CSlotInfo& ref = getLocalIMGInfo(_slot,_drive); + if ( + (ref.status == EJECTED )|| + (ref.status == FAILED ) ) + { + ref.status = READY2MOUNT; + outputInfo("status set to READY2MOUNT for S%dD%d\n",_slot,_drive); + config->need2remount=true; + x_refresh_panel(PANEL_DISK); + } +} + + + +CEmulator::CEmulator(CEmulator** _parent) +{ + if (theEmulator) + x_fatal_exit("MULTIPLE INSTANCES"); + bInThread = false; + theEmulator= this; + parent = _parent ; +#ifdef ACTIVEGSPLUGIN + pInstance = NULL; +#endif + theWindow = NULL; + g_sim65816.halt_sim = 0; + x=0; + y=0; + memset(lights,0,sizeof(lights)); + memset(tracks,0,sizeof(tracks)); + config = NULL; +} + +#ifdef ACTIVEGSPLUGIN +void CEmulator::setPluginInstance(void* _instance) +{ + pInstance = _instance; +} +#endif + +void CEmulator::mountDisks() +{ + config->need2remount=true; + forceFocus(); +} + + +int CEmulator::theThread() +{ + +#ifdef TEST_RASTER + + x_test_raster(); + +#else + + if (!config) + { + x_fatal_exit("!!!MISSING CONFIG!!!\n"); + return 0; + } + + if (bInThread) + { + x_fatal_exit("THREAD ALREADY RUNNING\n"); + return 0; + } + + + bInThread=true; + outputInfo("emulator thread launched!\n"); + + while(1) + { + config->need2remount=true; + mountDelayedDisk(); + + nbparams=0; + bramParam.Empty(); + + + // 1- OPTION PAR DEFAULT DE L'EMULATEUR + + // initialise les options par défault + setStart.slot=0; + g_sim65816.g_6502_emulation = 0; + g_sim65816.g_use_apple2e_rom = 0; + + + // paramètre auto! + if (config->bootslot==-1) + { + // default + config->bootslot=5; + for(int b = 5;b<=7;b++) + { + const char* s = config->getSlot(b,1); + if (s && s[0]) + { + printf("bootslot set to %d\n",b); + config->bootslot=b; + break; + } + } + } + + switch(config->bootslot) + { + case 6: + setEmulatorParam("driveemulation:slow;emulate6502:1;"); + setBramParam("slot6:card;boot:6;border:black;background:black;font:white"); + + break; + case 5: + setBramParam("boot=5"); + break; + default: + setEmulatorParam("driveemulation:fast;"); + setBramParam("slot6:disk"); + break; + } + + // 1 la vitesse + + g_moremem.g_zipgs_reg_c05a = 0x0F; // MAX SPEED + + int sp = config->speed; + if (sp == SPEED_AUTO) + { + if (config->bootslot==6) + sp = SPEED_1MHZ; + else + sp = SPEED_GS; + printf("speed auto set to %d\n",sp); + } + + onSpeedChanged(sp,true); + + // 2 - LES OPTIONS DU FICHIERS DE CONF + + option.loadOptions(); + + // 3 - LES OPTIONS DU FICHIER XML CONFIG + + printf("*loading option from xml\n"); + printf("EmulatorParam: %s\n",config->xmlEmulatorParam.c_str()); + printf("BramParam: %s\n",config->xmlBramParam.c_str()); + printf("SystemParam: %s\n",config->xmlSystemParam.c_str()); + + option.addEmulatorParam(config->xmlSystemParam.c_str()); + setBramParam(config->xmlSystemParam.c_str()); + setBramParam(config->xmlBramParam.c_str()); + option.addEmulatorParam(config->xmlEmulatorParam.c_str()); + setEmulatorParam(config->xmlEmulatorParam.c_str()); + + // 4 - LES OPTIONS JAVASCRIPT + printf("*loading option from javascript\n"); + option.addEmulatorParam(STRING2CONSTCHAR(config->systemParam)); + setBramParam(STRING2CONSTCHAR(config->systemParam)); + setBramParam(STRING2CONSTCHAR(config->bramParam)); + setEmulatorParam(STRING2CONSTCHAR(config->emulatorParam)); + option.addEmulatorParam(STRING2CONSTCHAR(config->emulatorParam)); + + option.enableOptions(); + + mountDisks(); + + g_adb.g_adb_repeat_delay = option.getIntValue(OPTION_ADBDELAY); + g_adb.g_adb_repeat_rate = option.getIntValue(OPTION_ADBRATE); + + int ar = option.getIntValue(OPTION_AUDIORATE); + if (ar) + { + if (ar<11025 || ar>44100) + ar = 22100; + g_sound.g_audio_enable = 1; + g_sound.g_audio_rate = ar; + } + else + g_sound.g_audio_enable = 0; + + int mem = option.getIntValue(OPTION_MEMORYSIZE); + + if (mem <=8 && mem>=0) + mem *= 1024*1024; + else + if (mem>=128 && mem<=8*1024) + { + mem *= 1024; + } + else + if (mem>=128*1024 && mem<=8*1024*1024) + { + } + else + mem = 2*1024*1024; + + g_sim65816.g_mem_size_exp = mem; + + if (config->bootslot!=6 && g_sim65816.g_use_apple2e_rom) + { + printf("disabling apple 2e rom (only works when booting from slot6\n"); + g_sim65816.g_use_apple2e_rom = 0; + } + + + + g_savestate.init(); + if (config->stateFilename.IsEmpty()) + { + } + else + { + + printf("about to restore : %s\n",config->stateFilename.c_str()); + g_savestate.restoreState(config->stateFilename.c_str()); + } + + printf("*** notifying boot option ***\n"); + x_refresh_panel(PANEL_BOOT); + printf("*** launching Emulator Mainloop\n"); + +#ifndef MAC + kegsmain(0,NULL); +#else + extern int macmain(int,char**); + macmain(0,NULL); +#endif + g_savestate.shut(); + + joystick_shut(); + + + if (!r_sim65816.restart_requested) + break; + else + { + outputInfo("*** Restarting emulator\n"); + r_sim65816.restart_requested = 0; + + outputInfo("*** bRestarting\n"); + setConfig(config); + } + } + +#endif // TEST_RASTER + + outputInfo("end of emulator thread\n"); + + bInThread=false; + return 0; + + +} + +void CEmulator::forceFocus() +{ + // TODO OG +} + + +void CEmulator::readImageInfo(int _slot,int _drive, int _imagelen, int _imagestart, int _isprodos) +{ + if (!this) return ; + CSlotInfo& ref = getLocalIMGInfo(_slot,_drive); + ref.size = _imagelen; + MyString prefix("?"); + if (_isprodos) //_info.track0_len!=-1) + { + char ptr[32]; + memset(ptr,0,sizeof(ptr)); + const char* filename = ref.filename.c_str(); + if (filename) + { + FILE* f = fopen(filename,"rb"); + if (f) + { + fseek(f,_imagestart+0x404,SEEK_SET); + if (16==fread(ptr,1,16,f)) + if ( ((ptr[0]&0xF0)==0xF0) ) + { + int len= ptr[0]&0x0F; + ptr[len+1] = 0; + prefix = "/"; + prefix += (ptr+1); + } + + fclose(f); + } + } + } + else + prefix = "NON-PRODOS"; + ref.prefix = prefix; +} + +int CEmulator::getLocalMultipleIMGInfo(int _slot,int _drive,CSlotInfo& info, int _pos) +{ + CActiveImage& active = config->getActiveImage(_slot,_drive); + if (_pos>=active.iNb) return 0; + info = config->getLocalImage(_slot,_drive,_pos); + if (active.iActive==_pos) return 1; + else + return -1; +} + +int CEmulator::mountDelayedDisk() +{ + for(int slot=5;slot<=7;slot++) + for(int disk=1;disk<=2;disk++) + { + CSlotInfo& ref = getLocalIMGInfo(slot,disk); + if (ref.status==DELAYEDMOUNT) + { + outputInfo("status set to READY2MOUNT for S%dD%d\n",slot,disk); + ref.status=READY2MOUNT; + } + + } + return 0; +} + +bool CEmulator::remainingDelayedDisk() +{ + for(int slot=5;slot<=7;slot++) + for(int disk=1;disk<=2;disk++) + { + CSlotInfo& ref = getLocalIMGInfo(slot,disk); + if (ref.status==DELAYEDMOUNT) + return true; + } + return false; +} + +int CEmulator::getSmartSwap() +{ + int found = 0; + for(int slot=5;slot<=6;slot++) + { + for(int disk=1;disk<=2;disk++) + { + CActiveImage& active = config->getActiveImage(slot,disk); + if (active.iNb > 1) + { + if (found) + { + // multiple multiple : does not know how to handle + return 0; + } + else + found = slot*10+disk; + } + } + } + return found; +} + +int CEmulator::smartSwap() +{ + int smart = getSmartSwap(); + if (!smart) + { + outputInfo("smart swap not available\n"); + return 0; + } + return swapDisk(smart/10,smart%10); +} + + + +int CEmulator::swapDisk(int _slot,int _drive, int pos ) +{ + CActiveImage& active = config->getActiveImage(_slot,_drive); + if (active.iNb <=1) + { + outputInfo("nothing to swap\n"); + return 0; + } + + CSlotInfo& ref = getLocalIMGInfo(_slot,_drive); + if (ref.status != UNDEFINED) + { + ref.status = EJECTED ; + outputInfo("status set to EJECTED for S%dD%d\n",_slot,_drive); + } + //ejectDisk(_slot,_drive); + + + // passe à la suivante + if (pos<0) + pos = active.iActive+1; + if (pos>=active.iNb) + pos=0; + + active.iActive = pos; + outputInfo("swapping to entry %d\n",pos); + + CSlotInfo& info = getLocalIMGInfo(_slot,_drive); + if (!info.url.IsEmpty()) + { + outputInfo("status set to DELAYEDMOUNT for S%dD%d\n",_slot,_drive); + info.status = DELAYEDMOUNT; + info.delay = (int)(60*1.5); // 5s + } + + config->need2remount=true; + x_refresh_panel(PANEL_DISK); + return 1; +} + +CSlotInfo& CEmulator::getLocalIMGInfo(int _slot,int _drive) +{ + CActiveImage& active = config->getActiveImage(_slot,_drive); + return config->getLocalImage(_slot,_drive,active.iActive); +} + + +int CEmulator::mountImages() +{ + if (!this) return 0; + +#if defined(ACTIVEGSPLUGIN) && !defined(DRIVER_IOS) + checkAlerts(); +#endif + + if (config->need2remount) + { + //outputInfo("mounting images...\n"); + + int ri = 0; + for(int slot=5;slot<=7;slot++) + { + int maxdrive=2; + if (slot==7) maxdrive=MAXSLOT7DRIVES; + for(int drive=1;drive<=maxdrive;drive++) + { + ri |= loadDiskImage(/*name,*/slot,drive); + if (r_sim65816.should_emulator_terminate()) + return 0 ; + // regarde si il faut patcher le disque systËme + if (setStart.slot == (slot*10)+drive) + setStartParam(); + } + } + + config->need2remount = (int)remainingDelayedDisk(); + if (ri) + x_refresh_panel(PANEL_DISK); + + return 1; + } + else + return 0; + +} + +int CEmulator::loadDiskImage(int _slot,int _drive) +{ + ASSERT(theEmulator==this); + + CSlotInfo& ref = getLocalIMGInfo(_slot,_drive); + if (ref.status != READY2MOUNT) + return 0; + + if (ref.url.IsEmpty()) + { + ref.status = NOTHING; + outputInfo("status set to NOTHING for S%dD%d\n",_slot,_drive); + ref.filename.Empty(); + ref.shortname.Empty(); + return 1; + } + + MyString path; + MyString shortname; + + CDownload dl(this->config->baseURL); +#ifdef DRIVER_ANDROID + dl.fromMainThread = false; +#endif + + + if (dl.retrieveFile(STRING2CONSTCHAR(ref.url),path,shortname)) + { + ref.filename = path ; + ref.shortname = shortname ; + ref.status = MOUNTED ; + outputInfo("status set to MOUNTED for S%dD%d\n",_slot,_drive); + //ref.delay = 1; + ::showStatus("Image %s mounted [S%dD%d]",ref.shortname.c_str(),_slot,_drive); + return 1 ; + } + else + { + ref.status = FAILED ; + outputInfo("status set to FAILED for S%dD%d\n",_slot,_drive); + ref.shortname = getfile(STRING2CONSTCHAR(ref.url)); + return 1; + } + +} + +void CEmulator::resetLocalIMG(void) +{ +} + +// Interface + +const char* getLocalIMG(int _slot,int _drive) +{ + CEmulator* emu = CEmulator::theEmulator; + CSlotInfo& ref = emu->getLocalIMGInfo(_slot,_drive); + + if (ref.status == DELAYEDMOUNT) + { + ref.delay--; + if (ref.delay<=0) + { + ref.status = READY2MOUNT; + outputInfo("status set to READY2MOUNT for S%dD%d : image %s\n",_slot,_drive,ref.shortname.c_str()); + } + emu->config->need2remount=true; + return NULL; + } + + if (ref.status == MOUNTED) + return ref.filename.c_str() ; + else + return NULL; +} + + +int mountImages() +{ + return CEmulator::theEmulator->mountImages(); +} + +void updateBramParameters(unsigned char* bramPtr) +{ + return CEmulator::theEmulator->updateBramParameters(); +} + +void readImageInfo(int _slot,int _drive, int _imagelen, int _imagestart, int _isprodos) +{ + return CEmulator::theEmulator->readImageInfo(_slot,_drive,_imagelen,_imagestart,_isprodos); +} + +/* +void refreshInfo() +{ + CEmulator* emu = CEmulator::theEmulator; + if (!emu) return ; + emu->infoRefresh(); +} +*/ + +void disableConsole() +{ + CEmulator* emu = CEmulator::theEmulator; + if (!emu) return ; + emu->disableConsole(); + +} + +int activeRead(char* buf) +{ + CEmulator* emu = CEmulator::theEmulator; + if (!emu) + { + buf[0]=0; + return 0; + } + else + return (emu->activeRead(buf)); + +} + + + +void COption::enableOptions() +{ + + + r_sim65816.g_ignore_bad_acc = !getIntValue(OPTION_HALTONBADACC); + r_sim65816.g_ignore_halts = !getIntValue(OPTION_HALTONHALTS); + r_sim65816.g_halt_on_bad_read = getIntValue(OPTION_HALTONBADREAD); + r_sim65816.set_rewind_enable(getIntValue(OPTION_ENABLEREWIND)); + + r_sim65816.set_color_mode( (colormodeenum)getIntValue(OPTION_COLORMODE)); + r_sim65816.set_video_fx((videofxenum)getIntValue(OPTION_VIDEOFX)); + + g_joystick_type = getIntValue(OPTION_JOYSTICKMODE); +#ifndef VIRTUALAPPLE + g_sim65816.set_fixed_vblank( getIntValue(OPTION_FIXEDVBLANK),(speedenum)getIntValue(OPTION_SPEED) ); +#endif + + g_sim65816.g_enable_disk_sound = getIntValue(OPTION_DISKSOUND); + + g_paddles.g_joystick_scale_factor_x = (getIntValue(OPTION_JOYXSCALE)*256)/1000; // 0x100 = 1 + g_paddles.g_joystick_scale_factor_y = (getIntValue(OPTION_JOYYSCALE)*256)/1000; // 0x100 = 1 + + + g_adb.g_simulate_space = getIntValue(OPTION_SIMULATESPACE); + + + if (r_sim65816.get_state()==RUNNING) + paddle_fixup_joystick_type(); +#ifdef DRIVER_IOS + extern int x_frame_rate; + extern int x_lock_zoom; + x_frame_rate = getIntValue(OPTION_FRAMERATE); +#warning "TODO CHANGE FPS IN REALTIME" + x_lock_zoom = getIntValue(OPTION_LOCKZOOM); +#endif + + x_refresh_panel(PANEL_RUNTIME); + + +} + + +void CEmulator::setLight(int _motorOn,int _slot, int _drive, int _track) +{ + int id=0; + for(int slot=5;slot<=6;slot++) + for(int drive=1; drive<=2; drive++) + { + if ( (_slot==slot) && (_drive==drive) ) + { + lights[id]=_motorOn; + tracks[id]=_track; + } + else + lights[id]=0; + id++; + } + +} + +//extern char targetSpeed[256]; +extern char estimatedSpeed[256]; + + +void CEmulator::processCommand( const char* _val, MyString& ret) +{ +// outputInfo("processingCommand:%s\n",_val); + if (!strcmp(_val,"help")) + ret = "({ commands : [ \"help\" , \"version\", \"system\", \"status\", \"runtime\", \"reboot\",\"savestate\", \"restorestate\", \"pause\", \"resume\" ,\"pauseresume\", \"swap\", \"screenshot\",\"saveoptions\",\"defaultoptions\",\"sendkey:ctrl;alt;esc\" ] })"; + else + if (!strcasecmp(_val,"saveoptions")) + { + option.saveOptions(1); + ret = "({ \"info\" : \"options saved\"})"; + } + else + if (!strcasecmp(_val,"defaultOptions")) + { + option.setDefaultOptions(); + option.enableOptions(); + ret = "({ \"info\" : \"default options restored\"})"; + } + else + if (!strncasecmp(_val,"sendkey:",8 /* sizeof ("sendkey:")*/)) + { +#if defined (DRIVER_OSX) && !defined(ACTIVEGSPLUGIN) + ret = "({ \"info\" : \"not implemented\"})"; +#else + const char* keystr[] = { "^ctrl" , "^alt", "^esc", "^reset", "^option", NULL }; + const int keycode[] = { 0x36 , 0x37 , 0x35, 0x7F, 0x3A, 0 }; +#define MAX_CODE 100 + int code[MAX_CODE]; + int nbcode=0; + const char* ptr = _val+8; + MyString keysent; + while(*ptr) + { + const char* p = ptr; + while(*p && *p!=';') p++; + int l = p-ptr; + int k = 0; + while(keystr[k]) + { + if (!strncasecmp(keystr[k],ptr,l)) + { + code[nbcode++]=k; + // printf("found %s (%X)\n",keystr[k],keycode[k]); + keysent+=keystr[k]; + keysent+=";"; + break; + } + k++; + } + if (!keystr[k]) + printf("key not valid %s\n",ptr); + ptr = p; + if (*ptr==';') ptr++; + if (nbcode==MAX_CODE) break; + } + + for(int i=0;i=0;i--) + { + add_event_key(keycode[code[i]],1); + } + + ret.Format("({ \"info\" : \"key sent %s\"})",keysent.c_str()); +#endif + } + else + if (!strcasecmp(_val,"version")) + { + ret = "({ \"info\" : \"" ACTIVEGSVERSIONSTRFULL "\"})"; + } + else + /* + if (!strcmp(_val,"rewind")) + { + stateActionRequired = STATE_REWIND; + ret = "({ \"info\" : \"rewind activated\"})"; + } + else + */ + if (!strcasecmp(_val,"system")) + { + ret = "( { "; + + ret += " \"currentBuild\" : \"" TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) "\","; + MyString str; + int g_joystick_plugged = (g_joystick_native_type1 != -1) || (g_joystick_native_type2 != -1) ? 1 : 0 ; + str.Format("\"joystickPlugged\" : %d,",g_joystick_plugged); + ret += str.c_str(); + MyString engine; + getEngineString(engine); + + str.Format("\"renderingEngine\" : \"%s\",",engine.c_str()); + ret += str.c_str(); + + str.Format("\"memorySize\" : %d,",option.getIntValue(OPTION_MEMORYSIZE)); + ret += str.c_str(); + + str.Format("\"audioRate\" : %d",option.getIntValue(OPTION_AUDIORATE)); + ret += str.c_str(); + + + ret +="})"; + } + else + if (!strcasecmp(_val,"reboot")) + { + // Force la relecture du fichier XML! + config->xmlAlreadyLoaded = 0; + onBootSlotChanged(-1); // Bootslot Auto + ret = "({ \"info\" : \"Rebooted!\" })"; + } + else + if (!strcasecmp(_val,"status")) + { + MyString str; + ret = "( {"; + str.Format("\"vbl\" : %d,",g_sim65816.g_vbl_count); + ret += str; + str.Format("\"speed\" : { estimated:\"%s\", target:\"",estimatedSpeed); + if (!g_sim65816.g_speed_fast) + str +="1"; + else + str += option.getDescription(OPTION_SPEED,g_sim65816.get_limit_speed()); + str +="\"},"; + ret += str; + ret += " \"lights\" : {"; + for(int i=0;i<4;i++) + { + str.Format(" \"slot%d%d\" : { \"on\" : %d, \"track\" : %d }",(i/2)+5,(i&1)+1,lights[i],tracks[i]); + ret += str; + if (i!=3) + ret+=","; + + } + ret += "}"; + ret += "} )"; + } + else + if (!strcasecmp(_val,"runtime")) + { + MyString str; + ret = "( {"; + str.Format("\"pause\" : %d,",r_sim65816.get_state()==IN_PAUSE); + ret += str; + str.Format("\"swap\" : %d,",getSmartSwap()); + ret += str; + str.Format("\"rewindAvailable\" : %d,",r_sim65816.get_rewind_enable()); + ret += str.c_str(); + + str.Format("\"savedState\" : %d,", g_savestate.getSavedStateVBL()); + ret += str.c_str(); + + ret += "\"slots\" : ["; + int nb = 0; + for(int slot=5;slot<=7;slot++) + { + int maxdrive=2; + if (slot==7) maxdrive=MAXSLOT7DRIVES; + for(int disk=1;disk<=maxdrive;disk++) + { + for(int active=0;activegetLocalIMGInfo(sw/10,sw%10); + ret = info.shortname; + ret.Format("({ \"info\" : \"disk %s inserted\", \"slot\" : %d, name : \"%s\" })",info.shortname.c_str(),sw,info.shortname.c_str()); + } + } + else + { + ret="({ \"error\" : \"unsupported command:"; + ret += _val ; + ret += "\"})"; + } +} + + +// initialize le son depuis le thread principal +void CEmulator::launchEmulator() +{ + x_async_sound_init(); + //CDownload::initPersistentPath(); + x_LaunchThread(); + // attend la fin de l'émulateur +// x_WaitForEndThread(); + +} + + + +void CEmulator::terminateEmulator() +{ + outputInfo("terminateCEmulator (%X)\n",this); + + if (bInThread) + { + + // envoie le signal de quit + r_sim65816.quit_emulator(); + + // attend la fin de l'émulateur + x_WaitForEndThread(); + + x_async_snd_shutdown(); + + } + + // l'émulateur a quitté correctement : il est pret à redémarrer + r_sim65816.reset_quit(); + // OG 080111 Force un redraw pour rafraichir le contenu du browser si besoin + refresh_video(1); + + +} + +CEmulator::~CEmulator() +{ + outputInfo("~CEmulator (%X)",this); + + // termine le singleton + theEmulator=NULL; + + if (parent) + *parent = NULL; + + +} + +void CEmulator::onXMLConfigChanged(const char *_xmlconfig,simplexml* _pXML) +{ + if (!acceptEvents()) + { + outputInfo("### onXMLConfigChanged Ignored"); + return; + } + + MyString newxmlconfig = _xmlconfig; // le copie si la valeur était déjà stockée dans xmlconfig +// config->resetConfig(); // remets les valeur par défault + config->xmlconfig = newxmlconfig.c_str(); + config->pXML = _pXML; + config->xmlAlreadyLoaded=0; // pour forcer la relecture au prochain chargement + relaunchEmulator(); + +} + +extern void addNotificationWindow(); + +void addConsoleWindow(Kimage* _dst) +{ +#if defined(_DEBUG) && defined(WIN32) && 0 + extern void addConsole(const char*); + +// extern char estimatedSpeed[256]; + extern void addConsole(const char* _str); +// extern int getFrameRate(int _id); + extern void drawConsole(Kimage* _dst); + char str[256]; + int fr0 = getFrameRate(0); + int fr1 = getFrameRate(1); + int fr2 = getFrameRate(2); + int fr3 = getFrameRate(3); + sprintf(str,"fps:%02d.%0d 60hz:%02d.%0d req:%02d.%0d c054:%02d.%0d ",fr0/10,fr0%10,fr3/10,fr3%10,fr1/10,fr1%10,fr2/10,fr2%10); +// sprintf(str,"p1:%d p2:%d fps:%d ",getFrameRate(3),getFrameRate(4),getFrameRate(1)); + addConsole(str); + drawConsole(_dst); +#endif +// addNotificationWindow(); +} + + + + +#ifdef TEST_RASTER +int x_test_raster() +{ + x_video_init(); + r_sim65816.set_state(RUNNING); + + while(!r_sim65816.should_emulator_terminate()) + { + + static int pos=0; + + // faire scroller + + // int bitmapBytesPerRow = (pixelsWide * 4);// 1 + int bitmapBytesPerRow = g_kimage_offscreen.width_act * (g_kimage_offscreen.mdepth >> 3); + + int destx=0; + int desty = 0; + int col = pos; + + x_wait_for_last_refresh(1.0/60.0); + + CHANGE_BORDER(0,0x00FF00); + + byte* ptrdest = (byte*)g_kimage_offscreen.data_ptr ; + for(int i=0;i> 3); + + int destx= g_kimage_offscreen.width_act - NOTIFICATION_WIDTH - NOTIFICATION_MARGIN ; + int col = 0xFFFFFF; + + for(int i=0;i=g_kimage_offscreen.height) continue; + + byte* ptrdest = (byte*)g_kimage_offscreen.data_ptr + y*bitmapBytesPerRow; + + for(int j=0;jg_kimage_offscreen.width_act ) ) continue; + ((word32*)ptrdest)[x] = col; + } + } + if (g_notification_motion) + { + g_notification_y += g_notification_speed; + g_notification_speed += 0.5f; + if (g_notification_y>= g_kimage_offscreen.height-(NOTIFICATION_HEIGHT+NOTIFICATION_MARGIN)) + { + g_notification_y = (float)(g_kimage_offscreen.height-(NOTIFICATION_HEIGHT+NOTIFICATION_MARGIN)); + if (g_notification_speed<2.0f) + { + g_notification_motion = 0; + g_notification_show = 3*60; + } + else + g_notification_speed *= -0.5f; + + } + } + else + { + g_notification_show--; + } + +// g_notification_y++; + if (g_notification_y>g_kimage_offscreen.height+NOTIFICATION_HEIGHT) + g_notification_y = -NOTIFICATION_HEIGHT; + + g_video.g_needfullrefreshfornextframe = 1; + +} + + + + diff --git a/Common/activeconfig.cpp b/Common/activeconfig.cpp new file mode 100644 index 0000000..a62f803 --- /dev/null +++ b/Common/activeconfig.cpp @@ -0,0 +1,84 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "Cemulatorctrl.h" +#include "../kegs/Src/iwm.h" +#include "../kegs/Src/config.h" +#include "../kegs/Src/savestate.h" + +void x_notify_disk_insertion(int _size,int _start, int _isprodos,int slot, int drive) +{ + + readImageInfo(slot,drive+1,_size,_start,_isprodos); +} + + +void checkImages() +{ + + if (mountImages()) + { + printf("Mounting images...\n"); + + g_iwm.g_highest_smartport_unit = -1; + + insert_disk(5,0,getLocalIMG(5,1),0,0,0,0); + insert_disk(5,1,getLocalIMG(5,2),0,0,0,0); + insert_disk(6,0,getLocalIMG(6,1),0,0,0,0); + insert_disk(6,1,getLocalIMG(6,2),0,0,0,0); + + for(int disk=1;diskshowStatus(st.c_str()); +} + +/* +void showError(const char* format,...) +{ + + va_list argptr; + va_start( argptr, format ); + MyString st; + st.FormatV(format,argptr); + va_end(argptr); + + outputInfoInternal(st.c_str()); +} +*/ + + +void showProgress(const char* file,int percent) +{ + MyString progress; + if (percent>=0) + progress.Format("Downloading: %s (%3d%%)",getfile(file),percent); + else + progress.Format("Downloading: %s (%4dK)",getfile(file),(int)(-percent/1024)); + +// outputInfoInternal(progress.c_str()); + + CEmulator* emu = CEmulator::theEmulator; + if (emu) + emu->showStatus(progress.c_str()); + + +#ifdef DRIVER_IOS + extern void x_downloadinginprogress(int); + x_downloadinginprogress(percent); +#endif +} + +void x_notify_motor_status(int _motorOn,int _slot,int _drive, int _curtrack) +{ + + CEmulator* emu = CEmulator::theEmulator; + if (emu) + { + emu->setLight(_motorOn,_slot,_drive,_curtrack); + if (!option.getIntValue(OPTION_DONOTSHOWDISKSTATUS)) + { + emu->loadingInProgress(_motorOn,_slot,_drive); + } + } +} + +void x_clk_setup_bram_version() +{ + extern void initializeBram(unsigned char*); +// extern byte g_bram[2][256]; + g_clock.g_bram_ptr = (&g_clock.g_bram[0][0]); // ROM 01 only + initializeBram(g_clock.g_bram_ptr); +} + + + + + +void x_config_load_additional_roms() +{ +} + +void x_notify_disk_ejection(int _slot,int _drive) +{ + CEmulator::theEmulator->ejectDisk(_slot,_drive); +} + + +void apply_patch(int _slot,int _disk,byte * _buf, int _pos, int _len) +{ + CEmulator* emu = CEmulator::theEmulator; + CSlotInfo& ref = emu->getLocalIMGInfo(_slot,_disk); + int t = ref.patch_addr - _pos; + if (ref.patch_addr !=0 && t>=0 && t<_len) + { + const char*s = ref.patch_value; + while(*s && t<_len) + { + byte a = *(s++)-'0'; + if (a>9) a-='A'-'0'-10; + byte b = *(s++)-'0'; + if (b>9) b-='A'-'0'-10; + _buf[t++]=a*16+b; + } + } +} + + +void apply_breakpoints() +{ + CEmulator* emu = CEmulator::theEmulator; + if (!emu) return ; + CEmulatorConfig* config = emu->config; + for(int i=0;inb_bps;i++) + set_bp(config->BPs[i].addr,config->BPs[i].mode,config->BPs[i].value,config->BPs[i].check); +} diff --git a/Common/ki.h b/Common/ki.h new file mode 100644 index 0000000..355c740 --- /dev/null +++ b/Common/ki.h @@ -0,0 +1,84 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifndef KEGS_KI_H +#define KEGS_KI_H + +#include +# if defined( _WIN32) && !defined(UNDER_CE) + #include +#endif + +#include "../kegs/src/defc.h" +#include "../kegs/src/iwm.h" +extern void showStatus(const char* format,...); +extern void showError(const char* format,...); +extern void showProgress(const char* file,int percent); + + +// Emulator Interface + +// Struct + +#define MAXSLOT7DRIVES MAX_C7_DISKS + +//#define HALT_WANTTOQUIT 0x20 +#define HALT_WANTTOBRK 0x40 + + + + + +// Globals + +//extern void (*ki_loadingptr)(int motorOn,int slot,int drive); +//extern int g_limit_speed; +extern int g_fast_disk_emul; +//extern unsigned char *g_bram_ptr; +//extern int g_joystick_type; +extern int toggleJoystick(int); +//OGMAC +#ifdef _WIN32 +#include +void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags); +extern void kegsinit(HWND); +extern LRESULT CALLBACK win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); +//extern void add_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags); +#endif + +/* +extern int g_pause; +extern int g_halt_on_bad_read; +extern int g_ignore_bad_acc ; +extern int g_ignore_halts ; +*/ + +// Function +extern const char* getLocalIMG(int _slot,int _drive); + +extern int kegsmain(int argc, char** argv); +extern void win_event_redraw(); + +#define get_halt_act() g_sim65816.halt_sim +extern void set_halt_act(int); +extern void clr_halt_act(void); + + +// Interface Kegs -> Control + +extern void updateBramParameters(unsigned char* bram); +extern void readImageInfo(int _slot,int _drive, int _imagelen, int _imagestart, int _isprodos); +extern int mountImages(void); +extern void disableConsole(void); +extern void fatalExit(int ret); +extern void setInitialized(int _value); +extern void setAcceptEvents(int _value); + + + +#endif // KEGS_KI_H + +// diff --git a/Common/libpng.cpp b/Common/libpng.cpp new file mode 100644 index 0000000..7ba7f36 --- /dev/null +++ b/Common/libpng.cpp @@ -0,0 +1,191 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Libraries/libpng/png.h" +#include "cemulatorctrl.h" +#include "../kegs/src/video.h" +#define abort_(X) { printf(X); return 0;} + +extern word32 g_a2palette_8to1624[256]; + + +#ifdef DRIVER_OSX +extern int macUsingCoreGraphics; +#endif + +int savePNG(MyString& _path) +{ + + int _borderWidth = option.getIntValue(OPTION_PNGBORDER); + + _path = "({ \"error\" : \"Cannot create screenshot\" })"; + + CEmulator* pEmu = CEmulator::theEmulator ; + int bootslot = pEmu->config->bootslot; + + MyString filename; + CSlotInfo& slot = pEmu->getLocalIMGInfo(bootslot,1); + + printf(slot.shortname.c_str()); + MyString filenoext; + if (!slot.shortname.IsEmpty()) + filenoext = getfilenoext(slot.shortname.c_str()); + else + filenoext = "nodisk"; + + int i=0; +// CDownload dl; + while(i<100) + { + filename.Format("%s%sscreenshot_%s_%d.png", + CDownload::getPersistentPath(), + ACTIVEGS_DIRECTORY_SEPARATOR, + filenoext.c_str(), + i); + + FILE* f=fopen(filename.c_str(),"rb"); + if (!f) break; + fclose(f); + i++; + } + Kimage* kimage_ptr = g_video.g_a2_line_kimage[0]; + int a2width ; + int a2height; + + if (kimage_ptr == &s_video.g_kimage_superhires) + { + a2width = 320*VIDEO_HFACTOR; + a2height=200*VIDEO_VFACTOR;; + } + else + { + kimage_ptr = &s_video.g_mainwin_kimage; + a2width = 280*VIDEO_HFACTOR; + a2height = 192*VIDEO_VFACTOR; + } + + int width = a2width + _borderWidth*2; + int height = a2height + _borderWidth*2; + + + png_byte color_type =PNG_COLOR_TYPE_RGB; + png_byte bit_depth = 8; + + png_structp png_ptr; + png_infop info_ptr; + png_bytep row_pointers[1024]; + byte *pngraw = (byte*)malloc(width*height*3); + int stride =kimage_ptr->width_act * kimage_ptr->mdepth / 8; + + int bcolor = g_a2palette_8to1624[g_video.g_border_color]; + char border[3]; +#ifdef DRIVER_OSX + if (macUsingCoreGraphics) + { + border[0]=(char)bcolor; + border[1]=(char)(bcolor >> 8); + border[2]=(char)(bcolor >> 16); + } + else +#endif + { + border[2]=(char)bcolor; + border[1]=(char)(bcolor >> 8); + border[0]=(char)(bcolor >> 16); + +} + + for(int i=0;i=(a2height+_borderWidth) + || j<_borderWidth || j>=(a2width+_borderWidth) ) + { + dst[0]=border[0]; + dst[1]=border[1]; + dst[2]=border[2]; + } + else + { + byte* src= &kimage_ptr->data_ptr[(i-_borderWidth)*stride+(j-_borderWidth)* kimage_ptr->mdepth / 8]; + #ifdef DRIVER_OSX + if (macUsingCoreGraphics) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + } + else + #endif + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + } + } + } + } + + /* create file */ + FILE *fp = fopen(filename.c_str(), "wb"); + if (!fp) + abort_("[write_png_file] File could not be opened for writing"); + + + /* initialize stuff */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + abort_("[write_png_file] png_create_write_struct failed"); + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + abort_("[write_png_file] png_create_info_struct failed"); + + if (setjmp(png_jmpbuf(png_ptr))) + abort_("[write_png_file] Error during init_io"); + + png_init_io(png_ptr, fp); + + /* write header */ + if (setjmp(png_jmpbuf(png_ptr))) + abort_("[write_png_file] Error during writing header"); + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + /* write bytes */ + if (setjmp(png_jmpbuf(png_ptr))) + abort_("[write_png_file] Error during writing bytes"); + + png_write_image(png_ptr, row_pointers); + + /* end write */ + if (setjmp(png_jmpbuf(png_ptr))) + abort_("[write_png_file] Error during end of write"); + + png_write_end(png_ptr, NULL); + + png_destroy_info_struct(png_ptr,&info_ptr); + + png_destroy_write_struct(&png_ptr,&info_ptr); + png_free(png_ptr,NULL); + free(pngraw); + fclose(fp); + + outputInfo("screenshot %s saved\n",filename.c_str()); + _path.Format("({ \"info\" : \"Screenshot saved : %s\", \"filename\" : \"%s\" })",getfile(filename.c_str()),filename.c_str()); + + return 1; +} diff --git a/Common/rom.cpp b/Common/rom.cpp new file mode 100644 index 0000000..1e503a7 --- /dev/null +++ b/Common/rom.cpp @@ -0,0 +1,8280 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Common/CEMulatorCtrl.h" +#include "../Kegs/Src/sim65816.h" + +void default_config_load_roms() +{ + +extern byte *g_rom_fc_ff_ptr; +extern unsigned char gsrom01[]; +extern unsigned char apple2e_rom[]; +extern unsigned char apple2e_disk[]; + + g_sim65816.g_mem_size_base = 256*1024; + memset(&g_rom_fc_ff_ptr[0], 0, 2*65536); + + if ( g_sim65816.g_use_apple2e_rom == 0) + { + memcpy(&g_rom_fc_ff_ptr[2*65536], gsrom01,128*1024); + +#ifdef VIRTUALAPPLE + +#define TOGS(MEM,STR) \ +{ \ +char* d = (char*)MEM; \ +const char* s = STR; \ +char c; \ +while((c=*s++)!=0) *d++=(c|0x80); \ +*d=0; \ +} + + + // g_rom_fc_ff_ptr[0x03bb97]=0x60; // Ret == fully disable display + g_rom_fc_ff_ptr[0x03bb11]=0x0D; // Number of space + TOGS(&g_rom_fc_ff_ptr[0x03bb13],"Please Wait..."); + g_rom_fc_ff_ptr[0x03bb8e]=0x0B; // Center Line + g_rom_fc_ff_ptr[0x03bbb8]=0x60; // Abort display +#endif + + + g_sim65816.g_rom_version = 1; + } + else + { + // main + memcpy(&g_rom_fc_ff_ptr[4*65536-16*1024], &apple2e_rom[16*1024],16*1024); + + + // enleve le (c) + + /* +ff/fb60: 20 58 fc JSR $fc58 +ff/fb63: a0 09 LDY #$09 +ff/fb65: b9 09 ff LDA $ff09,Y +ff/fb68: 99 0e 04 STA $040e,Y +ff/fb6b: 88 DEY +ff/fb6c: d0 f7 BNE $fb65 +ff/fb6e: 60 RTS +*/ + +#ifdef VIRTUALAPPLE + g_rom_fc_ff_ptr[0x03FB63]=0x60; +#endif + // aux + memcpy(&g_rom_fc_ff_ptr[3*65536-16*1024], &apple2e_rom[0],16*1024); + + // disk + memcpy(&g_rom_fc_ff_ptr[3*65536+0xC600], &apple2e_disk[0],1*256); + g_sim65816.g_rom_version = -2; + + if ( g_sim65816.g_6502_emulation == 0) + { + printf("*** USING APPLE IIE ROM - FORCING 6502 EMULATION\n"); + g_sim65816.g_6502_emulation =1; + } + else + printf("*** USING APPLE IIE ROM\n"); + } + +} + +unsigned char gsrom01[]={ +0xC2, 0x30, 0xA2, 0x0E, 0x00, 0xBF, 0x51, 0x00, 0xFE, 0x9F, 0x00, 0x00, 0xE1, 0xCA, 0xCA, 0x10, +0xF4, 0xA9, 0x2F, 0x01, 0x8F, 0xC0, 0x03, 0xE1, 0xA9, 0xFE, 0x00, 0x8F, 0xC2, 0x03, 0xE1, 0x8F, +0xCA, 0x03, 0xE1, 0xA9, 0xEF, 0x01, 0x8F, 0xC4, 0x03, 0xE1, 0xA9, 0xFE, 0x00, 0x8F, 0xC6, 0x03, +0xE1, 0xA2, 0x06, 0x00, 0xBF, 0x61, 0x00, 0xFE, 0x9F, 0x80, 0x01, 0xE1, 0xCA, 0xCA, 0x10, 0xF4, +0xA2, 0x01, 0x01, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x05, 0x22, 0x7C, 0x00, 0xE1, 0x18, 0xE2, 0x30, +0x6B, 0x5C, 0xAF, 0x00, 0xFE, 0x5C, 0xA3, 0x00, 0xFE, 0x5C, 0x75, 0x00, 0xFE, 0x5C, 0x69, 0x00, +0xFE, 0x22, 0x68, 0x00, 0xE1, 0x5C, 0x0B, 0xBF, 0xFF, 0xC2, 0x30, 0x3B, 0x38, 0xE9, 0x07, 0x00, +0x1B, 0x0B, 0x5B, 0x80, 0x14, 0xC2, 0x30, 0x3B, 0x38, 0xE9, 0x0A, 0x00, 0x1B, 0x0B, 0x5B, 0xA9, +0x2D, 0x01, 0x85, 0x08, 0xA9, 0x01, 0xFE, 0x85, 0x09, 0xAF, 0xC4, 0x03, 0xE1, 0x85, 0x05, 0xAF, +0xC5, 0x03, 0xE1, 0x85, 0x06, 0xAF, 0xCC, 0x03, 0xE1, 0x85, 0x01, 0xAF, 0xCE, 0x03, 0xE1, 0x85, +0x03, 0x80, 0x38, 0xC2, 0x30, 0x3B, 0x38, 0xE9, 0x07, 0x00, 0x1B, 0x0B, 0x5B, 0x80, 0x14, 0xC2, +0x30, 0x3B, 0x38, 0xE9, 0x0A, 0x00, 0x1B, 0x0B, 0x5B, 0xA9, 0x2D, 0x01, 0x85, 0x08, 0xA9, 0x01, +0xFE, 0x85, 0x09, 0xAF, 0xC0, 0x03, 0xE1, 0x85, 0x05, 0xAF, 0xC1, 0x03, 0xE1, 0x85, 0x06, 0xAF, +0xC8, 0x03, 0xE1, 0x85, 0x01, 0xAF, 0xCA, 0x03, 0xE1, 0x85, 0x03, 0x8A, 0x48, 0x29, 0xFF, 0x00, +0xF0, 0x3A, 0xC7, 0x05, 0xB0, 0x36, 0x0A, 0x0A, 0xA8, 0xB7, 0x01, 0xAA, 0xC8, 0xC8, 0xB7, 0x01, +0x85, 0x03, 0x86, 0x01, 0x88, 0xB7, 0x05, 0xAA, 0x88, 0xB7, 0x05, 0x85, 0x05, 0x86, 0x06, 0xA3, +0x02, 0x29, 0xFF, 0x00, 0xF0, 0x1B, 0xC7, 0x05, 0xB0, 0x17, 0x0A, 0x0A, 0xA8, 0xB7, 0x05, 0xAA, +0xC8, 0xB7, 0x05, 0x85, 0x06, 0x86, 0x05, 0xFA, 0x2B, 0x68, 0x7A, 0x6B, 0xA2, 0x01, 0x00, 0x80, +0x03, 0xA2, 0x02, 0x00, 0x68, 0x2B, 0x3B, 0x18, 0x69, 0x0A, 0x00, 0x1B, 0x8A, 0x38, 0x6B, 0x21, +0x00, 0x00, 0x00, 0xB3, 0x01, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x0A, 0x90, 0xFE, 0x00, 0xFD, +0x06, 0xFE, 0x00, 0x6D, 0xAE, 0xFE, 0x00, 0x03, 0xBB, 0xFE, 0x00, 0x45, 0xBF, 0xFF, 0x00, 0x00, +0x3E, 0xFF, 0x00, 0x00, 0x80, 0xFF, 0x00, 0xBB, 0xD2, 0xFE, 0x00, 0x27, 0xC7, 0xFE, 0x00, 0x47, +0xA7, 0xFE, 0x00, 0xC0, 0x00, 0xFF, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, +0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, +0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, +0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, +0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, 0x01, 0xFE, 0x00, 0xEB, +0x01, 0xFE, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xF2, 0x01, 0xFE, 0x00, 0xB5, 0x02, 0xFE, 0x00, 0xB5, +0x02, 0xFE, 0x00, 0x1C, 0x03, 0xFE, 0x00, 0xBB, 0x02, 0xFE, 0x00, 0x14, 0x03, 0xFE, 0x00, 0xE2, +0xFF, 0xFE, 0x00, 0xE2, 0xFF, 0xFE, 0x00, 0xAF, 0x03, 0xFE, 0x00, 0xE4, 0x03, 0xFE, 0x00, 0xE7, +0x05, 0xFE, 0x00, 0x4C, 0x06, 0xFE, 0x00, 0x81, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x3B, 0x38, 0xE9, 0x08, 0x00, 0x1B, 0x0B, 0x5B, 0xA2, 0x02, 0x01, 0x22, 0x00, +0x00, 0xE1, 0x90, 0x03, 0x4C, 0x73, 0x02, 0x22, 0x80, 0x16, 0xE1, 0xAF, 0xC0, 0x03, 0xE1, 0x85, +0x01, 0xAF, 0xC2, 0x03, 0xE1, 0x85, 0x03, 0xA7, 0x01, 0x0A, 0x0A, 0x20, 0xE5, 0x06, 0x90, 0x03, +0x82, 0x50, 0x00, 0x86, 0x05, 0x84, 0x07, 0xA7, 0x05, 0xAA, 0xA0, 0x02, 0x00, 0xB7, 0x05, 0x85, +0x07, 0x8F, 0xCA, 0x03, 0xE1, 0x86, 0x05, 0x8A, 0x8F, 0xC8, 0x03, 0xE1, 0xA7, 0x01, 0x0A, 0x0A, +0xA8, 0x88, 0x88, 0xA9, 0x00, 0x00, 0x97, 0x05, 0x88, 0x88, 0x10, 0xFA, 0x20, 0x86, 0x02, 0xB0, +0x22, 0xF4, 0x03, 0x01, 0xA3, 0x01, 0xAA, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x07, 0xA3, 0x01, 0x1A, +0x83, 0x01, 0x80, 0xF0, 0xC9, 0x02, 0x00, 0xF0, 0xF4, 0xA2, 0x00, 0x00, 0xC9, 0x01, 0x00, 0xF0, +0x01, 0xAA, 0x68, 0x2B, 0x3B, 0x18, 0x69, 0x08, 0x00, 0x1B, 0x8A, 0xC9, 0x01, 0x00, 0xB0, 0x05, +0x22, 0x84, 0x16, 0xE1, 0x18, 0x6B, 0xA9, 0x04, 0x00, 0x20, 0xE5, 0x06, 0xB0, 0x27, 0x5A, 0xDA, +0x0B, 0x3B, 0x5B, 0xA7, 0x03, 0xAA, 0xA0, 0x02, 0x00, 0xB7, 0x03, 0x85, 0x05, 0x8F, 0xCE, 0x03, +0xE1, 0x86, 0x03, 0x8A, 0x8F, 0xCC, 0x03, 0xE1, 0xA9, 0x00, 0x00, 0x87, 0x03, 0xA0, 0x02, 0x00, +0x97, 0x03, 0x2B, 0x68, 0x68, 0x60, 0x20, 0x22, 0x03, 0x4C, 0x8B, 0xFF, 0xA2, 0x02, 0x05, 0x22, +0x00, 0x00, 0xE1, 0x20, 0x22, 0x03, 0xF4, 0x00, 0x00, 0xF4, 0x03, 0x05, 0xA3, 0x01, 0xAA, 0x22, +0x00, 0x00, 0xE1, 0xB0, 0x07, 0xA3, 0x01, 0x1A, 0x83, 0x01, 0x80, 0xF0, 0xC9, 0x01, 0x00, 0xF0, +0x09, 0xC9, 0x02, 0x00, 0xF0, 0xEF, 0x83, 0x03, 0x80, 0xEB, 0x68, 0x68, 0xD0, 0x03, 0x4C, 0x8B, +0xFF, 0x48, 0xF4, 0xFE, 0x00, 0xF4, 0x06, 0x03, 0xA2, 0x01, 0x01, 0x22, 0x00, 0x00, 0xE1, 0xA2, +0x03, 0x15, 0x22, 0x00, 0x00, 0xE1, 0x0E, 0x43, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x52, 0x65, +0x73, 0x65, 0x74, 0x20, 0x24, 0xA9, 0xFF, 0xFF, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x02, +0x80, 0xF6, 0xAF, 0xC4, 0x03, 0xE1, 0xC9, 0xEF, 0x01, 0xD0, 0x0A, 0xAF, 0xC6, 0x03, 0xE1, 0xC9, +0xFE, 0x00, 0xD0, 0x01, 0x60, 0x48, 0x48, 0xAF, 0xC6, 0x03, 0xE1, 0x29, 0xFF, 0x00, 0x48, 0xAF, +0xC4, 0x03, 0xE1, 0x48, 0xA2, 0x02, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x02, 0x10, 0x22, 0x00, +0x00, 0xE1, 0xA9, 0xEF, 0x01, 0x8F, 0xC4, 0x03, 0xE1, 0xA9, 0xFE, 0x00, 0x8F, 0xC6, 0x03, 0xE1, +0x48, 0x48, 0xAF, 0xCE, 0x03, 0xE1, 0x29, 0xFF, 0x00, 0x48, 0xAF, 0xCC, 0x03, 0xE1, 0x48, 0xA2, +0x02, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0x0B, 0x3B, 0x5B, 0xA0, 0x04, 0x00, 0xB7, 0x03, 0x29, 0xFF, +0x7F, 0x97, 0x03, 0xF4, 0x00, 0x00, 0xF4, 0x04, 0x00, 0xD4, 0x05, 0xD4, 0x03, 0xA2, 0x02, 0x19, +0x22, 0x00, 0x00, 0xE1, 0xA0, 0x04, 0x00, 0xB7, 0x03, 0x09, 0x00, 0x80, 0x97, 0x03, 0xA7, 0x03, +0x8F, 0xCC, 0x03, 0xE1, 0x88, 0x88, 0xB7, 0x03, 0x8F, 0xCE, 0x03, 0xE1, 0x2B, 0x68, 0x68, 0x60, +0x0B, 0x3B, 0x5B, 0xA6, 0x09, 0x24, 0x0B, 0x30, 0x0C, 0xAF, 0xC0, 0x03, 0xE1, 0x85, 0x09, 0xAF, +0xC1, 0x03, 0xE1, 0x80, 0x0A, 0xAF, 0xC4, 0x03, 0xE1, 0x85, 0x09, 0xAF, 0xC5, 0x03, 0xE1, 0x85, +0x0A, 0x8A, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xA8, 0xB7, 0x09, 0x85, 0x0D, 0xC8, 0xC8, 0xB7, 0x09, +0x85, 0x0F, 0x4C, 0xC3, 0xFF, 0x3B, 0x38, 0xE9, 0x14, 0x00, 0x1B, 0x0B, 0x5B, 0x24, 0x21, 0x30, +0x18, 0xAF, 0xC0, 0x03, 0xE1, 0x85, 0x01, 0xAF, 0xC2, 0x03, 0xE1, 0x85, 0x03, 0xAF, 0xC8, 0x03, +0xE1, 0x85, 0x0D, 0xAF, 0xCA, 0x03, 0xE1, 0x80, 0x16, 0xAF, 0xC4, 0x03, 0xE1, 0x85, 0x01, 0xAF, +0xC6, 0x03, 0xE1, 0x85, 0x03, 0xAF, 0xCC, 0x03, 0xE1, 0x85, 0x0D, 0xAF, 0xCE, 0x03, 0xE1, 0x85, +0x0F, 0xA5, 0x03, 0x29, 0xFF, 0x00, 0xC9, 0xFE, 0x00, 0xF0, 0x0A, 0xA5, 0x01, 0x85, 0x09, 0xA5, +0x03, 0x85, 0x0B, 0x80, 0x30, 0xA7, 0x01, 0x0A, 0x0A, 0x20, 0xE5, 0x06, 0x86, 0x11, 0x84, 0x13, +0xA7, 0x11, 0x85, 0x09, 0xA0, 0x02, 0x00, 0xB7, 0x11, 0x85, 0x0B, 0xD4, 0x03, 0xD4, 0x01, 0xD4, +0x0B, 0xD4, 0x09, 0xA7, 0x01, 0x0A, 0x0A, 0xF4, 0x00, 0x00, 0x48, 0xA2, 0x02, 0x2B, 0x22, 0x00, +0x00, 0xE1, 0x20, 0xE0, 0x04, 0xA5, 0x1F, 0x29, 0xFF, 0x00, 0xC7, 0x01, 0x90, 0x08, 0x20, 0xFF, +0x04, 0xA5, 0x1F, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xA8, 0xB7, 0x01, 0x85, 0x05, 0xA5, 0x1B, 0x97, +0x09, 0xC8, 0xC8, 0xB7, 0x01, 0x85, 0x07, 0xA5, 0x1D, 0x97, 0x09, 0xA7, 0x1B, 0xF0, 0x1F, 0x0A, +0x0A, 0xA8, 0x88, 0x88, 0xB7, 0x1B, 0xD0, 0x10, 0x88, 0x88, 0xB7, 0x1B, 0xD0, 0x0C, 0xB7, 0x05, +0x97, 0x1B, 0xC8, 0xC8, 0xB7, 0x05, 0x97, 0x1B, 0x88, 0x88, 0x88, 0x88, 0x10, 0xE6, 0xA5, 0x1F, +0x29, 0xFF, 0x00, 0x09, 0x00, 0x01, 0xAA, 0x24, 0x21, 0x10, 0x06, 0x22, 0x08, 0x00, 0xE1, 0x80, +0x04, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x00, 0x00, 0xA5, 0x19, 0x85, 0x21, 0xA5, 0x17, 0x85, 0x1F, +0xA5, 0x15, 0x85, 0x1D, 0x2B, 0x3B, 0x18, 0x69, 0x1C, 0x00, 0x1B, 0x8A, 0xC9, 0x01, 0x00, 0x6B, +0x24, 0x21, 0x30, 0x0E, 0xA5, 0x09, 0x8F, 0xC0, 0x03, 0xE1, 0xA5, 0x0B, 0x8F, 0xC2, 0x03, 0xE1, +0x80, 0x0C, 0xA5, 0x09, 0x8F, 0xC4, 0x03, 0xE1, 0xA5, 0x0B, 0x8F, 0xC6, 0x03, 0xE1, 0x60, 0x48, +0x48, 0xD4, 0x0B, 0xD4, 0x09, 0xA2, 0x02, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x11, 0x68, +0x85, 0x13, 0xD4, 0x13, 0xD4, 0x11, 0xA2, 0x02, 0x22, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x1F, 0x29, +0xFF, 0x00, 0x1A, 0x0A, 0x0A, 0xF4, 0x00, 0x00, 0x48, 0xD4, 0x13, 0xD4, 0x11, 0xA2, 0x02, 0x19, +0x22, 0x00, 0x00, 0xE1, 0xD4, 0x13, 0xD4, 0x11, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, 0xA7, +0x11, 0x85, 0x09, 0xA0, 0x02, 0x00, 0xB7, 0x11, 0x85, 0x0B, 0x20, 0xE0, 0x04, 0x48, 0x48, 0xD4, +0x0F, 0xD4, 0x0D, 0xA2, 0x02, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x11, 0x68, 0x85, 0x13, +0xD4, 0x13, 0xD4, 0x11, 0xA2, 0x02, 0x22, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x1F, 0x29, 0xFF, 0x00, +0x1A, 0x0A, 0x0A, 0xF4, 0x00, 0x00, 0x48, 0xD4, 0x13, 0xD4, 0x11, 0xA2, 0x02, 0x19, 0x22, 0x00, +0x00, 0xE1, 0xD4, 0x13, 0xD4, 0x11, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, 0xA7, 0x11, 0x85, +0x0D, 0xA0, 0x02, 0x00, 0xB7, 0x11, 0x85, 0x0F, 0x24, 0x21, 0x30, 0x0E, 0xA5, 0x0D, 0x8F, 0xC8, +0x03, 0xE1, 0xA5, 0x0F, 0x8F, 0xCA, 0x03, 0xE1, 0x80, 0x0C, 0xA5, 0x0D, 0x8F, 0xCC, 0x03, 0xE1, +0xA5, 0x0F, 0x8F, 0xCE, 0x03, 0xE1, 0xA7, 0x09, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xA8, 0xA9, 0xEB, +0x01, 0x97, 0x09, 0xA9, 0x00, 0x00, 0x97, 0x0D, 0xC8, 0xC8, 0xA9, 0xFE, 0x00, 0x97, 0x09, 0xA9, +0x00, 0x00, 0x97, 0x0D, 0xC8, 0xC8, 0xA7, 0x09, 0x1A, 0x87, 0x09, 0xA5, 0x1F, 0x29, 0xFF, 0x00, +0x1A, 0xC7, 0x09, 0xF0, 0x02, 0xB0, 0xD7, 0x60, 0x0B, 0x48, 0x48, 0x48, 0x48, 0x3B, 0x5B, 0x24, +0x13, 0x30, 0x0C, 0xAF, 0xC0, 0x03, 0xE1, 0x85, 0x01, 0xAF, 0xC1, 0x03, 0xE1, 0x80, 0x0A, 0xAF, +0xC4, 0x03, 0xE1, 0x85, 0x01, 0xAF, 0xC5, 0x03, 0xE1, 0x85, 0x02, 0xA5, 0x11, 0x29, 0xFF, 0x00, +0xF0, 0x04, 0xC7, 0x01, 0x90, 0x05, 0xA2, 0x11, 0x00, 0x80, 0x2B, 0x0A, 0x0A, 0xA8, 0xB7, 0x01, +0x85, 0x05, 0xC8, 0xB7, 0x01, 0x85, 0x06, 0xA5, 0x12, 0x29, 0xFF, 0x00, 0xF0, 0x04, 0xC7, 0x05, +0x90, 0x05, 0xA2, 0x12, 0x00, 0x80, 0x0F, 0x0A, 0x0A, 0xA8, 0xB7, 0x05, 0x85, 0x15, 0xC8, 0xB7, +0x05, 0x85, 0x16, 0xA2, 0x00, 0x00, 0x68, 0x68, 0x68, 0x68, 0x4C, 0xC6, 0xFF, 0x0B, 0x3B, 0x5B, +0xA6, 0x09, 0x24, 0x0B, 0x30, 0x0C, 0xAF, 0xC8, 0x03, 0xE1, 0x85, 0x09, 0xAF, 0xCA, 0x03, 0xE1, +0x80, 0x0A, 0xAF, 0xCC, 0x03, 0xE1, 0x85, 0x09, 0xAF, 0xCE, 0x03, 0xE1, 0x85, 0x0B, 0x8A, 0x29, +0xFF, 0x00, 0x0A, 0x0A, 0xA8, 0xB7, 0x09, 0x85, 0x0D, 0xC8, 0xC8, 0xB7, 0x09, 0x85, 0x0F, 0x4C, +0xC3, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x3B, 0x5B, 0xA6, 0x11, 0x24, 0x13, 0x30, +0x18, 0xAF, 0xC8, 0x03, 0xE1, 0x85, 0x11, 0xAF, 0xCA, 0x03, 0xE1, 0x85, 0x13, 0xAF, 0xC0, 0x03, +0xE1, 0x85, 0x01, 0xAF, 0xC2, 0x03, 0xE1, 0x80, 0x16, 0xAF, 0xCC, 0x03, 0xE1, 0x85, 0x11, 0xAF, +0xCE, 0x03, 0xE1, 0x85, 0x13, 0xAF, 0xC4, 0x03, 0xE1, 0x85, 0x01, 0xAF, 0xC6, 0x03, 0xE1, 0x85, +0x03, 0x8A, 0x29, 0xFF, 0x00, 0xF0, 0x04, 0xC7, 0x01, 0x90, 0x08, 0xA2, 0x11, 0x00, 0x68, 0x68, +0x4C, 0xDC, 0xFF, 0x0A, 0x0A, 0xA8, 0xA5, 0x0D, 0x97, 0x11, 0xC8, 0xC8, 0xA5, 0x0F, 0x97, 0x11, +0x68, 0x68, 0x4C, 0xD9, 0xFF, 0x48, 0x48, 0xF4, 0x00, 0x00, 0x48, 0xF4, 0x00, 0x90, 0xF4, 0x08, +0x80, 0x48, 0x48, 0xA2, 0x02, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xFA, 0x7A, 0x60, 0xDA, 0x00, 0x00, +0x00, 0x64, 0x0A, 0xFE, 0x00, 0x90, 0x0A, 0xFE, 0x00, 0xDF, 0x0B, 0xFE, 0x00, 0x4F, 0x0C, 0xFE, +0x00, 0x5C, 0x0C, 0xFE, 0x00, 0x66, 0x0C, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, +0x00, 0x04, 0x0E, 0xFE, 0x00, 0x34, 0x11, 0xFE, 0x00, 0x45, 0x11, 0xFE, 0x00, 0x56, 0x11, 0xFE, +0x00, 0x5E, 0x11, 0xFE, 0x00, 0x8E, 0x11, 0xFE, 0x00, 0xBD, 0x11, 0xFE, 0x00, 0xEC, 0x11, 0xFE, +0x00, 0x23, 0x12, 0xFE, 0x00, 0x5A, 0x12, 0xFE, 0x00, 0x7A, 0x12, 0xFE, 0x00, 0x9A, 0x12, 0xFE, +0x00, 0xAD, 0x12, 0xFE, 0x00, 0xCF, 0x12, 0xFE, 0x00, 0xD9, 0x12, 0xFE, 0x00, 0xE3, 0x12, 0xFE, +0x00, 0x28, 0x13, 0xFE, 0x00, 0xB4, 0x13, 0xFE, 0x00, 0xDE, 0x13, 0xFE, 0x00, 0xEC, 0x13, 0xFE, +0x00, 0xFD, 0x13, 0xFE, 0x00, 0x16, 0x14, 0xFE, 0x00, 0x2F, 0x14, 0xFE, 0x00, 0x50, 0x14, 0xFE, +0x00, 0x71, 0x14, 0xFE, 0x00, 0x8D, 0x14, 0xFE, 0x00, 0xB7, 0x14, 0xFE, 0x00, 0x22, 0x15, 0xFE, +0x00, 0x42, 0x15, 0xFE, 0x00, 0x62, 0x15, 0xFE, 0x00, 0xC2, 0x15, 0xFE, 0x00, 0xD0, 0x15, 0xFE, +0x00, 0xDE, 0x15, 0xFE, 0x00, 0x1D, 0x16, 0xFE, 0x00, 0xFC, 0x15, 0xFE, 0x00, 0x1B, 0x17, 0xFE, +0x00, 0x2E, 0x17, 0xFE, 0x00, 0xB2, 0x17, 0xFE, 0x00, 0x27, 0x18, 0xFE, 0x00, 0x3E, 0x16, 0xFE, +0x00, 0x4C, 0x16, 0xFE, 0x00, 0x6C, 0x16, 0xFE, 0x00, 0x7A, 0x16, 0xFE, 0x00, 0x88, 0x16, 0xFE, +0x00, 0x96, 0x16, 0xFE, 0x00, 0x4C, 0x17, 0xFE, 0x00, 0x5A, 0x16, 0xFE, 0x00, 0xA4, 0x16, 0xFE, +0x00, 0xB6, 0x16, 0xFE, 0x00, 0x67, 0x17, 0xFE, 0x00, 0x7A, 0x17, 0xFE, 0x00, 0x53, 0x24, 0xFE, +0x00, 0x70, 0x24, 0xFE, 0x00, 0xEC, 0x17, 0xFE, 0x00, 0x6B, 0x18, 0xFE, 0x00, 0xF1, 0x17, 0xFE, +0x00, 0x70, 0x18, 0xFE, 0x00, 0xF6, 0x17, 0xFE, 0x00, 0x75, 0x18, 0xFE, 0x00, 0xFB, 0x17, 0xFE, +0x00, 0x7A, 0x18, 0xFE, 0x00, 0x00, 0x18, 0xFE, 0x00, 0x7F, 0x18, 0xFE, 0x00, 0x05, 0x18, 0xFE, +0x00, 0x84, 0x18, 0xFE, 0x00, 0xD8, 0x1A, 0xFE, 0x00, 0xF5, 0x1A, 0xFE, 0x00, 0x12, 0x1B, 0xFE, +0x00, 0x3B, 0x1B, 0xFE, 0x00, 0x8D, 0x1B, 0xFE, 0x00, 0xB8, 0x1B, 0xFE, 0x00, 0xE4, 0x1B, 0xFE, +0x00, 0x02, 0x1C, 0xFE, 0x00, 0x1F, 0x1C, 0xFE, 0x00, 0x4A, 0x22, 0xFE, 0x00, 0x4F, 0x22, 0xFE, +0x00, 0x54, 0x22, 0xFE, 0x00, 0x59, 0x22, 0xFE, 0x00, 0x6E, 0x22, 0xFE, 0x00, 0x63, 0x80, 0xFE, +0x00, 0x85, 0x80, 0xFE, 0x00, 0x99, 0x80, 0xFE, 0x00, 0xAD, 0x80, 0xFE, 0x00, 0xC1, 0x80, 0xFE, +0x00, 0x4B, 0x81, 0xFE, 0x00, 0x75, 0x81, 0xFE, 0x00, 0x94, 0x81, 0xFE, 0x00, 0xB3, 0x81, 0xFE, +0x00, 0xD2, 0x81, 0xFE, 0x00, 0x1F, 0x82, 0xFE, 0x00, 0x3E, 0x82, 0xFE, 0x00, 0x5D, 0x82, 0xFE, +0x00, 0x7C, 0x82, 0xFE, 0x00, 0x9B, 0x82, 0xFE, 0x00, 0xA9, 0x43, 0xFE, 0x00, 0xD8, 0x43, 0xFE, +0x00, 0xBF, 0x44, 0xFE, 0x00, 0xED, 0x43, 0xFE, 0x00, 0x24, 0x44, 0xFE, 0x00, 0x82, 0x44, 0xFE, +0x00, 0xB6, 0x59, 0xFE, 0x00, 0x04, 0x5A, 0xFE, 0x00, 0xC3, 0x61, 0xFE, 0x00, 0x84, 0x60, 0xFE, +0x00, 0xFD, 0x5E, 0xFE, 0x00, 0x06, 0x5F, 0xFE, 0x00, 0x0F, 0x5F, 0xFE, 0x00, 0x18, 0x5F, 0xFE, +0x00, 0x3A, 0x52, 0xFE, 0x00, 0xC7, 0x52, 0xFE, 0x00, 0x05, 0x45, 0xFE, 0x00, 0x44, 0x45, 0xFE, +0x00, 0x49, 0x42, 0xFE, 0x00, 0x4E, 0x42, 0xFE, 0x00, 0x53, 0x42, 0xFE, 0x00, 0x58, 0x42, 0xFE, +0x00, 0x6E, 0x42, 0xFE, 0x00, 0x85, 0x34, 0xFE, 0x00, 0x81, 0x36, 0xFE, 0x00, 0xD9, 0x1C, 0xFE, +0x00, 0xED, 0x1C, 0xFE, 0x00, 0x01, 0x1D, 0xFE, 0x00, 0x12, 0x1D, 0xFE, 0x00, 0x2F, 0x1D, 0xFE, +0x00, 0x56, 0x1D, 0xFE, 0x00, 0x43, 0x1C, 0xFE, 0x00, 0xC8, 0x1C, 0xFE, 0x00, 0x7D, 0x1D, 0xFE, +0x00, 0xDD, 0x1D, 0xFE, 0x00, 0xB1, 0x64, 0xFE, 0x00, 0x90, 0x64, 0xFE, 0x00, 0x44, 0x62, 0xFE, +0x00, 0xE0, 0x0D, 0xFE, 0x00, 0x88, 0x3D, 0xFE, 0x00, 0x73, 0x3E, 0xFE, 0x00, 0xAE, 0x3E, 0xFE, +0x00, 0x86, 0x3E, 0xFE, 0x00, 0xCA, 0x3E, 0xFE, 0x00, 0x89, 0x3F, 0xFE, 0x00, 0x93, 0x17, 0xFE, +0x00, 0x57, 0x18, 0xFE, 0x00, 0x05, 0x69, 0xFE, 0x00, 0xE8, 0x6A, 0xFE, 0x00, 0xBC, 0x17, 0xFE, +0x00, 0x31, 0x18, 0xFE, 0x00, 0xC1, 0x17, 0xFE, 0x00, 0x36, 0x18, 0xFE, 0x00, 0xC6, 0x17, 0xFE, +0x00, 0x3B, 0x18, 0xFE, 0x00, 0xE2, 0x17, 0xFE, 0x00, 0x61, 0x18, 0xFE, 0x00, 0xCB, 0x17, 0xFE, +0x00, 0x40, 0x18, 0xFE, 0x00, 0xD0, 0x17, 0xFE, 0x00, 0x45, 0x18, 0xFE, 0x00, 0x85, 0x65, 0xFE, +0x00, 0x96, 0x65, 0xFE, 0x00, 0xD1, 0x65, 0xFE, 0x00, 0xB8, 0x65, 0xFE, 0x00, 0xCC, 0x64, 0xFE, +0x00, 0xE1, 0x64, 0xFE, 0x00, 0x24, 0x65, 0xFE, 0x00, 0x07, 0x65, 0xFE, 0x00, 0x4D, 0x67, 0xFE, +0x00, 0x66, 0x67, 0xFE, 0x00, 0xB1, 0x67, 0xFE, 0x00, 0x90, 0x67, 0xFE, 0x00, 0xD5, 0x17, 0xFE, +0x00, 0x4A, 0x18, 0xFE, 0x00, 0x27, 0x0E, 0xFE, 0x00, 0x38, 0x0E, 0xFE, 0x00, 0x82, 0x15, 0xFE, +0x00, 0xA2, 0x15, 0xFE, 0x00, 0xB6, 0x3F, 0xFE, 0x00, 0xFF, 0x1E, 0xE0, 0x00, 0x03, 0x1F, 0xE0, +0x00, 0x07, 0x1F, 0xE0, 0x00, 0x0B, 0x1F, 0xE0, 0x00, 0x0F, 0x1F, 0xE0, 0x00, 0x9F, 0x8B, 0xFE, +0x00, 0xA4, 0x8B, 0xFE, 0x00, 0xA9, 0x8B, 0xFE, 0x00, 0xAE, 0x8B, 0xFE, 0x00, 0xC4, 0x8B, 0xFE, +0x00, 0x9C, 0x8D, 0xFE, 0x00, 0xFD, 0x8D, 0xFE, 0x00, 0xA9, 0x8E, 0xFE, 0x00, 0xBB, 0x8E, 0xFE, +0x00, 0xE9, 0x8E, 0xFE, 0x00, 0x0A, 0x18, 0xFE, 0x00, 0x89, 0x18, 0xFE, 0x00, 0x0F, 0x18, 0xFE, +0x00, 0x8E, 0x18, 0xFE, 0x00, 0x65, 0x3C, 0xFE, 0x00, 0x49, 0x0E, 0xFE, 0x00, 0x81, 0x0E, 0xFE, +0x00, 0x8B, 0x0E, 0xFE, 0x00, 0xB3, 0x0E, 0xFE, 0x00, 0x38, 0x69, 0xFE, 0x00, 0x14, 0x18, 0xFE, +0x00, 0x5C, 0x18, 0xFE, 0x00, 0xB7, 0x17, 0xFE, 0x00, 0x2C, 0x18, 0xFE, 0x00, 0xE7, 0x17, 0xFE, +0x00, 0x66, 0x18, 0xFE, 0x00, 0xF1, 0x33, 0xFE, 0x00, 0x77, 0x6A, 0xFE, 0x00, 0x55, 0x69, 0xFE, +0x00, 0xB0, 0x69, 0xFE, 0x00, 0xF4, 0x18, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0xCE, 0x3F, 0xA2, 0x03, +0x10, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0xFE, 0x00, 0xF4, 0xFD, 0x0E, 0xF4, 0xE0, 0x00, 0xF4, 0x00, +0x1E, 0xF4, 0x00, 0x00, 0xF4, 0xFC, 0x01, 0xA2, 0x02, 0x2B, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0x8B, +0xFF, 0x22, 0x64, 0x00, 0xE1, 0xC9, 0x00, 0x00, 0xF0, 0x06, 0xA2, 0x01, 0x04, 0x4C, 0x85, 0xFF, +0x0B, 0xA3, 0x0F, 0xF4, 0x00, 0x00, 0xF4, 0x04, 0x00, 0xF4, 0x00, 0x00, 0x48, 0xA2, 0x01, 0x0D, +0x22, 0x00, 0x00, 0xE1, 0xA3, 0x0F, 0x5B, 0xA2, 0x00, 0x00, 0x74, 0x00, 0xE8, 0xE8, 0xE0, 0x00, +0x02, 0x90, 0xF7, 0xA3, 0x0B, 0xC9, 0x00, 0x00, 0xD0, 0x03, 0xA9, 0xA0, 0x00, 0x85, 0x28, 0xA3, +0x0D, 0x85, 0x08, 0xA3, 0x09, 0x85, 0x0A, 0x48, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x80, 0xD4, +0x0A, 0xF4, 0x02, 0xC0, 0xF4, 0xE1, 0x00, 0xF4, 0x00, 0x20, 0x22, 0x08, 0x11, 0xFE, 0x90, 0x08, +0x68, 0x68, 0xA9, 0x10, 0x04, 0x4C, 0xC2, 0x0B, 0xA2, 0x00, 0x01, 0x68, 0x95, 0x06, 0x68, 0x95, +0x08, 0xE2, 0x20, 0xAF, 0x29, 0xC0, 0x00, 0x09, 0x40, 0x8F, 0x29, 0xC0, 0x00, 0xC2, 0x20, 0x22, +0x6C, 0x1F, 0xE0, 0x90, 0x03, 0x4C, 0xC2, 0x0B, 0xD4, 0x08, 0xA2, 0x04, 0x14, 0x22, 0x00, 0x00, +0xE1, 0xF4, 0xE1, 0x00, 0xF4, 0x00, 0x9E, 0xA2, 0x04, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x22, 0xBD, +0x3B, 0xFE, 0xC9, 0x00, 0x00, 0xF0, 0x03, 0x4C, 0xC2, 0x0B, 0xF4, 0x00, 0x00, 0xA2, 0x04, 0x15, +0x22, 0x00, 0x00, 0xE1, 0xA2, 0x00, 0x01, 0xA9, 0xE0, 0x77, 0x95, 0x4E, 0xA9, 0xFE, 0x00, 0x95, +0x50, 0xA9, 0xAA, 0x00, 0xA6, 0x0A, 0xA0, 0x00, 0x80, 0x20, 0x24, 0x11, 0x90, 0x03, 0x4C, 0xC2, +0x0B, 0x86, 0x2A, 0x84, 0x2C, 0x8A, 0xA2, 0x00, 0x01, 0x95, 0x0A, 0x98, 0x95, 0x0C, 0xA0, 0x02, +0x00, 0xB7, 0x2A, 0x48, 0xA7, 0x2A, 0x48, 0xA2, 0x04, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, +0x4C, 0xC2, 0x0B, 0xA9, 0x28, 0x00, 0x85, 0x52, 0xA9, 0x14, 0x00, 0x85, 0x50, 0x64, 0x56, 0x22, +0xA8, 0x1F, 0xE0, 0x90, 0x03, 0x4C, 0xC2, 0x0B, 0xA5, 0x28, 0x20, 0xD0, 0x0B, 0xA6, 0x0A, 0xA0, +0x00, 0x00, 0x20, 0x24, 0x11, 0x90, 0x03, 0x4C, 0xC2, 0x0B, 0x86, 0x3C, 0x84, 0x3E, 0xA2, 0x00, +0x01, 0xA9, 0x01, 0x00, 0x95, 0x00, 0x74, 0x02, 0xA2, 0x04, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0x4C, +0x81, 0xFF, 0x85, 0x0A, 0xA2, 0x04, 0x03, 0x22, 0x00, 0x00, 0xE1, 0xA6, 0x0A, 0x4C, 0x84, 0xFF, +0x48, 0x18, 0x63, 0x01, 0x63, 0x01, 0x4A, 0x18, 0x63, 0x01, 0x18, 0x69, 0x4E, 0x00, 0xFA, 0x60, +0xC9, 0x00, 0x00, 0xD0, 0x03, 0x4C, 0x8B, 0xFF, 0x20, 0xB3, 0x0D, 0xA2, 0x00, 0x01, 0xB5, 0x0C, +0x48, 0x85, 0x2C, 0xB5, 0x0A, 0x48, 0x85, 0x2A, 0xA7, 0x2A, 0xAA, 0xA0, 0x02, 0x00, 0xB7, 0x2A, +0x48, 0xDA, 0xA2, 0x04, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0x22, 0x10, 0x11, 0xFE, 0xA5, 0x46, 0x48, +0xA5, 0x44, 0x48, 0x22, 0x10, 0x11, 0xFE, 0xD4, 0x3E, 0xD4, 0x3C, 0x22, 0x10, 0x11, 0xFE, 0xA2, +0x00, 0x01, 0xB5, 0x08, 0x48, 0xB5, 0x06, 0x48, 0x22, 0x10, 0x11, 0xFE, 0x20, 0xAD, 0x3C, 0xA9, +0x00, 0x00, 0x48, 0xF4, 0x04, 0x00, 0x48, 0x48, 0xA2, 0x01, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0xE2, +0x30, 0xAF, 0x29, 0xC0, 0x00, 0x29, 0x3F, 0x8F, 0x29, 0xC0, 0x00, 0xC2, 0x30, 0x4C, 0x3F, 0xFF, +0x22, 0x14, 0x1F, 0xE0, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x02, 0x6B, 0xA2, 0x04, 0x03, +0x22, 0x00, 0x00, 0xE1, 0x4C, 0x8B, 0xFF, 0xC9, 0x00, 0x00, 0xF0, 0x08, 0xA9, 0xFF, 0xFF, 0x83, +0x07, 0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x00, 0x80, 0xF6, 0x00, 0x00, 0x00, 0x20, 0xE1, 0x00, 0xA0, +0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x40, +0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE0, 0x77, 0xFE, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0xE1, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, +0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x80, 0x02, 0x00, 0x00, 0x77, 0x07, 0x41, +0x08, 0x2C, 0x07, 0x0F, 0x00, 0x80, 0x00, 0x70, 0x0F, 0x00, 0x0D, 0xA9, 0x0F, 0xF0, 0x0F, 0xE0, +0x00, 0xDF, 0x04, 0xAF, 0x0D, 0x8F, 0x07, 0xCC, 0x0C, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xF0, +0x00, 0xFF, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xF0, +0x00, 0xFF, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0x0F, 0x03, 0x1E, 0xE0, 0x00, 0x07, +0x1E, 0xE0, 0x00, 0x0B, 0x1E, 0xE0, 0x00, 0x0F, 0x1E, 0xE0, 0x00, 0x13, 0x1E, 0xE0, 0x00, 0x17, +0x1E, 0xE0, 0x00, 0x1B, 0x1E, 0xE0, 0x00, 0x1F, 0x1E, 0xE0, 0x00, 0x23, 0x1E, 0xE0, 0x00, 0x27, +0x1E, 0xE0, 0x00, 0x2B, 0x1E, 0xE0, 0x00, 0x2F, 0x1E, 0xE0, 0x00, 0x33, 0x1E, 0xE0, 0x00, 0x37, +0x1E, 0xE0, 0x00, 0x22, 0x64, 0x00, 0xE1, 0x0B, 0x5B, 0xA3, 0x03, 0x48, 0xA3, 0x03, 0x83, 0x05, +0x68, 0x83, 0x01, 0x7B, 0x60, 0xA0, 0x9C, 0x00, 0xB7, 0x24, 0x85, 0x2A, 0xC8, 0xC8, 0xB7, 0x24, +0x85, 0x2C, 0xF0, 0x02, 0x38, 0x60, 0xA5, 0x2A, 0xD0, 0xFA, 0x18, 0x60, 0x18, 0xA9, 0x00, 0x00, +0x6B, 0x3B, 0x0B, 0x5B, 0xA0, 0x36, 0x00, 0xBB, 0xBF, 0x7B, 0x0D, 0xFE, 0x97, 0x07, 0x88, 0x88, +0x10, 0xF5, 0x4C, 0xC3, 0xFF, 0xFB, 0x0D, 0xFE, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x01, 0xC0, 0x01, +0xC0, 0xFF, 0x3F, 0xFF, 0x3F, 0xA3, 0x07, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x18, 0x0E, +0xFE, 0x83, 0x09, 0xBF, 0x1A, 0x0E, 0xFE, 0x83, 0x0B, 0x4C, 0xB7, 0xFF, 0x74, 0xBD, 0xFF, 0x00, +0x3B, 0x4C, 0xFE, 0x00, 0x3B, 0x50, 0xFE, 0x00, 0x20, 0xB3, 0x0D, 0xA2, 0x00, 0x01, 0xA3, 0x09, +0x95, 0x4E, 0xA3, 0x0B, 0x95, 0x50, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA2, 0x00, 0x01, 0xB5, +0x4E, 0x83, 0x09, 0xB5, 0x50, 0x83, 0x0B, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, 0x0D, 0x64, 0x56, 0xA3, +0x0D, 0x20, 0xD0, 0x0B, 0xF4, 0x00, 0x00, 0x48, 0xD4, 0x3E, 0xD4, 0x3C, 0xA2, 0x02, 0x19, 0x22, +0x00, 0x00, 0xE1, 0x90, 0x04, 0xAA, 0x4C, 0x79, 0xFF, 0xA3, 0x0D, 0x85, 0x28, 0xA3, 0x09, 0x85, +0x52, 0xA3, 0x0B, 0x85, 0x50, 0x22, 0xA8, 0x1F, 0xE0, 0xB0, 0xEA, 0xA3, 0x0D, 0x85, 0x28, 0x4C, +0x76, 0xFF, 0x20, 0xB3, 0x0D, 0xA9, 0x00, 0x80, 0x85, 0x56, 0x80, 0xC3, 0x20, 0xB3, 0x0D, 0xA3, +0x09, 0x85, 0x2A, 0xA3, 0x0B, 0x85, 0x2C, 0xA5, 0x28, 0x87, 0x2A, 0xA5, 0x4A, 0xA0, 0x02, 0x00, +0x97, 0x2A, 0xA5, 0x48, 0xC8, 0xC8, 0x97, 0x2A, 0xA2, 0x00, 0x01, 0xB5, 0x04, 0xC8, 0xC8, 0x97, +0x2A, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xA3, 0x0B, 0x85, 0x2C, 0xA7, +0x2A, 0x20, 0xD0, 0x0B, 0xF4, 0x00, 0x00, 0x48, 0xD4, 0x3E, 0xD4, 0x3C, 0xA2, 0x02, 0x19, 0x22, +0x00, 0x00, 0xE1, 0x90, 0x04, 0xAA, 0x4C, 0x6E, 0xFF, 0xA7, 0x2A, 0x85, 0x28, 0xA0, 0x02, 0x00, +0xB7, 0x2A, 0x85, 0x50, 0xC8, 0xC8, 0xB7, 0x2A, 0x85, 0x54, 0xC8, 0xC8, 0xB7, 0x2A, 0x85, 0x56, +0x22, 0xAC, 0x1F, 0xE0, 0x90, 0x04, 0xAA, 0x4C, 0x6E, 0xFF, 0x4C, 0x6B, 0xFF, 0x5C, 0x00, 0x00, +0x00, 0x5C, 0xFF, 0x65, 0xFE, 0x5C, 0xA1, 0x24, 0xFE, 0x5C, 0xB9, 0x22, 0xFE, 0x5C, 0x1F, 0x81, +0xFE, 0x5C, 0x1A, 0x81, 0xFE, 0x5C, 0x15, 0x81, 0xFE, 0x5C, 0xF7, 0x8B, 0xFE, 0x5C, 0xA1, 0x42, +0xFE, 0x5C, 0x4D, 0x31, 0xFE, 0x5C, 0xE3, 0xFF, 0xFE, 0x5C, 0x56, 0x65, 0xFE, 0x5C, 0xE7, 0x67, +0xFE, 0x5C, 0xE3, 0xFF, 0xFE, 0x5C, 0xE3, 0xFF, 0xFE, 0x5C, 0xA2, 0x18, 0xFE, 0x5C, 0xBC, 0x18, +0xFE, 0x5C, 0xF4, 0x18, 0xFE, 0x5C, 0x03, 0x19, 0xFE, 0x5C, 0x12, 0x19, 0xFE, 0x5C, 0x26, 0x19, +0xFE, 0x5C, 0x62, 0x19, 0xFE, 0x5C, 0xA5, 0x19, 0xFE, 0x5C, 0x03, 0x1A, 0xFE, 0x5C, 0x17, 0x1A, +0xFE, 0x5C, 0x7A, 0x1A, 0xFE, 0x5C, 0xBC, 0x1A, 0xFE, 0x5C, 0x04, 0x21, 0xFE, 0x5C, 0x18, 0x21, +0xFE, 0x5C, 0x8B, 0x23, 0xFE, 0x5C, 0x8B, 0x23, 0xFE, 0x5C, 0x38, 0x37, 0xFE, 0x5C, 0xDE, 0x38, +0xFE, 0x5C, 0xE0, 0x38, 0xFE, 0x5C, 0x69, 0x39, 0xFE, 0x5C, 0x6B, 0x39, 0xFE, 0x5C, 0xF7, 0x39, +0xFE, 0x5C, 0xFA, 0x39, 0xFE, 0x5C, 0xEA, 0x3E, 0xFE, 0x5C, 0x6B, 0x3F, 0xFE, 0x5C, 0x78, 0x46, +0xFE, 0x5C, 0xB3, 0x46, 0xFE, 0x5C, 0x86, 0x46, 0xFE, 0x5C, 0x89, 0x46, 0xFE, 0x5C, 0x86, 0x46, +0xFE, 0x5C, 0x83, 0x46, 0xFE, 0x5C, 0x45, 0x69, 0xFE, 0x5C, 0x34, 0x48, 0xFE, 0x5C, 0xBF, 0x47, +0xFE, 0x5C, 0x1E, 0x47, 0xFE, 0x5C, 0x5F, 0x48, 0xFE, 0x5C, 0x06, 0x48, 0xFE, 0x5C, 0x81, 0x47, +0xFE, 0x5C, 0x91, 0x48, 0xFE, 0x5C, 0xC7, 0x49, 0xFE, 0x5C, 0xAF, 0x4B, 0xFE, 0x5C, 0x82, 0x4B, +0xFE, 0x5C, 0x51, 0x4B, 0xFE, 0x5C, 0xA5, 0x20, 0xFE, 0x5C, 0x09, 0x38, 0xFE, 0x5C, 0xB9, 0x74, +0xFE, 0x5C, 0xF6, 0x72, 0xFE, 0x5C, 0xDC, 0x0D, 0xFE, 0x5C, 0x1D, 0x8F, 0xFE, 0x5C, 0xF9, 0x10, +0xFE, 0x5C, 0xFC, 0x10, 0xFE, 0x5C, 0xFF, 0x10, 0xFE, 0x5C, 0x02, 0x11, 0xFE, 0x5C, 0x05, 0x11, +0xFE, 0x5C, 0x59, 0x0C, 0xFE, 0x5C, 0xC8, 0x42, 0xFE, 0x5C, 0xC0, 0x42, 0xFE, 0x5C, 0xC0, 0x42, +0xFE, 0x5C, 0xC0, 0x42, 0xFE, 0x5C, 0xC0, 0x42, 0xFE, 0x5C, 0xE0, 0x22, 0xFE, 0x5C, 0xD8, 0x22, +0xFE, 0x5C, 0xD8, 0x22, 0xFE, 0x5C, 0xD8, 0x22, 0xFE, 0x5C, 0xD8, 0x22, 0xFE, 0x5C, 0x13, 0x66, +0xFE, 0x5C, 0x6E, 0x66, 0xFE, 0x5C, 0xF4, 0x67, 0xFE, 0x5C, 0x6A, 0x68, 0xFE, 0x5C, 0x04, 0x6B, +0xFE, 0x5C, 0x78, 0x6B, 0xFE, 0x5C, 0xBA, 0x6B, 0xFE, 0x5C, 0xD9, 0x6B, 0xFE, 0x5C, 0x2A, 0x6C, +0xFE, 0x5C, 0xB6, 0x6C, 0xFE, 0x5C, 0xCE, 0x6D, 0xFE, 0x5C, 0x17, 0x6E, 0xFE, 0x5C, 0x45, 0x6E, +0xFE, 0x5C, 0xBC, 0x70, 0xFE, 0x5C, 0xA7, 0x6B, 0xFE, 0x5C, 0x8E, 0x6E, 0xFE, 0x5C, 0xA2, 0x54, +0xFE, 0x5C, 0x04, 0x56, 0xFE, 0x5C, 0x40, 0x54, 0xFE, 0x5C, 0xED, 0x56, 0xFE, 0x5C, 0xA1, 0x57, +0xFE, 0x5C, 0xA8, 0x58, 0xFE, 0x5C, 0xD4, 0x5C, 0xFE, 0x5C, 0xC0, 0x8A, 0xFE, 0x5C, 0x87, 0x85, +0xFE, 0x5C, 0xBD, 0x84, 0xFE, 0x5C, 0x1D, 0x72, 0xFE, 0x5C, 0xA2, 0x72, 0xFE, 0x5C, 0xA9, 0x6E, +0xFE, 0x5C, 0xAD, 0x6E, 0xFE, 0x5C, 0xCB, 0x6E, 0xFE, 0x5C, 0x70, 0x6F, 0xFE, 0x5C, 0x22, 0x81, +0xFE, 0x5C, 0x8B, 0x86, 0xFE, 0x5C, 0x8F, 0x63, 0xFE, 0x5C, 0xBD, 0x40, 0xFE, 0x5C, 0xD2, 0x41, +0xFE, 0x5C, 0x23, 0x83, 0xFE, 0x5C, 0x6C, 0x83, 0xFE, 0x5C, 0x63, 0x31, 0xFE, 0x5C, 0x53, 0x33, +0xFE, 0x5C, 0xC4, 0x33, 0xFE, 0x5C, 0x1C, 0x6B, 0xFE, 0x5C, 0x3A, 0x6B, 0xFE, 0x5C, 0x57, 0x6B, +0xFE, 0x5C, 0x25, 0x67, 0xFE, 0x5C, 0x18, 0x69, 0xFE, 0x4C, 0xC2, 0xFF, 0x4C, 0xD8, 0xFF, 0x4C, +0x8B, 0xFF, 0x4C, 0xD8, 0xFF, 0x4C, 0xC2, 0xFF, 0xA2, 0x02, 0x09, 0x22, 0x04, 0x00, 0xE1, 0x6B, +0xA2, 0x02, 0x10, 0x80, 0xF6, 0xA2, 0x04, 0x69, 0x80, 0xF1, 0xA2, 0x03, 0x10, 0x80, 0xEC, 0xA2, +0x03, 0x11, 0x80, 0xE7, 0x48, 0x48, 0xF4, 0x00, 0x00, 0x48, 0xDA, 0x5A, 0x48, 0x48, 0x22, 0x08, +0x11, 0xFE, 0xFA, 0x7A, 0x60, 0xE2, 0x30, 0xA9, 0x80, 0x0F, 0x29, 0xC0, 0xE0, 0x8F, 0x29, 0xC0, +0xE0, 0xC2, 0x30, 0x4C, 0x8B, 0xFF, 0xE2, 0x30, 0xA9, 0x7F, 0x2F, 0x29, 0xC0, 0xE0, 0x8F, 0x29, +0xC0, 0xE0, 0xC2, 0x30, 0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x00, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0x20, +0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xA3, 0x0A, 0x85, 0x2B, 0x24, 0x07, 0x30, 0x10, 0xA0, 0x1E, +0x00, 0xBB, 0xBF, 0x3B, 0x0D, 0xFE, 0x97, 0x2A, 0x88, 0x88, 0x10, 0xF5, 0x80, 0x0E, 0xA0, 0x1E, +0x00, 0xBB, 0xBF, 0x5B, 0x0D, 0xFE, 0x97, 0x2A, 0x88, 0x88, 0x10, 0xF5, 0x4C, 0x6B, 0xFF, 0x0B, +0x3B, 0x5B, 0xA9, 0x1E, 0x00, 0xA6, 0x0D, 0xF0, 0x0C, 0xE0, 0x10, 0x00, 0xB0, 0x1A, 0x18, 0x69, +0x20, 0x00, 0xCA, 0xD0, 0xF9, 0xAA, 0xA0, 0x1E, 0x00, 0xB7, 0x09, 0x9F, 0x00, 0x9E, 0xE1, 0xCA, +0xCA, 0x88, 0x88, 0x10, 0xF4, 0x4C, 0xCE, 0xFF, 0xA2, 0x50, 0x04, 0x4C, 0xD1, 0xFF, 0x0B, 0x3B, +0x5B, 0xA9, 0x1E, 0x00, 0xA6, 0x0D, 0xF0, 0x0C, 0xE0, 0x10, 0x00, 0xB0, 0x1A, 0x18, 0x69, 0x20, +0x00, 0xCA, 0xD0, 0xF9, 0xAA, 0xA0, 0x1E, 0x00, 0xBF, 0x00, 0x9E, 0xE1, 0x97, 0x09, 0xCA, 0xCA, +0x88, 0x88, 0x10, 0xF4, 0x4C, 0xCE, 0xFF, 0xA2, 0x50, 0x04, 0x4C, 0xD1, 0xFF, 0xA3, 0x0B, 0xC9, +0x10, 0x00, 0xB0, 0x24, 0xA8, 0xF0, 0x0A, 0xA9, 0x00, 0x00, 0x18, 0x69, 0x20, 0x00, 0x88, 0xD0, +0xFA, 0xAA, 0xA3, 0x09, 0xC9, 0x10, 0x00, 0xB0, 0x15, 0x8A, 0x63, 0x09, 0x63, 0x09, 0xAA, 0xA3, +0x07, 0x9F, 0x00, 0x9E, 0xE1, 0x4C, 0xCD, 0xFF, 0xA2, 0x50, 0x04, 0x4C, 0xD2, 0xFF, 0xA2, 0x51, +0x04, 0x4C, 0xD2, 0xFF, 0xA3, 0x09, 0xC9, 0x10, 0x00, 0xB0, 0x24, 0xA8, 0xF0, 0x0A, 0xA9, 0x00, +0x00, 0x18, 0x69, 0x20, 0x00, 0x88, 0xD0, 0xFA, 0xAA, 0xA3, 0x07, 0xC9, 0x10, 0x00, 0xB0, 0x15, +0x8A, 0x63, 0x07, 0x63, 0x07, 0xAA, 0xBF, 0x00, 0x9E, 0xE1, 0x83, 0x0B, 0x4C, 0xC2, 0xFF, 0xA2, +0x50, 0x04, 0x4C, 0xC7, 0xFF, 0xA2, 0x51, 0x04, 0x4C, 0xC7, 0xFF, 0xA3, 0x09, 0xC9, 0xC8, 0x00, +0xB0, 0x13, 0xA9, 0x00, 0x00, 0xE2, 0x20, 0xA3, 0x09, 0xAA, 0xA3, 0x07, 0x9F, 0x00, 0x9D, 0xE1, +0xC2, 0x20, 0x4C, 0xC2, 0xFF, 0xA2, 0x52, 0x04, 0x4C, 0xC7, 0xFF, 0xA3, 0x07, 0xC9, 0xC8, 0x00, +0xB0, 0x13, 0xA9, 0x00, 0x00, 0xE2, 0x20, 0xA3, 0x07, 0xAA, 0xBF, 0x00, 0x9D, 0xE1, 0x83, 0x09, +0xC2, 0x20, 0x4C, 0xB7, 0xFF, 0xA2, 0x52, 0x04, 0x4C, 0xBC, 0xFF, 0xE2, 0x20, 0xA3, 0x07, 0xA2, +0xC8, 0x00, 0x9F, 0xFF, 0x9C, 0xE1, 0xCA, 0xD0, 0xF9, 0xC2, 0x30, 0x4C, 0xB7, 0xFF, 0x20, 0xB3, +0x0D, 0x22, 0xAF, 0x3E, 0xFE, 0xA3, 0x09, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xA2, 0xFE, 0x7C, +0x9D, 0x00, 0x20, 0xCA, 0xCA, 0x10, 0xF9, 0xAB, 0x7B, 0x22, 0x87, 0x3E, 0xFE, 0x4C, 0x60, 0xFF, +0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x08, 0x4C, 0x60, 0xFF, 0x20, 0xB3, 0x0D, 0xA5, 0x08, 0x83, +0x09, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x24, 0xA3, 0x0B, 0x85, 0x26, 0xF4, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x04, 0x67, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x27, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0xA2, 0x04, 0x67, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x18, 0xA0, 0x18, 0x00, +0x68, 0x97, 0x24, 0xC8, 0xC8, 0x68, 0x97, 0x24, 0xA0, 0x1C, 0x00, 0x68, 0x97, 0x24, 0xC8, 0xC8, +0x68, 0x97, 0x24, 0x80, 0x0F, 0xAA, 0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x24, +0xA3, 0x0B, 0x85, 0x26, 0xA0, 0xA8, 0x00, 0xBB, 0xBF, 0x79, 0x0C, 0xFE, 0x97, 0x24, 0x88, 0x88, +0xC0, 0x20, 0x00, 0x10, 0xF2, 0x24, 0x07, 0x10, 0x10, 0xA0, 0x16, 0x00, 0xBB, 0xBF, 0x23, 0x0D, +0xFE, 0x97, 0x24, 0x88, 0x88, 0x10, 0xF5, 0x80, 0x0E, 0xA0, 0x16, 0x00, 0xBB, 0xBF, 0x79, 0x0C, +0xFE, 0x97, 0x24, 0x88, 0x88, 0x10, 0xF5, 0xF4, 0xFE, 0x00, 0xF4, 0xF5, 0x0D, 0xA0, 0x1A, 0x00, +0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, 0x48, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xB0, +0x30, 0xA0, 0x1E, 0x00, 0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, 0x48, 0xA5, 0x24, 0x18, 0x69, +0x08, 0x00, 0xD4, 0x26, 0x48, 0xA2, 0x04, 0x6C, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x13, 0xA2, 0x00, +0x01, 0xA0, 0x74, 0x00, 0xB5, 0x4E, 0x97, 0x24, 0xC8, 0xC8, 0xB5, 0x50, 0x97, 0x24, 0x4C, 0x6B, +0xFF, 0xAA, 0x4C, 0x6E, 0xFF, 0x0B, 0x3B, 0x5B, 0xA0, 0x1A, 0x00, 0x20, 0xCF, 0x13, 0xB0, 0x0B, +0xA0, 0x1E, 0x00, 0x20, 0xCF, 0x13, 0xB0, 0x03, 0x4C, 0xC3, 0xFF, 0xAA, 0x4C, 0xC6, 0xFF, 0xB7, +0x09, 0x48, 0x88, 0x88, 0xB7, 0x09, 0x48, 0xA2, 0x04, 0x68, 0x22, 0x00, 0x00, 0xE1, 0x60, 0x20, +0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x24, 0xA3, 0x0A, 0x85, 0x25, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, +0xA5, 0x24, 0x83, 0x09, 0xA5, 0x26, 0x29, 0xFF, 0x00, 0x83, 0x0B, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, +0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xA3, 0x0A, 0x85, 0x2B, 0xA0, 0x0E, 0x00, 0xB7, 0x2A, 0x97, 0x24, +0x88, 0x88, 0x10, 0xF8, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xA3, 0x0A, +0x85, 0x2B, 0xA0, 0x0E, 0x00, 0xB7, 0x24, 0x97, 0x2A, 0x88, 0x88, 0x10, 0xF8, 0x4C, 0x6B, 0xFF, +0x20, 0xB3, 0x0D, 0x8B, 0xA3, 0x0A, 0xAA, 0xA3, 0x0B, 0x48, 0xAB, 0xAB, 0xA0, 0x10, 0x00, 0xBD, +0x00, 0x00, 0x97, 0x24, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x18, 0x00, 0x90, 0xF2, 0xAB, 0x4C, 0x6B, +0xFF, 0x20, 0xB3, 0x0D, 0x8B, 0xA3, 0x0A, 0xAA, 0xA3, 0x0B, 0x48, 0xAB, 0xAB, 0xA0, 0x10, 0x00, +0xB7, 0x24, 0x9D, 0x00, 0x00, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x18, 0x00, 0x90, 0xF2, 0xAB, 0x4C, +0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x3C, 0x1E, 0xE0, 0xA3, 0x09, 0x18, 0x65, 0x1C, 0x85, 0x20, +0xA3, 0x0B, 0x18, 0x65, 0x1E, 0x85, 0x22, 0x22, 0xAF, 0x18, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, +0x0D, 0x22, 0x3C, 0x1E, 0xE0, 0xA5, 0x20, 0x38, 0xE5, 0x1C, 0x18, 0x63, 0x09, 0x85, 0x20, 0xA3, +0x09, 0x85, 0x1C, 0xA5, 0x22, 0x38, 0xE5, 0x1E, 0x18, 0x63, 0x0B, 0x85, 0x22, 0xA3, 0x0B, 0x85, +0x1E, 0x22, 0xAF, 0x18, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x3C, 0x1E, 0xE0, 0xA3, +0x09, 0x38, 0xE5, 0x1C, 0xA8, 0x18, 0x65, 0x14, 0x85, 0x14, 0x98, 0x18, 0x65, 0x18, 0x85, 0x18, +0x98, 0x18, 0x65, 0x1C, 0x85, 0x1C, 0x98, 0x18, 0x65, 0x20, 0x85, 0x20, 0xBB, 0xA3, 0x0B, 0x38, +0xE5, 0x1E, 0xA8, 0x18, 0x65, 0x16, 0x85, 0x16, 0x98, 0x18, 0x65, 0x1A, 0x85, 0x1A, 0x98, 0x18, +0x65, 0x1E, 0x85, 0x1E, 0x98, 0x18, 0x65, 0x22, 0x85, 0x22, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0x5A, 0xDA, 0xA0, 0x1C, 0x00, 0xB7, 0x24, 0x83, 0x05, 0xC8, 0xC8, 0xB7, 0x24, 0x83, 0x07, 0xA2, +0x04, 0x6F, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x07, 0x22, 0xAF, 0x18, 0xFE, 0x4C, 0x6B, 0xFF, 0xAA, +0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xAA, 0xA3, 0x0B, 0x48, 0xDA, 0xA0, 0x1A, 0x00, +0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, 0x48, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xAA, +0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA0, 0x1A, 0x00, 0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, +0x48, 0xA3, 0x0D, 0xAA, 0xA3, 0x0F, 0x48, 0xDA, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xAA, +0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA0, 0x1A, 0x00, 0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, +0x48, 0xA3, 0x0D, 0xAA, 0xA3, 0x0F, 0x48, 0xDA, 0xA2, 0x04, 0x6C, 0x22, 0x00, 0x00, 0xE1, 0xAA, +0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xAA, 0xA3, 0x0B, 0x48, 0xDA, 0xA0, 0x1E, 0x00, +0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, 0x48, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xAA, +0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA0, 0x1E, 0x00, 0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, +0x48, 0xA3, 0x0D, 0xAA, 0xA3, 0x0F, 0x48, 0xDA, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xAA, +0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0xA0, 0x72, 0x00, 0xB7, 0x24, 0x3A, 0x97, 0x24, 0x4C, 0x3F, +0xFF, 0x20, 0xB3, 0x0D, 0xA0, 0x72, 0x00, 0xB7, 0x24, 0x1A, 0x97, 0x24, 0x4C, 0x3F, 0xFF, 0x20, +0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xA3, 0x0A, 0x85, 0x2B, 0xA0, 0x40, 0x00, 0xB7, 0x24, 0x87, +0x2A, 0xC8, 0xC8, 0xB7, 0x24, 0xA0, 0x02, 0x00, 0x97, 0x2A, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, +0xA3, 0x09, 0xAA, 0xA3, 0x0A, 0x8B, 0x48, 0xAB, 0xAB, 0xA0, 0x40, 0x00, 0xB7, 0x24, 0x9D, 0x00, +0x00, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x72, 0x00, 0x90, 0xF2, 0xAB, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, +0x0D, 0xA3, 0x09, 0xAA, 0xA3, 0x0A, 0x8B, 0x48, 0xAB, 0xAB, 0xA0, 0x40, 0x00, 0xBD, 0x00, 0x00, +0x97, 0x24, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x72, 0x00, 0x90, 0xF2, 0xAB, 0x4C, 0x6B, 0xFF, 0x20, +0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, 0x22, 0x3A, 0x19, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, +0x22, 0x4C, 0x1E, 0xE0, 0x22, 0xD8, 0x18, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, +0xAA, 0xA7, 0x24, 0x20, 0xC9, 0x16, 0x22, 0x3A, 0x19, 0xFE, 0x4C, 0x60, 0xFF, 0x20, 0xB3, 0x0D, +0x22, 0xB7, 0x19, 0xFE, 0x22, 0xEF, 0x19, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x5C, +0x1E, 0xE0, 0x22, 0xD3, 0x19, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, +0x22, 0x4E, 0x19, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x50, 0x1E, 0xE0, 0x22, 0xD8, +0x18, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xAA, 0xA7, 0x24, 0x20, 0xC9, 0x16, +0x22, 0x4E, 0x19, 0xFE, 0x4C, 0x60, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0xAA, 0xA5, 0x08, 0x20, +0xC9, 0x16, 0x22, 0xD8, 0x18, 0xFE, 0x4C, 0x76, 0xFF, 0x20, 0xD9, 0x16, 0xA2, 0x00, 0x01, 0x95, +0x0E, 0xE8, 0xE8, 0xE0, 0x20, 0x01, 0x90, 0xF7, 0x60, 0x29, 0x80, 0x00, 0xF0, 0x0B, 0x8A, 0x29, +0x03, 0x00, 0x0A, 0xAA, 0xBF, 0xF4, 0x16, 0xFE, 0x60, 0x8A, 0x29, 0x0F, 0x00, 0x0A, 0xAA, 0xBF, +0xFC, 0x16, 0xFE, 0x60, 0x00, 0x00, 0x55, 0x55, 0xAA, 0xAA, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x11, +0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x99, 0x99, +0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, +0x09, 0xA0, 0x44, 0x00, 0x97, 0x24, 0xA3, 0x0B, 0xC8, 0xC8, 0x97, 0x24, 0x4C, 0x6B, 0xFF, 0x20, +0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xA3, 0x0A, 0x85, 0x2B, 0xA0, 0x44, 0x00, 0xB7, 0x24, 0x87, +0x2A, 0xC8, 0xC8, 0xB7, 0x24, 0xA0, 0x02, 0x00, 0x97, 0x2A, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, +0xA2, 0x00, 0x00, 0xA0, 0x44, 0x00, 0xBF, 0xBD, 0x0C, 0xFE, 0x97, 0x24, 0xE8, 0xE8, 0xC8, 0xC8, +0xC0, 0x72, 0x00, 0x90, 0xF1, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xA0, 0x40, 0x00, +0x97, 0x24, 0xA3, 0x0B, 0xC8, 0xC8, 0x97, 0x24, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, +0xA0, 0x40, 0x00, 0x18, 0x77, 0x24, 0x97, 0x24, 0xA3, 0x0B, 0xC8, 0xC8, 0x18, 0x77, 0x24, 0x97, +0x24, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xA0, 0x74, 0x00, 0x97, 0x24, 0xA3, 0x0B, +0xC8, 0xC8, 0x97, 0x24, 0xA0, 0x78, 0x00, 0xA9, 0x00, 0x00, 0x97, 0x24, 0xC8, 0xC8, 0x97, 0x24, +0x4C, 0x6B, 0xFF, 0xA0, 0x48, 0x00, 0x80, 0x21, 0xA0, 0x7E, 0x00, 0x80, 0x1C, 0xA0, 0x7C, 0x00, +0x80, 0x17, 0xA0, 0x80, 0x00, 0x80, 0x12, 0xA0, 0x82, 0x00, 0x80, 0x0D, 0xA0, 0x8C, 0x00, 0x80, +0x08, 0xA0, 0x8E, 0x00, 0x80, 0x03, 0xA0, 0xA0, 0x00, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x97, 0x24, +0x4C, 0x60, 0xFF, 0xA0, 0x84, 0x00, 0x80, 0x30, 0xA0, 0x88, 0x00, 0x80, 0x2B, 0xA0, 0x90, 0x00, +0x80, 0x26, 0xA0, 0x94, 0x00, 0x80, 0x21, 0xA0, 0x98, 0x00, 0x80, 0x1C, 0xA0, 0x9C, 0x00, 0x80, +0x17, 0xA0, 0xA2, 0x00, 0x80, 0x12, 0xA0, 0xA6, 0x00, 0x80, 0x0D, 0xA0, 0x18, 0x00, 0x80, 0x08, +0xA0, 0x1C, 0x00, 0x80, 0x03, 0xA0, 0x78, 0x00, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x97, 0x24, 0xA3, +0x0B, 0xC8, 0xC8, 0x97, 0x24, 0x4C, 0x6B, 0xFF, 0xA0, 0x48, 0x00, 0x80, 0x21, 0xA0, 0x7E, 0x00, +0x80, 0x1C, 0xA0, 0x7C, 0x00, 0x80, 0x17, 0xA0, 0x80, 0x00, 0x80, 0x12, 0xA0, 0x82, 0x00, 0x80, +0x0D, 0xA0, 0x8C, 0x00, 0x80, 0x08, 0xA0, 0x8E, 0x00, 0x80, 0x03, 0xA0, 0xA0, 0x00, 0x20, 0xB3, +0x0D, 0xB7, 0x24, 0x83, 0x09, 0x4C, 0x3F, 0xFF, 0xA0, 0x74, 0x00, 0x80, 0x35, 0xA0, 0x78, 0x00, +0x80, 0x30, 0xA0, 0x84, 0x00, 0x80, 0x2B, 0xA0, 0x88, 0x00, 0x80, 0x26, 0xA0, 0x90, 0x00, 0x80, +0x21, 0xA0, 0x94, 0x00, 0x80, 0x1C, 0xA0, 0x98, 0x00, 0x80, 0x17, 0xA0, 0x9C, 0x00, 0x80, 0x12, +0xA0, 0xA2, 0x00, 0x80, 0x0D, 0xA0, 0xA6, 0x00, 0x80, 0x08, 0xA0, 0x18, 0x00, 0x80, 0x03, 0xA0, +0x1C, 0x00, 0x20, 0xB3, 0x0D, 0xB7, 0x24, 0x83, 0x09, 0xC8, 0xC8, 0xB7, 0x24, 0x83, 0x0B, 0x4C, +0x3F, 0xFF, 0xA0, 0x16, 0x00, 0xBB, 0xB7, 0x24, 0x95, 0x0C, 0x88, 0x88, 0x10, 0xF7, 0x6B, 0xA0, +0x16, 0x00, 0xBB, 0xB5, 0x0C, 0x97, 0x24, 0x88, 0x88, 0x10, 0xF7, 0x6B, 0xA3, 0x0C, 0x85, 0x2A, +0xA3, 0x0D, 0x85, 0x2B, 0xA0, 0x00, 0x00, 0xA2, 0x00, 0x01, 0xB7, 0x2A, 0x95, 0x0E, 0xE8, 0xE8, +0xC8, 0xC8, 0xC0, 0x20, 0x00, 0x90, 0xF3, 0x6B, 0xA3, 0x0C, 0x85, 0x2A, 0xA3, 0x0D, 0x85, 0x2B, +0xA0, 0x00, 0x00, 0xA2, 0x00, 0x01, 0xB5, 0x0E, 0x97, 0x2A, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x20, +0x00, 0x90, 0xF3, 0x6B, 0x22, 0x4C, 0x1E, 0xE0, 0xA5, 0x16, 0x29, 0x07, 0x00, 0xA8, 0x22, 0x54, +0x1E, 0xE0, 0x6B, 0x22, 0x50, 0x1E, 0xE0, 0xA5, 0x16, 0x29, 0x07, 0x00, 0xA8, 0x22, 0x54, 0x1E, +0xE0, 0x6B, 0xA2, 0x00, 0x01, 0xA0, 0x4A, 0x00, 0xB7, 0x24, 0x95, 0x0E, 0xC8, 0xC8, 0xE8, 0xE8, +0xE0, 0x20, 0x01, 0x90, 0xF3, 0x6B, 0xA2, 0x00, 0x01, 0xA0, 0x20, 0x00, 0xB7, 0x24, 0x95, 0x0E, +0xC8, 0xC8, 0xE8, 0xE8, 0xE0, 0x20, 0x01, 0x90, 0xF3, 0x6B, 0xA2, 0x00, 0x01, 0xA0, 0x4A, 0x00, +0xB5, 0x0E, 0x97, 0x24, 0xC8, 0xC8, 0xE8, 0xE8, 0xE0, 0x20, 0x01, 0x90, 0xF3, 0x6B, 0xA2, 0x00, +0x01, 0xA0, 0x20, 0x00, 0xB5, 0x0E, 0x97, 0x24, 0xC8, 0xC8, 0xE8, 0xE8, 0xE0, 0x20, 0x01, 0x90, +0xF3, 0x6B, 0x98, 0xC9, 0x00, 0x00, 0xF0, 0x24, 0x0A, 0x24, 0x0B, 0x30, 0x20, 0x0A, 0x85, 0x42, +0xA2, 0x00, 0x01, 0xB5, 0x10, 0xA8, 0xB5, 0x0E, 0xDA, 0x22, 0x68, 0x1E, 0xE0, 0xFA, 0x95, 0x0E, +0x98, 0x95, 0x10, 0xE8, 0xE8, 0xE8, 0xE8, 0xE0, 0x20, 0x01, 0x90, 0xE7, 0x6B, 0x85, 0x42, 0xA2, +0x00, 0x01, 0xB5, 0x0E, 0xA8, 0xDA, 0x22, 0x68, 0x1E, 0xE0, 0xFA, 0x95, 0x0E, 0xE8, 0xE8, 0xE0, +0x10, 0x01, 0x90, 0xEE, 0x6B, 0x22, 0x5C, 0x1E, 0xE0, 0x22, 0x60, 0x1E, 0xE0, 0xA5, 0x16, 0x29, +0x07, 0x00, 0x22, 0x64, 0x1E, 0xE0, 0x6B, 0xA3, 0x0C, 0x85, 0x2A, 0xA3, 0x0D, 0x85, 0x2B, 0xA0, +0x00, 0x00, 0xA2, 0x00, 0x01, 0xB7, 0x2A, 0x95, 0x2E, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x08, 0x00, +0x90, 0xF3, 0x6B, 0xA3, 0x0C, 0x85, 0x2A, 0xA3, 0x0D, 0x85, 0x2B, 0xA0, 0x00, 0x00, 0xA2, 0x00, +0x01, 0xB5, 0x2E, 0x97, 0x2A, 0xE8, 0xE8, 0xC8, 0xC8, 0xC0, 0x08, 0x00, 0x90, 0xF3, 0x6B, 0xA2, +0x00, 0x01, 0xA0, 0x6A, 0x00, 0xB5, 0x2E, 0x97, 0x24, 0xC8, 0xC8, 0xE8, 0xE8, 0xE0, 0x08, 0x01, +0x90, 0xF3, 0x6B, 0xA2, 0x00, 0x01, 0xA0, 0x6A, 0x00, 0xB7, 0x24, 0x95, 0x2E, 0xC8, 0xC8, 0xE8, +0xE8, 0xE0, 0x08, 0x01, 0x90, 0xF3, 0x6B, 0x24, 0x0B, 0x10, 0x03, 0x4C, 0x52, 0x1A, 0x0B, 0x7B, +0x18, 0x69, 0x00, 0x01, 0x5B, 0xA2, 0x07, 0x00, 0xB5, 0x2E, 0x20, 0x32, 0x1A, 0xCA, 0x10, 0xF8, +0x2B, 0x6B, 0xDA, 0xA8, 0x8A, 0x0A, 0x0A, 0x48, 0x98, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, +0x3D, 0x4C, 0xFE, 0xA8, 0xBF, 0x3B, 0x4C, 0xFE, 0xFA, 0x95, 0x2E, 0xE8, 0xE8, 0x98, 0x95, 0x2E, +0xFA, 0x60, 0x0B, 0x7B, 0x18, 0x69, 0x00, 0x01, 0x5B, 0xA2, 0x07, 0x00, 0xB5, 0x2E, 0x20, 0x66, +0x1A, 0xCA, 0x10, 0xF8, 0x2B, 0x6B, 0xDA, 0xA8, 0x8A, 0x0A, 0x48, 0x98, 0x29, 0xFF, 0x00, 0x0A, +0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0xFA, 0x95, 0x2E, 0xFA, 0x60, 0xC9, 0x00, 0x00, 0xF0, 0x24, 0x0A, +0x24, 0x0B, 0x30, 0x20, 0x0A, 0x85, 0x42, 0xA2, 0x00, 0x01, 0xB5, 0x30, 0xA8, 0xB5, 0x2E, 0xDA, +0x22, 0x68, 0x1E, 0xE0, 0xFA, 0x95, 0x2E, 0x98, 0x95, 0x30, 0xE8, 0xE8, 0xE8, 0xE8, 0xE0, 0x20, +0x01, 0x90, 0xE7, 0x6B, 0x85, 0x42, 0xA2, 0x00, 0x01, 0xB5, 0x2E, 0xA8, 0xDA, 0x22, 0x68, 0x1E, +0xE0, 0xFA, 0x95, 0x2E, 0xE8, 0xE8, 0xE0, 0x10, 0x01, 0x90, 0xEE, 0x6B, 0xEB, 0x85, 0x2A, 0x98, +0xEB, 0x85, 0x2C, 0xA6, 0x42, 0xF0, 0x0A, 0xA5, 0x2C, 0x0A, 0x26, 0x2A, 0x26, 0x2C, 0xCA, 0xD0, +0xF6, 0xA5, 0x2C, 0xEB, 0xA8, 0xA5, 0x2A, 0xEB, 0x6B, 0x3B, 0x0B, 0x5B, 0xA5, 0x0B, 0x87, 0x0F, +0xA0, 0x02, 0x00, 0xA5, 0x0D, 0x97, 0x0F, 0xC8, 0xC8, 0xA5, 0x07, 0x97, 0x0F, 0xC8, 0xC8, 0xA5, +0x09, 0x97, 0x0F, 0x4C, 0xA2, 0xFF, 0x3B, 0x0B, 0x5B, 0xA0, 0x06, 0x00, 0xB7, 0x0B, 0x18, 0x65, +0x09, 0x97, 0x0B, 0x88, 0x88, 0xB7, 0x0B, 0x18, 0x65, 0x07, 0x97, 0x0B, 0x88, 0x88, 0x10, 0xEC, +0x4C, 0xD9, 0xFF, 0x3B, 0x0B, 0x5B, 0xA7, 0x0B, 0x18, 0x65, 0x07, 0x87, 0x0B, 0xA0, 0x02, 0x00, +0xB7, 0x0B, 0x18, 0x65, 0x09, 0x97, 0x0B, 0xC8, 0xC8, 0xB7, 0x0B, 0x38, 0xE5, 0x07, 0x97, 0x0B, +0xC8, 0xC8, 0xB7, 0x0B, 0x38, 0xE5, 0x09, 0x97, 0x0B, 0x4C, 0xD9, 0xFF, 0x3B, 0x0B, 0x5B, 0xA0, +0x02, 0x00, 0xB7, 0x0F, 0xD7, 0x0B, 0x10, 0x02, 0xB7, 0x0B, 0x97, 0x07, 0x88, 0x88, 0x10, 0xF2, +0xA0, 0x06, 0x00, 0xB7, 0x0F, 0xD7, 0x0B, 0x30, 0x02, 0xB7, 0x0B, 0x97, 0x07, 0x88, 0x88, 0xC0, +0x03, 0x00, 0x10, 0xEF, 0xA0, 0x04, 0x00, 0xA7, 0x07, 0xD7, 0x07, 0x10, 0x13, 0x88, 0x88, 0xB7, +0x07, 0xA0, 0x06, 0x00, 0xD7, 0x07, 0x10, 0x08, 0xA9, 0xFF, 0xFF, 0x85, 0x13, 0x4C, 0xA2, 0xFF, +0xA9, 0x00, 0x00, 0xA0, 0x06, 0x00, 0x97, 0x07, 0x88, 0x88, 0x10, 0xFA, 0x80, 0xED, 0x3B, 0x0B, +0x5B, 0xA0, 0x02, 0x00, 0xB7, 0x0F, 0xD7, 0x0B, 0x30, 0x02, 0xB7, 0x0B, 0x97, 0x07, 0x88, 0x88, +0x10, 0xF2, 0xA0, 0x06, 0x00, 0xB7, 0x0F, 0xD7, 0x0B, 0x10, 0x02, 0xB7, 0x0B, 0x97, 0x07, 0x88, +0x88, 0xC0, 0x03, 0x00, 0x10, 0xEF, 0x4C, 0xA2, 0xFF, 0x3B, 0x0B, 0x5B, 0xA7, 0x0B, 0xC7, 0x07, +0x30, 0x1E, 0xA0, 0x04, 0x00, 0xD7, 0x07, 0x10, 0x17, 0x88, 0x88, 0xB7, 0x0B, 0xD7, 0x07, 0x30, +0x0F, 0xA0, 0x06, 0x00, 0xD7, 0x07, 0x10, 0x08, 0xA9, 0xFF, 0xFF, 0x85, 0x0F, 0x4C, 0xD9, 0xFF, +0xA9, 0x00, 0x00, 0x80, 0xF6, 0x3B, 0x0B, 0x5B, 0xA7, 0x0F, 0x87, 0x07, 0xA0, 0x02, 0x00, 0xB7, +0x0F, 0x97, 0x07, 0xB7, 0x0B, 0xA0, 0x06, 0x00, 0x97, 0x07, 0xA7, 0x0B, 0x88, 0x88, 0x97, 0x07, +0x4C, 0xA2, 0xFF, 0x3B, 0x0B, 0x5B, 0xA0, 0x06, 0x00, 0xB7, 0x07, 0xD7, 0x0B, 0xD0, 0x0C, 0x88, +0x88, 0x10, 0xF6, 0xA9, 0xFF, 0xFF, 0x85, 0x0F, 0x4C, 0xD9, 0xFF, 0xA9, 0x00, 0x00, 0x80, 0xF6, +0x3B, 0x0B, 0x5B, 0xA0, 0x00, 0x00, 0xB7, 0x07, 0xC8, 0xC8, 0xC8, 0xC8, 0xD7, 0x07, 0x10, 0x0F, +0x88, 0x88, 0xC0, 0x04, 0x00, 0x90, 0xEF, 0xA9, 0xFF, 0xFF, 0x85, 0x0B, 0x4C, 0xC3, 0xFF, 0xA9, +0x00, 0x00, 0x80, 0xF6, 0x20, 0xB3, 0x0D, 0x7B, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x48, 0x48, 0xA5, +0x00, 0x48, 0xF4, 0xA7, 0x41, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x48, 0x48, 0xA5, 0x02, +0x48, 0xF4, 0xA7, 0x41, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x01, 0x18, 0x63, 0x07, +0x83, 0x01, 0xA3, 0x03, 0x69, 0x00, 0x00, 0x83, 0x03, 0xA3, 0x01, 0x18, 0x63, 0x01, 0xA3, 0x03, +0x63, 0x03, 0xAA, 0xA3, 0x05, 0x38, 0xE9, 0xFF, 0xFF, 0x85, 0x00, 0xA9, 0x00, 0x00, 0xE9, 0xFF, +0x7F, 0x85, 0x02, 0xA3, 0x01, 0x29, 0xFF, 0x7F, 0x18, 0x65, 0x02, 0x85, 0x02, 0x8A, 0x18, 0x65, +0x00, 0x85, 0x00, 0xA5, 0x02, 0x10, 0x0F, 0xA5, 0x00, 0x18, 0x69, 0xFF, 0xFF, 0x85, 0x00, 0xA5, +0x02, 0x69, 0xFF, 0x7F, 0x85, 0x02, 0xA5, 0x00, 0xC9, 0x00, 0x80, 0xD0, 0x03, 0xA9, 0x00, 0x00, +0xFA, 0xFA, 0xFA, 0xFA, 0x83, 0x09, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, 0x0D, 0xA2, 0x00, 0x01, 0xA3, +0x09, 0x95, 0x00, 0xA3, 0x0B, 0x95, 0x02, 0x4C, 0x6B, 0xFF, 0x3B, 0x0B, 0x5B, 0xA0, 0x02, 0x00, +0xB7, 0x0B, 0x18, 0x77, 0x07, 0x97, 0x07, 0x88, 0x88, 0x10, 0xF5, 0x4C, 0xD9, 0xFF, 0x3B, 0x0B, +0x5B, 0xA0, 0x02, 0x00, 0xB7, 0x07, 0x38, 0xF7, 0x0B, 0x97, 0x07, 0x88, 0x88, 0x10, 0xF5, 0x4C, +0xD9, 0xFF, 0x3B, 0x0B, 0x5B, 0xA5, 0x07, 0x87, 0x0B, 0xA0, 0x02, 0x00, 0xA5, 0x09, 0x97, 0x0B, +0x4C, 0xD9, 0xFF, 0x3B, 0x0B, 0x5B, 0xA0, 0x02, 0x00, 0xB7, 0x07, 0xD7, 0x0B, 0xD0, 0x0C, 0x88, +0x88, 0x10, 0xF6, 0xA9, 0xFF, 0xFF, 0x85, 0x0F, 0x4C, 0xD9, 0xFF, 0xA9, 0x00, 0x00, 0x80, 0xF6, +0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xAA, 0xA3, 0x0A, 0x8B, 0x48, 0xAB, 0xAB, 0xBD, 0x00, 0x00, 0x38, +0xA0, 0x08, 0x00, 0xF7, 0x24, 0x9D, 0x00, 0x00, 0xBD, 0x02, 0x00, 0x38, 0xC8, 0xC8, 0xF7, 0x24, +0x9D, 0x02, 0x00, 0xAB, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xAA, 0xA3, 0x0A, 0x8B, +0x48, 0xAB, 0xAB, 0xBD, 0x00, 0x00, 0x18, 0xA0, 0x08, 0x00, 0x77, 0x24, 0x9D, 0x00, 0x00, 0xBD, +0x02, 0x00, 0x18, 0xC8, 0xC8, 0x77, 0x24, 0x9D, 0x02, 0x00, 0xAB, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, +0x0D, 0x22, 0x3C, 0x1E, 0xE0, 0x48, 0x48, 0xA3, 0x0D, 0x38, 0xE5, 0x14, 0x48, 0xA5, 0x12, 0x48, +0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x0F, 0x38, 0xE5, 0x16, 0x4A, 0x24, 0x0B, 0x10, +0x01, 0x4A, 0x18, 0x63, 0x01, 0xA8, 0x68, 0x68, 0xA3, 0x0B, 0x38, 0xE5, 0x16, 0x24, 0x0B, 0x30, +0x09, 0x29, 0x01, 0x00, 0x49, 0x01, 0x00, 0x0A, 0x80, 0x06, 0x29, 0x03, 0x00, 0x49, 0x03, 0x00, +0xAA, 0xB7, 0x0E, 0xE0, 0x00, 0x00, 0xF0, 0x05, 0x4A, 0x4A, 0xCA, 0x80, 0xF6, 0x24, 0x0B, 0x10, +0x05, 0x29, 0x03, 0x00, 0x80, 0x03, 0x29, 0x0F, 0x00, 0x83, 0x0D, 0x4C, 0x6B, 0xFF, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0x0B, 0x3B, 0x5B, 0xA9, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, +0xA0, 0x04, 0x00, 0xB7, 0x0D, 0x38, 0xE7, 0x0D, 0x10, 0x06, 0x49, 0xFF, 0xFF, 0x1A, 0xE6, 0x05, +0x48, 0xA7, 0x15, 0x10, 0x06, 0x49, 0xFF, 0xFF, 0x1A, 0xE6, 0x05, 0x48, 0xA2, 0x0B, 0x09, 0x22, +0x00, 0x00, 0xE1, 0xA0, 0x04, 0x00, 0xB7, 0x11, 0x38, 0xE7, 0x11, 0x10, 0x06, 0x49, 0xFF, 0xFF, +0x1A, 0xE6, 0x05, 0xF4, 0x00, 0x00, 0x48, 0xA2, 0x0B, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xFA, +0xFA, 0xFA, 0x46, 0x05, 0x90, 0x04, 0x49, 0xFF, 0xFF, 0x1A, 0x87, 0x15, 0xA5, 0x03, 0xD0, 0x37, +0xC6, 0x03, 0xA5, 0x15, 0xA6, 0x17, 0x1A, 0xD0, 0x01, 0xE8, 0x1A, 0xD0, 0x01, 0xE8, 0x85, 0x15, +0x86, 0x17, 0xA5, 0x11, 0xA6, 0x13, 0x1A, 0xD0, 0x01, 0xE8, 0x1A, 0xD0, 0x01, 0xE8, 0x85, 0x11, +0x86, 0x13, 0xA5, 0x0D, 0xA6, 0x0F, 0x1A, 0xD0, 0x01, 0xE8, 0x1A, 0xD0, 0x01, 0xE8, 0x85, 0x0D, +0x86, 0x0F, 0x64, 0x05, 0x4C, 0xE7, 0x1D, 0x2B, 0x68, 0x68, 0x4C, 0xA1, 0xFF, 0xA4, 0xC4, 0x98, +0x25, 0xC8, 0xAA, 0xA5, 0xA0, 0xC4, 0xC6, 0x90, 0x02, 0x25, 0xA2, 0x37, 0x4C, 0x35, 0xCE, 0x85, +0xC0, 0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x85, 0xC2, 0xA5, 0xC0, 0x35, 0xCA, 0x05, 0xC2, 0x91, 0xBC, +0x80, 0x24, 0x98, 0x25, 0xC8, 0xAA, 0xB5, 0xCE, 0x37, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x13, 0x49, +0xFF, 0xFF, 0x31, 0xBC, 0x85, 0xC2, 0xB7, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x05, 0xC2, 0x91, 0xBC, +0x80, 0x04, 0xB5, 0xCA, 0x91, 0xBC, 0xC8, 0xC8, 0xC4, 0xC6, 0x90, 0xD6, 0xD0, 0x1B, 0x98, 0x25, +0xC8, 0xAA, 0xB5, 0xCE, 0x25, 0xA2, 0x37, 0x4C, 0x85, 0xC0, 0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x85, +0xC2, 0xA5, 0xC0, 0x35, 0xCA, 0x05, 0xC2, 0x91, 0xBC, 0x6B, 0xA4, 0xC4, 0x98, 0x25, 0xC8, 0xAA, +0xA5, 0xA0, 0xC4, 0xC6, 0x90, 0x02, 0x25, 0xA2, 0x37, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x11, 0xBC, +0x91, 0xBC, 0x80, 0x0E, 0x98, 0x25, 0xC8, 0xAA, 0xB7, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x11, 0xBC, +0x91, 0xBC, 0xC8, 0xC8, 0xC4, 0xC6, 0x90, 0xEC, 0xD0, 0x10, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA2, +0x37, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x11, 0xBC, 0x91, 0xBC, 0x6B, 0xA4, 0xC4, 0x98, 0x25, 0xC8, +0xAA, 0xA5, 0xA0, 0xC4, 0xC6, 0x90, 0x02, 0x25, 0xA2, 0x37, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x51, +0xBC, 0x91, 0xBC, 0x80, 0x0E, 0x98, 0x25, 0xC8, 0xAA, 0xB7, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x51, +0xBC, 0x91, 0xBC, 0xC8, 0xC8, 0xC4, 0xC6, 0x90, 0xEC, 0xD0, 0x10, 0x98, 0x25, 0xC8, 0xAA, 0xA5, +0xA2, 0x37, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x51, 0xBC, 0x91, 0xBC, 0x6B, 0xA4, 0xC4, 0x98, 0x25, +0xC8, 0xAA, 0xA5, 0xA0, 0xC4, 0xC6, 0x90, 0x02, 0x25, 0xA2, 0x37, 0x4C, 0x35, 0xCE, 0x35, 0xCA, +0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x91, 0xBC, 0x80, 0x11, 0x98, 0x25, 0xC8, 0xAA, 0xB7, 0x4C, 0x35, +0xCE, 0x35, 0xCA, 0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x91, 0xBC, 0xC8, 0xC8, 0xC4, 0xC6, 0x90, 0xE9, +0xD0, 0x13, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA2, 0x37, 0x4C, 0x35, 0xCE, 0x35, 0xCA, 0x49, 0xFF, +0xFF, 0x31, 0xBC, 0x91, 0xBC, 0x6B, 0xA4, 0xC4, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA0, 0xC4, 0xC6, +0x90, 0x02, 0x25, 0xA2, 0x85, 0xC0, 0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x85, 0xC2, 0xA5, 0xC0, 0x35, +0xCA, 0x05, 0xC2, 0x91, 0xBC, 0x80, 0x08, 0x98, 0x25, 0xC8, 0xAA, 0xB5, 0xCA, 0x91, 0xBC, 0xC8, +0xC8, 0xC4, 0xC6, 0x90, 0xF2, 0xD0, 0x15, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA2, 0x49, 0xFF, 0xFF, +0x31, 0xBC, 0x85, 0xC2, 0xA5, 0xA2, 0x35, 0xCA, 0x05, 0xC2, 0x91, 0xBC, 0x6B, 0xA4, 0xC4, 0x98, +0x25, 0xC8, 0xAA, 0xA5, 0xA0, 0xC4, 0xC6, 0x90, 0x02, 0x25, 0xA2, 0x35, 0xCA, 0x11, 0xBC, 0x91, +0xBC, 0x80, 0x0A, 0x98, 0x25, 0xC8, 0xAA, 0xB5, 0xCA, 0x11, 0xBC, 0x91, 0xBC, 0xC8, 0xC8, 0xC4, +0xC6, 0x90, 0xF0, 0xD0, 0x0C, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA2, 0x35, 0xCA, 0x11, 0xBC, 0x91, +0xBC, 0x6B, 0xA4, 0xC4, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA0, 0xC4, 0xC6, 0x90, 0x02, 0x25, 0xA2, +0x35, 0xCA, 0x51, 0xBC, 0x91, 0xBC, 0x80, 0x0A, 0x98, 0x25, 0xC8, 0xAA, 0xB5, 0xCA, 0x51, 0xBC, +0x91, 0xBC, 0xC8, 0xC8, 0xC4, 0xC6, 0x90, 0xF0, 0xD0, 0x0C, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA2, +0x35, 0xCA, 0x51, 0xBC, 0x91, 0xBC, 0x6B, 0xA4, 0xC4, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA0, 0xC4, +0xC6, 0x90, 0x02, 0x25, 0xA2, 0x35, 0xCA, 0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x91, 0xBC, 0x80, 0x0D, +0x98, 0x25, 0xC8, 0xAA, 0xB5, 0xCA, 0x49, 0xFF, 0xFF, 0x31, 0xBC, 0x91, 0xBC, 0xC8, 0xC8, 0xC4, +0xC6, 0x90, 0xED, 0xD0, 0x0F, 0x98, 0x25, 0xC8, 0xAA, 0xA5, 0xA2, 0x35, 0xCA, 0x49, 0xFF, 0xFF, +0x31, 0xBC, 0x91, 0xBC, 0x6B, 0xA5, 0xB6, 0x29, 0x7F, 0x00, 0x0A, 0x0A, 0xAA, 0xA5, 0xA4, 0xD0, +0x22, 0xA0, 0x6A, 0x00, 0xB7, 0x24, 0xC9, 0xFF, 0xFF, 0xD0, 0x18, 0xC8, 0xC8, 0xC0, 0x72, 0x00, +0x90, 0xF2, 0xBF, 0xF4, 0x20, 0xFE, 0x8F, 0x00, 0x1E, 0xE0, 0xBF, 0xF6, 0x20, 0xFE, 0x8F, 0x02, +0x1E, 0xE0, 0x6B, 0xBF, 0xE4, 0x20, 0xFE, 0x8F, 0x00, 0x1E, 0xE0, 0xBF, 0xE6, 0x20, 0xFE, 0x8F, +0x02, 0x1E, 0xE0, 0x6B, 0x5C, 0x7D, 0x1E, 0xFE, 0x5C, 0xEA, 0x1E, 0xFE, 0x5C, 0x2B, 0x1F, 0xFE, +0x5C, 0x6C, 0x1F, 0xFE, 0x5C, 0xB6, 0x1F, 0xFE, 0x5C, 0xFD, 0x1F, 0xFE, 0x5C, 0x32, 0x20, 0xFE, +0x5C, 0x67, 0x20, 0xFE, 0x22, 0x3C, 0x1E, 0xE0, 0x22, 0x44, 0x1E, 0xE0, 0x22, 0x58, 0x1E, 0xE0, +0xA0, 0x48, 0x00, 0xB7, 0x24, 0x85, 0xB6, 0x6B, 0x24, 0x07, 0x30, 0x39, 0xA9, 0x02, 0x00, 0x85, +0xC8, 0xA5, 0xA8, 0x38, 0xE5, 0x16, 0xA8, 0x29, 0x03, 0x00, 0x0A, 0x0A, 0xAA, 0x98, 0x4A, 0x29, +0xFE, 0xFF, 0x85, 0xC4, 0xBF, 0x8B, 0x21, 0xFE, 0x85, 0xA0, 0xA5, 0xAC, 0x38, 0xE5, 0x16, 0x3A, +0xA8, 0x29, 0x03, 0x00, 0x0A, 0x0A, 0xAA, 0x98, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xC6, 0xBF, 0x9D, +0x21, 0xFE, 0x85, 0xA2, 0x6B, 0x64, 0xC8, 0xA5, 0xA8, 0x38, 0xE5, 0x16, 0xA8, 0x29, 0x07, 0x00, +0x0A, 0xAA, 0x98, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xC4, 0xBF, 0x8B, 0x21, 0xFE, 0x85, 0xA0, +0xA5, 0xAC, 0x38, 0xE5, 0x16, 0x3A, 0xA8, 0x29, 0x07, 0x00, 0x0A, 0xAA, 0x98, 0x4A, 0x4A, 0x29, +0xFE, 0xFF, 0x85, 0xC6, 0xBF, 0x9B, 0x21, 0xFE, 0x85, 0xA2, 0x6B, 0xFF, 0xFF, 0x3F, 0xFF, 0x0F, +0xFF, 0x03, 0xFF, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0xFC, +0x00, 0xFF, 0x00, 0xFF, 0xC0, 0xFF, 0xF0, 0xFF, 0xFC, 0xFF, 0xFF, 0x20, 0xC0, 0x23, 0x22, 0x3C, +0x1E, 0xE0, 0x22, 0xA0, 0x1E, 0xE0, 0x24, 0x39, 0x10, 0x0C, 0x20, 0xC9, 0x45, 0x20, 0x96, 0x43, +0x22, 0x94, 0x1E, 0xE0, 0x80, 0x04, 0x22, 0x90, 0x1E, 0xE0, 0xB0, 0x20, 0x24, 0x39, 0x70, 0x03, +0x20, 0x83, 0x3A, 0xA5, 0x38, 0x0A, 0xAA, 0xFC, 0xFC, 0x21, 0x85, 0xB6, 0x22, 0x58, 0x1E, 0xE0, +0x22, 0x98, 0x1E, 0xE0, 0x22, 0x39, 0x22, 0xFE, 0x22, 0x9C, 0x1E, 0xE0, 0x22, 0xA8, 0x1E, 0xE0, +0x24, 0x39, 0x10, 0x03, 0x20, 0xD4, 0x45, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0x06, 0x22, 0x06, 0x22, +0x10, 0x22, 0x18, 0x22, 0x2B, 0x22, 0x22, 0x44, 0x1E, 0xE0, 0xA0, 0x48, 0x00, 0xB7, 0x24, 0x60, +0x22, 0x48, 0x1E, 0xE0, 0xA9, 0x00, 0x00, 0x60, 0xA9, 0xFF, 0xFF, 0xA2, 0x00, 0x01, 0x95, 0x0E, +0xE8, 0xE8, 0xE0, 0x20, 0x01, 0x90, 0xF7, 0xA9, 0x02, 0x00, 0x60, 0xA5, 0x16, 0x29, 0x07, 0x00, +0xA8, 0x22, 0x54, 0x1E, 0xE0, 0xA9, 0x00, 0x00, 0x60, 0x24, 0x39, 0x30, 0x06, 0x70, 0x08, 0x5C, +0x78, 0x1E, 0xE0, 0x5C, 0x6B, 0x43, 0xFE, 0x5C, 0xC4, 0x1F, 0xE0, 0xA2, 0x00, 0x00, 0x80, 0x0D, +0xA2, 0x01, 0x00, 0x80, 0x08, 0xA2, 0x02, 0x00, 0x80, 0x03, 0xA2, 0x03, 0x00, 0x20, 0xB3, 0x0D, +0x86, 0x38, 0x20, 0x8C, 0x22, 0xA6, 0x38, 0x22, 0xA1, 0x22, 0xFE, 0xAA, 0x4C, 0x6E, 0xFF, 0x20, +0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, 0x83, 0x0B, 0x20, 0x8C, +0x22, 0xA2, 0x04, 0x00, 0x22, 0xA1, 0x22, 0xFE, 0xAA, 0x4C, 0x84, 0xFF, 0xA3, 0x0B, 0x85, 0x2A, +0xA3, 0x0C, 0x85, 0x2B, 0xA0, 0x06, 0x00, 0xBB, 0xB7, 0x2A, 0x95, 0xA6, 0x88, 0x88, 0x10, 0xF7, +0x60, 0x86, 0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x04, 0x5C, 0x0C, 0x1E, 0xE0, 0x8B, 0xA0, 0x08, 0x00, +0xB7, 0x2A, 0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, 0xA9, 0x30, 0x00, 0x85, 0x3A, 0x22, 0xF8, +0x1E, 0xE0, 0x90, 0x01, 0x6B, 0xA5, 0x38, 0xD0, 0x0C, 0x20, 0x21, 0x54, 0x90, 0x12, 0x22, 0x88, +0x1F, 0xE0, 0x90, 0x0C, 0x6B, 0x4C, 0xAB, 0x21, 0xA9, 0x30, 0x00, 0x85, 0x3A, 0x4C, 0xAB, 0x21, +0x20, 0xCE, 0x23, 0x20, 0xC0, 0x23, 0xA2, 0x06, 0x00, 0xB5, 0xA6, 0x95, 0xAE, 0xCA, 0xCA, 0x10, +0xF8, 0x22, 0x6C, 0x1E, 0xE0, 0x22, 0xA0, 0x1E, 0xE0, 0x22, 0x90, 0x1E, 0xE0, 0x90, 0x05, 0x22, +0xA8, 0x1E, 0xE0, 0x6B, 0x22, 0x98, 0x1E, 0xE0, 0xA2, 0x02, 0x00, 0xB5, 0xB2, 0x38, 0xF5, 0xAE, +0x4A, 0xD5, 0xB8, 0x90, 0x06, 0xCA, 0xCA, 0x10, 0xF2, 0x80, 0x06, 0x22, 0x74, 0x1E, 0xE0, 0x80, +0x51, 0xA5, 0xA6, 0x18, 0x65, 0xB8, 0x85, 0xAA, 0x22, 0x74, 0x1E, 0xE0, 0x20, 0x7F, 0x23, 0xA5, +0xAC, 0x38, 0xE5, 0xBA, 0x85, 0xA8, 0xA5, 0xA6, 0x18, 0x65, 0xB8, 0x85, 0xA6, 0x22, 0x74, 0x1E, +0xE0, 0x20, 0x7F, 0x23, 0xA5, 0xAA, 0x38, 0xE5, 0xB8, 0x85, 0xA6, 0xA5, 0xAC, 0x38, 0xE5, 0xBA, +0x85, 0xAC, 0x22, 0x74, 0x1E, 0xE0, 0x20, 0x7F, 0x23, 0xA5, 0xA8, 0x18, 0x65, 0xBA, 0x85, 0xAC, +0xA5, 0xA6, 0x18, 0x65, 0xB8, 0x85, 0xA6, 0xA5, 0xAA, 0x38, 0xE5, 0xB8, 0x85, 0xAA, 0x22, 0x74, +0x1E, 0xE0, 0x22, 0x9C, 0x1E, 0xE0, 0x22, 0xA8, 0x1E, 0xE0, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0xA2, +0x06, 0x00, 0xB5, 0xAE, 0x95, 0xA6, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0x22, 0x90, 0x1E, 0xE0, 0x20, +0x83, 0x3A, 0x90, 0x01, 0x6B, 0x8B, 0x22, 0xC0, 0x1E, 0xE0, 0x22, 0xE8, 0x1E, 0xE0, 0x22, 0x70, +0x1E, 0xE0, 0x20, 0xE6, 0x23, 0x20, 0x0E, 0x24, 0x22, 0xCC, 0x1E, 0xE0, 0x22, 0x00, 0x1E, 0xE0, +0xA5, 0x40, 0x1A, 0xC5, 0xAA, 0x10, 0x07, 0x85, 0x40, 0x20, 0x41, 0x24, 0x80, 0xE7, 0xAB, 0x6B, +0xA0, 0x72, 0x00, 0xB7, 0x24, 0x30, 0x01, 0x60, 0x68, 0x18, 0xA9, 0x00, 0x00, 0x6B, 0xA0, 0x44, +0x00, 0xB7, 0x24, 0xF0, 0x0B, 0x85, 0xB8, 0xC8, 0xC8, 0xB7, 0x24, 0xF0, 0x03, 0x85, 0xBA, 0x60, +0x68, 0x18, 0xA9, 0x00, 0x00, 0x6B, 0xA5, 0xA6, 0x85, 0x40, 0x38, 0xE5, 0x14, 0x48, 0x48, 0x48, +0xD4, 0x12, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x18, 0x65, 0x0E, 0x85, 0xBC, 0x68, +0x65, 0x10, 0x29, 0xFF, 0x00, 0x85, 0xBE, 0x8B, 0xA5, 0xBD, 0x83, 0x00, 0xAB, 0x60, 0xA5, 0x40, +0x29, 0x07, 0x00, 0x0A, 0x24, 0x0B, 0x30, 0x01, 0x0A, 0x18, 0x69, 0x00, 0x01, 0xAA, 0xB5, 0x0E, +0x85, 0xCA, 0xB5, 0x10, 0x85, 0xCC, 0xB5, 0x2E, 0x85, 0xCE, 0xB5, 0x30, 0x85, 0xD0, 0xA5, 0xB6, +0x10, 0x0E, 0xA5, 0xCA, 0x49, 0xFF, 0xFF, 0x85, 0xCA, 0xA5, 0xCC, 0x49, 0xFF, 0xFF, 0x85, 0xCC, +0x60, 0xA5, 0xBC, 0x18, 0x65, 0x12, 0x85, 0xBC, 0xB0, 0x01, 0x60, 0xE6, 0xBE, 0x8B, 0xA5, 0xBD, +0x83, 0x00, 0xAB, 0x60, 0x20, 0xB3, 0x0D, 0x20, 0x89, 0x26, 0xA3, 0x09, 0x85, 0xAA, 0x85, 0xB2, +0xA3, 0x0B, 0x85, 0xAC, 0x85, 0xB4, 0x20, 0x9B, 0x26, 0x22, 0x8B, 0x24, 0xFE, 0xAA, 0x4C, 0x6E, +0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x89, 0x26, 0xA5, 0xA6, 0x18, 0x63, 0x09, 0x85, 0xAA, 0x85, 0xB2, +0xA5, 0xA8, 0x18, 0x63, 0x0B, 0x85, 0xAC, 0x85, 0xB4, 0x80, 0xDB, 0x20, 0xC5, 0x0D, 0xB0, 0x04, +0x5C, 0x08, 0x1E, 0xE0, 0x8B, 0xA0, 0x04, 0x00, 0xB7, 0x2A, 0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, +0x6B, 0xA9, 0x20, 0x00, 0x22, 0xF8, 0x1E, 0xE0, 0x90, 0x01, 0x6B, 0x22, 0xFC, 0x1E, 0xE0, 0x90, +0x01, 0x6B, 0x20, 0x21, 0x54, 0x90, 0x07, 0x22, 0x80, 0x1F, 0xE0, 0x90, 0x01, 0x6B, 0x20, 0xC0, +0x23, 0x20, 0xCE, 0x23, 0x8B, 0x22, 0x6C, 0x1E, 0xE0, 0x22, 0xA0, 0x1E, 0xE0, 0xA5, 0xAA, 0xC5, +0xA6, 0x10, 0x06, 0xA4, 0xA6, 0x84, 0xAA, 0x85, 0xA6, 0xA5, 0xAC, 0xC5, 0xA8, 0x10, 0x06, 0xA4, +0xA8, 0x85, 0xA8, 0x84, 0xAC, 0xA5, 0xAA, 0x18, 0x65, 0xB8, 0x85, 0xAA, 0xA5, 0xAC, 0x18, 0x65, +0xBA, 0x85, 0xAC, 0x22, 0x90, 0x1E, 0xE0, 0x90, 0x03, 0x4C, 0x7F, 0x26, 0x22, 0x98, 0x1E, 0xE0, +0x20, 0x83, 0x3A, 0xA5, 0xB4, 0xC5, 0xB0, 0xF0, 0x18, 0xA5, 0xAE, 0xC5, 0xB2, 0x30, 0x19, 0xF0, +0x10, 0xA4, 0xB2, 0x84, 0xAE, 0x85, 0xB2, 0xA5, 0xB0, 0xA4, 0xB4, 0x84, 0xB0, 0x85, 0xB4, 0x80, +0x07, 0x22, 0x78, 0x1E, 0xE0, 0x4C, 0x7B, 0x26, 0xA9, 0x00, 0x80, 0x85, 0xD6, 0x85, 0xDA, 0xA5, +0xB0, 0x85, 0xD8, 0x18, 0x65, 0xBA, 0x85, 0xDC, 0x48, 0x48, 0xA5, 0xB4, 0x38, 0xE5, 0xB0, 0x48, +0xA5, 0xB2, 0x38, 0xE5, 0xAE, 0x48, 0xA2, 0x0B, 0x0E, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0xD2, +0x68, 0x85, 0xD4, 0x48, 0x48, 0xA5, 0xB8, 0x48, 0xA9, 0x00, 0x00, 0x48, 0xA5, 0xD4, 0x48, 0xA5, +0xD2, 0x48, 0xA2, 0x0B, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0xE2, 0x68, 0x85, 0xE4, 0xA5, +0xD4, 0x0A, 0xA5, 0xD4, 0x6A, 0x85, 0xE0, 0xA5, 0xD2, 0x6A, 0x85, 0xDE, 0xA2, 0x04, 0x00, 0xB5, +0xD6, 0x18, 0x65, 0xDE, 0x95, 0xD6, 0xB5, 0xD8, 0x65, 0xE0, 0x95, 0xD8, 0xCA, 0xCA, 0xCA, 0xCA, +0x10, 0xED, 0x24, 0xD4, 0x30, 0x24, 0xA5, 0xD6, 0x38, 0xE5, 0xE2, 0x85, 0xD6, 0xA5, 0xD8, 0xE5, +0xE4, 0x85, 0xD8, 0xA5, 0xD4, 0xF0, 0x04, 0xC6, 0xDC, 0x80, 0x36, 0xA5, 0xD6, 0x18, 0x65, 0xD2, +0x85, 0xD6, 0xA5, 0xD8, 0x65, 0xD4, 0x85, 0xD8, 0x80, 0x27, 0xA5, 0xDA, 0x38, 0xE5, 0xE2, 0x85, +0xDA, 0xA5, 0xDC, 0xE5, 0xE4, 0x85, 0xDC, 0xA5, 0xD4, 0xC9, 0xFF, 0xFF, 0xF0, 0x04, 0xE6, 0xD8, +0x80, 0x0F, 0xA5, 0xDA, 0x18, 0x65, 0xD2, 0x85, 0xDA, 0xA5, 0xDC, 0x65, 0xD4, 0x85, 0xDC, 0x80, +0x00, 0x22, 0xC0, 0x1E, 0xE0, 0x22, 0xE8, 0x1E, 0xE0, 0xA5, 0xA6, 0xC5, 0xAE, 0xF0, 0x2C, 0x38, +0xE5, 0xAE, 0x48, 0x48, 0x48, 0xF4, 0x00, 0x00, 0xD4, 0xD4, 0xD4, 0xD2, 0xA2, 0x0B, 0x0F, 0x22, +0x00, 0x00, 0xE1, 0xFA, 0x7A, 0x8A, 0x18, 0x65, 0xD6, 0x85, 0xD6, 0x98, 0x65, 0xD8, 0x85, 0xD8, +0x8A, 0x18, 0x65, 0xDA, 0x85, 0xDA, 0x98, 0x65, 0xDC, 0x85, 0xDC, 0x20, 0xE6, 0x23, 0xA5, 0xA8, +0x85, 0xB0, 0xA5, 0xAA, 0x85, 0xB2, 0xA5, 0xAC, 0x85, 0xB4, 0x8A, 0xA5, 0xDC, 0xC5, 0xB4, 0x30, +0x02, 0xA5, 0xB4, 0x85, 0xAC, 0xA5, 0xD8, 0xC5, 0xB0, 0x10, 0x02, 0xA5, 0xB0, 0x85, 0xA8, 0xC5, +0xAC, 0x10, 0x0F, 0x22, 0x70, 0x1E, 0xE0, 0x20, 0x0E, 0x24, 0x22, 0xCC, 0x1E, 0xE0, 0x22, 0x00, +0x1E, 0xE0, 0xA5, 0x40, 0x1A, 0xC5, 0xAA, 0x10, 0x22, 0x85, 0x40, 0xA5, 0xD6, 0x18, 0x65, 0xD2, +0x85, 0xD6, 0xA5, 0xD8, 0x65, 0xD4, 0x85, 0xD8, 0xA5, 0xDA, 0x18, 0x65, 0xD2, 0x85, 0xDA, 0xA5, +0xDC, 0x65, 0xD4, 0x85, 0xDC, 0x20, 0x41, 0x24, 0x4C, 0x2B, 0x26, 0x22, 0x9C, 0x1E, 0xE0, 0x22, +0xA8, 0x1E, 0xE0, 0xAB, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0xA0, 0x40, 0x00, 0xB7, 0x24, 0x85, 0xA6, +0x85, 0xAE, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0xA8, 0x85, 0xB0, 0x60, 0xA0, 0x40, 0x00, 0xA5, 0xAA, +0x97, 0x24, 0xC8, 0xC8, 0xA5, 0xAC, 0x97, 0x24, 0x60, 0x64, 0xC2, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, +0xAA, 0x86, 0xB0, 0xC0, 0x00, 0x00, 0x30, 0x10, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x32, 0x85, +0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0xC8, 0xC8, +0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x85, 0xC4, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x05, 0xC2, +0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0x05, 0xA8, 0xA4, 0xBC, 0x30, 0x25, 0x91, 0xBE, 0x80, +0x21, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0xC8, 0xC8, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x85, +0xC4, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, +0x91, 0xBE, 0xA5, 0xC4, 0x85, 0xC2, 0xC8, 0xC8, 0x84, 0xBC, 0xC4, 0xB8, 0x90, 0x9A, 0xF0, 0x98, +0x6B, 0x64, 0xC2, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, 0xAA, 0x86, 0xB0, 0xC0, 0x00, 0x00, 0x30, 0x09, +0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x2B, 0x85, 0xA6, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0xC8, +0xC8, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x85, 0xC4, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x05, +0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x30, 0x29, 0x11, 0xBE, 0x91, 0xBE, +0x80, 0x23, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0xC8, 0xC8, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, +0x85, 0xC4, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, +0xBC, 0x11, 0xBE, 0x91, 0xBE, 0xA5, 0xC4, 0x85, 0xC2, 0xC8, 0xC8, 0x84, 0xBC, 0xC4, 0xB8, 0x90, +0x9F, 0xF0, 0x9D, 0x6B, 0x64, 0xC2, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, 0xAA, 0x86, 0xB0, 0xC0, 0x00, +0x00, 0x30, 0x09, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x2B, 0x85, 0xA6, 0xA4, 0xB0, 0xB7, 0xB2, +0x85, 0xC6, 0xC8, 0xC8, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x85, 0xC4, 0xA5, 0xC6, 0x22, 0xDE, +0x38, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x30, 0x29, 0x51, +0xBE, 0x91, 0xBE, 0x80, 0x23, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0xC8, 0xC8, 0x84, 0xB0, 0x22, +0x69, 0x39, 0xFE, 0x85, 0xC4, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, +0xFF, 0xFF, 0xA4, 0xBC, 0x51, 0xBE, 0x91, 0xBE, 0xA5, 0xC4, 0x85, 0xC2, 0xC8, 0xC8, 0x84, 0xBC, +0xC4, 0xB8, 0x90, 0x9F, 0xF0, 0x9D, 0x6B, 0x64, 0xC2, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, 0xAA, 0x86, +0xB0, 0xC0, 0x00, 0x00, 0x30, 0x09, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x2E, 0x85, 0xA6, 0xA4, +0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0xC8, 0xC8, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x85, 0xC4, 0xA5, +0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, +0x30, 0x2F, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, 0xBE, 0x80, 0x26, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, +0xC6, 0xC8, 0xC8, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x85, 0xC4, 0xA5, 0xC6, 0x22, 0xDE, 0x38, +0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, +0xBE, 0xA5, 0xC4, 0x85, 0xC2, 0xC8, 0xC8, 0x84, 0xBC, 0xC4, 0xB8, 0x90, 0x99, 0xF0, 0x97, 0x6B, +0xA4, 0xAC, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0xA4, 0xB8, 0x84, 0xBC, 0xB7, 0x4C, +0xC9, 0xFF, 0xFF, 0xF0, 0x30, 0x85, 0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA5, 0xC6, +0x22, 0xDE, 0x38, 0xFE, 0x85, 0xC2, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, +0x22, 0x69, 0x39, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0x05, 0xA8, 0xA4, +0xBC, 0x91, 0xBE, 0x80, 0x21, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x85, 0xC2, 0xA4, 0xB0, 0xB7, +0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, +0xFF, 0xFF, 0xA4, 0xBC, 0x91, 0xBE, 0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0x9E, +0x6B, 0xA4, 0xAC, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0xA4, 0xB8, 0x84, 0xBC, 0xB7, +0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x29, 0x85, 0xA6, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x85, 0xC2, +0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x05, 0xC2, +0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x11, 0xBE, 0x91, 0xBE, 0x80, 0x23, 0xA5, +0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x85, 0xC2, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, +0xB0, 0x22, 0x69, 0x39, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x11, 0xBE, +0x91, 0xBE, 0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0xA3, 0x6B, 0xA4, 0xAC, 0xB7, +0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0xA4, 0xB8, 0x84, 0xBC, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, +0xF0, 0x29, 0x85, 0xA6, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x85, 0xC2, 0xA4, 0xB0, 0xB7, 0xB2, +0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, +0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x51, 0xBE, 0x91, 0xBE, 0x80, 0x23, 0xA5, 0xC6, 0x22, 0xDE, 0x38, +0xFE, 0x85, 0xC2, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0x22, 0x69, 0x39, +0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x51, 0xBE, 0x91, 0xBE, 0x88, 0x88, +0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0xA3, 0x6B, 0xA4, 0xAC, 0xB7, 0xB2, 0x85, 0xC6, 0x88, +0x88, 0x84, 0xB0, 0xA4, 0xB8, 0x84, 0xBC, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x2C, 0x85, 0xA6, +0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, 0x85, 0xC2, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, +0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, 0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, +0xBC, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, 0xBE, 0x80, 0x26, 0xA5, 0xC6, 0x22, 0xDE, 0x38, 0xFE, +0x85, 0xC2, 0xA4, 0xB0, 0xB7, 0xB2, 0x85, 0xC6, 0x88, 0x88, 0x84, 0xB0, 0x22, 0x69, 0x39, 0xFE, +0x05, 0xC2, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, 0xBE, +0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0x9D, 0x6B, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, +0xAA, 0x86, 0xB0, 0xC0, 0x00, 0x00, 0x30, 0x10, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x22, 0x85, +0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA4, 0xB0, 0xB7, 0xB2, 0xC8, 0xC8, 0x84, 0xB0, +0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0x05, 0xA8, 0xA4, 0xBC, 0x30, 0x15, 0x91, 0xBE, 0x80, +0x11, 0xA4, 0xB0, 0xB7, 0xB2, 0xC8, 0xC8, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, +0x91, 0xBE, 0xC8, 0xC8, 0x84, 0xBC, 0xC4, 0xB8, 0x90, 0xBE, 0xF0, 0xBC, 0x6B, 0xA4, 0xB6, 0x84, +0xBC, 0xA6, 0xAA, 0x86, 0xB0, 0xC0, 0x00, 0x00, 0x30, 0x09, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, +0x1B, 0x85, 0xA6, 0xA4, 0xB0, 0xB7, 0xB2, 0xC8, 0xC8, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, +0x25, 0xA6, 0xA4, 0xBC, 0x30, 0x19, 0x11, 0xBE, 0x91, 0xBE, 0x80, 0x13, 0xA4, 0xB0, 0xB7, 0xB2, +0xC8, 0xC8, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x11, 0xBE, 0x91, 0xBE, 0xC8, +0xC8, 0x84, 0xBC, 0xC4, 0xB8, 0x90, 0xC3, 0xF0, 0xC1, 0x6B, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, 0xAA, +0x86, 0xB0, 0xC0, 0x00, 0x00, 0x30, 0x09, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x1B, 0x85, 0xA6, +0xA4, 0xB0, 0xB7, 0xB2, 0xC8, 0xC8, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, +0xBC, 0x30, 0x19, 0x51, 0xBE, 0x91, 0xBE, 0x80, 0x13, 0xA4, 0xB0, 0xB7, 0xB2, 0xC8, 0xC8, 0x84, +0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x51, 0xBE, 0x91, 0xBE, 0xC8, 0xC8, 0x84, 0xBC, +0xC4, 0xB8, 0x90, 0xC3, 0xF0, 0xC1, 0x6B, 0xA4, 0xB6, 0x84, 0xBC, 0xA6, 0xAA, 0x86, 0xB0, 0xC0, +0x00, 0x00, 0x30, 0x09, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x1E, 0x85, 0xA6, 0xA4, 0xB0, 0xB7, +0xB2, 0xC8, 0xC8, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x30, 0x1F, +0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, 0xBE, 0x80, 0x16, 0xA4, 0xB0, 0xB7, 0xB2, 0xC8, 0xC8, 0x84, +0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, 0xBE, 0xC8, +0xC8, 0x84, 0xBC, 0xC4, 0xB8, 0x90, 0xBD, 0xF0, 0xBB, 0x6B, 0xA4, 0xAC, 0x84, 0xB0, 0xA4, 0xB8, +0x84, 0xBC, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x20, 0x85, 0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, +0x85, 0xA8, 0xA4, 0xB0, 0xB7, 0xB2, 0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, +0xA6, 0x05, 0xA8, 0xA4, 0xBC, 0x91, 0xBE, 0x80, 0x11, 0xA4, 0xB0, 0xB7, 0xB2, 0x88, 0x88, 0x84, +0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x91, 0xBE, 0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, +0xC4, 0xB6, 0xB0, 0xBE, 0x6B, 0xA4, 0xAC, 0x84, 0xB0, 0xA4, 0xB8, 0x84, 0xBC, 0xB7, 0x4C, 0xC9, +0xFF, 0xFF, 0xF0, 0x19, 0x85, 0xA6, 0xA4, 0xB0, 0xB7, 0xB2, 0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, +0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x11, 0xBE, 0x91, 0xBE, 0x80, 0x13, 0xA4, 0xB0, 0xB7, +0xB2, 0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x11, 0xBE, 0x91, 0xBE, +0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0xC3, 0x6B, 0xA4, 0xAC, 0x84, 0xB0, 0xA4, +0xB8, 0x84, 0xBC, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x19, 0x85, 0xA6, 0xA4, 0xB0, 0xB7, 0xB2, +0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, 0xA6, 0xA4, 0xBC, 0x51, 0xBE, 0x91, +0xBE, 0x80, 0x13, 0xA4, 0xB0, 0xB7, 0xB2, 0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, +0xA4, 0xBC, 0x51, 0xBE, 0x91, 0xBE, 0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0xC3, +0x6B, 0xA4, 0xAC, 0x84, 0xB0, 0xA4, 0xB8, 0x84, 0xBC, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x1C, +0x85, 0xA6, 0xA4, 0xB0, 0xB7, 0xB2, 0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0x25, +0xA6, 0xA4, 0xBC, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x91, 0xBE, 0x80, 0x16, 0xA4, 0xB0, 0xB7, 0xB2, +0x88, 0x88, 0x84, 0xB0, 0x50, 0x03, 0x49, 0xFF, 0xFF, 0xA4, 0xBC, 0x49, 0xFF, 0xFF, 0x31, 0xBE, +0x91, 0xBE, 0x88, 0x88, 0x30, 0x06, 0x84, 0xBC, 0xC4, 0xB6, 0xB0, 0xBD, 0x6B, 0xA4, 0xB6, 0xB7, +0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x17, 0x85, 0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA4, +0xAA, 0xB7, 0xB2, 0x25, 0xA6, 0x05, 0xA8, 0xA4, 0xB6, 0x91, 0xBE, 0x80, 0x08, 0xA4, 0xAA, 0xB7, +0xB2, 0xA4, 0xB6, 0x91, 0xBE, 0xA5, 0xB2, 0x18, 0x65, 0xAA, 0x38, 0xE9, 0xA0, 0x00, 0x18, 0x65, +0xBA, 0xAA, 0xA5, 0xBE, 0x18, 0x65, 0xB6, 0x38, 0xE9, 0xA0, 0x00, 0x18, 0x65, 0xBA, 0xA8, 0x4B, +0xF4, 0xF5, 0x2C, 0xA5, 0xBA, 0x3A, 0x3A, 0x48, 0x0A, 0x63, 0x01, 0x49, 0xFF, 0xFF, 0x1A, 0x18, +0x69, 0xF7, 0x2E, 0x83, 0x01, 0x60, 0xA4, 0xB8, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, 0xF0, 0x16, 0x85, +0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA4, 0xAC, 0xB7, 0xB2, 0x25, 0xA6, 0x05, 0xA8, +0xA4, 0xB8, 0x91, 0xBE, 0x6B, 0xA4, 0xAC, 0xB7, 0xB2, 0xA4, 0xB8, 0x91, 0xBE, 0x6B, 0xBD, 0x02, +0x00, 0x99, 0x02, 0x00, 0xBD, 0x04, 0x00, 0x99, 0x04, 0x00, 0xBD, 0x06, 0x00, 0x99, 0x06, 0x00, +0xBD, 0x08, 0x00, 0x99, 0x08, 0x00, 0xBD, 0x0A, 0x00, 0x99, 0x0A, 0x00, 0xBD, 0x0C, 0x00, 0x99, +0x0C, 0x00, 0xBD, 0x0E, 0x00, 0x99, 0x0E, 0x00, 0xBD, 0x10, 0x00, 0x99, 0x10, 0x00, 0xBD, 0x12, +0x00, 0x99, 0x12, 0x00, 0xBD, 0x14, 0x00, 0x99, 0x14, 0x00, 0xBD, 0x16, 0x00, 0x99, 0x16, 0x00, +0xBD, 0x18, 0x00, 0x99, 0x18, 0x00, 0xBD, 0x1A, 0x00, 0x99, 0x1A, 0x00, 0xBD, 0x1C, 0x00, 0x99, +0x1C, 0x00, 0xBD, 0x1E, 0x00, 0x99, 0x1E, 0x00, 0xBD, 0x20, 0x00, 0x99, 0x20, 0x00, 0xBD, 0x22, +0x00, 0x99, 0x22, 0x00, 0xBD, 0x24, 0x00, 0x99, 0x24, 0x00, 0xBD, 0x26, 0x00, 0x99, 0x26, 0x00, +0xBD, 0x28, 0x00, 0x99, 0x28, 0x00, 0xBD, 0x2A, 0x00, 0x99, 0x2A, 0x00, 0xBD, 0x2C, 0x00, 0x99, +0x2C, 0x00, 0xBD, 0x2E, 0x00, 0x99, 0x2E, 0x00, 0xBD, 0x30, 0x00, 0x99, 0x30, 0x00, 0xBD, 0x32, +0x00, 0x99, 0x32, 0x00, 0xBD, 0x34, 0x00, 0x99, 0x34, 0x00, 0xBD, 0x36, 0x00, 0x99, 0x36, 0x00, +0xBD, 0x38, 0x00, 0x99, 0x38, 0x00, 0xBD, 0x3A, 0x00, 0x99, 0x3A, 0x00, 0xBD, 0x3C, 0x00, 0x99, +0x3C, 0x00, 0xBD, 0x3E, 0x00, 0x99, 0x3E, 0x00, 0xBD, 0x40, 0x00, 0x99, 0x40, 0x00, 0xBD, 0x42, +0x00, 0x99, 0x42, 0x00, 0xBD, 0x44, 0x00, 0x99, 0x44, 0x00, 0xBD, 0x46, 0x00, 0x99, 0x46, 0x00, +0xBD, 0x48, 0x00, 0x99, 0x48, 0x00, 0xBD, 0x4A, 0x00, 0x99, 0x4A, 0x00, 0xBD, 0x4C, 0x00, 0x99, +0x4C, 0x00, 0xBD, 0x4E, 0x00, 0x99, 0x4E, 0x00, 0xBD, 0x50, 0x00, 0x99, 0x50, 0x00, 0xBD, 0x52, +0x00, 0x99, 0x52, 0x00, 0xBD, 0x54, 0x00, 0x99, 0x54, 0x00, 0xBD, 0x56, 0x00, 0x99, 0x56, 0x00, +0xBD, 0x58, 0x00, 0x99, 0x58, 0x00, 0xBD, 0x5A, 0x00, 0x99, 0x5A, 0x00, 0xBD, 0x5C, 0x00, 0x99, +0x5C, 0x00, 0xBD, 0x5E, 0x00, 0x99, 0x5E, 0x00, 0xBD, 0x60, 0x00, 0x99, 0x60, 0x00, 0xBD, 0x62, +0x00, 0x99, 0x62, 0x00, 0xBD, 0x64, 0x00, 0x99, 0x64, 0x00, 0xBD, 0x66, 0x00, 0x99, 0x66, 0x00, +0xBD, 0x68, 0x00, 0x99, 0x68, 0x00, 0xBD, 0x6A, 0x00, 0x99, 0x6A, 0x00, 0xBD, 0x6C, 0x00, 0x99, +0x6C, 0x00, 0xBD, 0x6E, 0x00, 0x99, 0x6E, 0x00, 0xBD, 0x70, 0x00, 0x99, 0x70, 0x00, 0xBD, 0x72, +0x00, 0x99, 0x72, 0x00, 0xBD, 0x74, 0x00, 0x99, 0x74, 0x00, 0xBD, 0x76, 0x00, 0x99, 0x76, 0x00, +0xBD, 0x78, 0x00, 0x99, 0x78, 0x00, 0xBD, 0x7A, 0x00, 0x99, 0x7A, 0x00, 0xBD, 0x7C, 0x00, 0x99, +0x7C, 0x00, 0xBD, 0x7E, 0x00, 0x99, 0x7E, 0x00, 0xBD, 0x80, 0x00, 0x99, 0x80, 0x00, 0xBD, 0x82, +0x00, 0x99, 0x82, 0x00, 0xBD, 0x84, 0x00, 0x99, 0x84, 0x00, 0xBD, 0x86, 0x00, 0x99, 0x86, 0x00, +0xBD, 0x88, 0x00, 0x99, 0x88, 0x00, 0xBD, 0x8A, 0x00, 0x99, 0x8A, 0x00, 0xBD, 0x8C, 0x00, 0x99, +0x8C, 0x00, 0xBD, 0x8E, 0x00, 0x99, 0x8E, 0x00, 0xBD, 0x90, 0x00, 0x99, 0x90, 0x00, 0xBD, 0x92, +0x00, 0x99, 0x92, 0x00, 0xBD, 0x94, 0x00, 0x99, 0x94, 0x00, 0xBD, 0x96, 0x00, 0x99, 0x96, 0x00, +0xBD, 0x98, 0x00, 0x99, 0x98, 0x00, 0xBD, 0x9A, 0x00, 0x99, 0x9A, 0x00, 0xBD, 0x9C, 0x00, 0x99, +0x9C, 0x00, 0xBD, 0x9E, 0x00, 0x99, 0x9E, 0x00, 0x6B, 0xA4, 0xB8, 0xB7, 0x4C, 0xC9, 0xFF, 0xFF, +0xF0, 0x17, 0x85, 0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA4, 0xAC, 0xB7, 0xB2, 0x25, +0xA6, 0x05, 0xA8, 0xA4, 0xB8, 0x91, 0xBE, 0x80, 0x08, 0xA4, 0xAC, 0xB7, 0xB2, 0xA4, 0xB8, 0x91, +0xBE, 0xA5, 0xB2, 0x18, 0x65, 0xAC, 0x38, 0xE5, 0xBA, 0xAA, 0xA5, 0xBE, 0x18, 0x65, 0xB8, 0x38, +0xE5, 0xBA, 0xA8, 0x4B, 0xF4, 0x49, 0x2F, 0xA5, 0xBA, 0x3A, 0x3A, 0x48, 0x0A, 0x63, 0x01, 0x49, +0xFF, 0xFF, 0x1A, 0x18, 0x69, 0x4B, 0x31, 0x83, 0x01, 0x60, 0xA4, 0xB6, 0xB7, 0x4C, 0xC9, 0xFF, +0xFF, 0xF0, 0x16, 0x85, 0xA6, 0x49, 0xFF, 0xFF, 0x31, 0xBE, 0x85, 0xA8, 0xA4, 0xAA, 0xB7, 0xB2, +0x25, 0xA6, 0x05, 0xA8, 0xA4, 0xB6, 0x91, 0xBE, 0x6B, 0xA4, 0xAA, 0xB7, 0xB2, 0xA4, 0xB6, 0x91, +0xBE, 0x6B, 0xBD, 0x9E, 0x00, 0x99, 0x9E, 0x00, 0xBD, 0x9C, 0x00, 0x99, 0x9C, 0x00, 0xBD, 0x9A, +0x00, 0x99, 0x9A, 0x00, 0xBD, 0x98, 0x00, 0x99, 0x98, 0x00, 0xBD, 0x96, 0x00, 0x99, 0x96, 0x00, +0xBD, 0x94, 0x00, 0x99, 0x94, 0x00, 0xBD, 0x92, 0x00, 0x99, 0x92, 0x00, 0xBD, 0x90, 0x00, 0x99, +0x90, 0x00, 0xBD, 0x8E, 0x00, 0x99, 0x8E, 0x00, 0xBD, 0x8C, 0x00, 0x99, 0x8C, 0x00, 0xBD, 0x8A, +0x00, 0x99, 0x8A, 0x00, 0xBD, 0x88, 0x00, 0x99, 0x88, 0x00, 0xBD, 0x86, 0x00, 0x99, 0x86, 0x00, +0xBD, 0x84, 0x00, 0x99, 0x84, 0x00, 0xBD, 0x82, 0x00, 0x99, 0x82, 0x00, 0xBD, 0x80, 0x00, 0x99, +0x80, 0x00, 0xBD, 0x7E, 0x00, 0x99, 0x7E, 0x00, 0xBD, 0x7C, 0x00, 0x99, 0x7C, 0x00, 0xBD, 0x7A, +0x00, 0x99, 0x7A, 0x00, 0xBD, 0x78, 0x00, 0x99, 0x78, 0x00, 0xBD, 0x76, 0x00, 0x99, 0x76, 0x00, +0xBD, 0x74, 0x00, 0x99, 0x74, 0x00, 0xBD, 0x72, 0x00, 0x99, 0x72, 0x00, 0xBD, 0x70, 0x00, 0x99, +0x70, 0x00, 0xBD, 0x6E, 0x00, 0x99, 0x6E, 0x00, 0xBD, 0x6C, 0x00, 0x99, 0x6C, 0x00, 0xBD, 0x6A, +0x00, 0x99, 0x6A, 0x00, 0xBD, 0x68, 0x00, 0x99, 0x68, 0x00, 0xBD, 0x66, 0x00, 0x99, 0x66, 0x00, +0xBD, 0x64, 0x00, 0x99, 0x64, 0x00, 0xBD, 0x62, 0x00, 0x99, 0x62, 0x00, 0xBD, 0x60, 0x00, 0x99, +0x60, 0x00, 0xBD, 0x5E, 0x00, 0x99, 0x5E, 0x00, 0xBD, 0x5C, 0x00, 0x99, 0x5C, 0x00, 0xBD, 0x5A, +0x00, 0x99, 0x5A, 0x00, 0xBD, 0x58, 0x00, 0x99, 0x58, 0x00, 0xBD, 0x56, 0x00, 0x99, 0x56, 0x00, +0xBD, 0x54, 0x00, 0x99, 0x54, 0x00, 0xBD, 0x52, 0x00, 0x99, 0x52, 0x00, 0xBD, 0x50, 0x00, 0x99, +0x50, 0x00, 0xBD, 0x4E, 0x00, 0x99, 0x4E, 0x00, 0xBD, 0x4C, 0x00, 0x99, 0x4C, 0x00, 0xBD, 0x4A, +0x00, 0x99, 0x4A, 0x00, 0xBD, 0x48, 0x00, 0x99, 0x48, 0x00, 0xBD, 0x46, 0x00, 0x99, 0x46, 0x00, +0xBD, 0x44, 0x00, 0x99, 0x44, 0x00, 0xBD, 0x42, 0x00, 0x99, 0x42, 0x00, 0xBD, 0x40, 0x00, 0x99, +0x40, 0x00, 0xBD, 0x3E, 0x00, 0x99, 0x3E, 0x00, 0xBD, 0x3C, 0x00, 0x99, 0x3C, 0x00, 0xBD, 0x3A, +0x00, 0x99, 0x3A, 0x00, 0xBD, 0x38, 0x00, 0x99, 0x38, 0x00, 0xBD, 0x36, 0x00, 0x99, 0x36, 0x00, +0xBD, 0x34, 0x00, 0x99, 0x34, 0x00, 0xBD, 0x32, 0x00, 0x99, 0x32, 0x00, 0xBD, 0x30, 0x00, 0x99, +0x30, 0x00, 0xBD, 0x2E, 0x00, 0x99, 0x2E, 0x00, 0xBD, 0x2C, 0x00, 0x99, 0x2C, 0x00, 0xBD, 0x2A, +0x00, 0x99, 0x2A, 0x00, 0xBD, 0x28, 0x00, 0x99, 0x28, 0x00, 0xBD, 0x26, 0x00, 0x99, 0x26, 0x00, +0xBD, 0x24, 0x00, 0x99, 0x24, 0x00, 0xBD, 0x22, 0x00, 0x99, 0x22, 0x00, 0xBD, 0x20, 0x00, 0x99, +0x20, 0x00, 0xBD, 0x1E, 0x00, 0x99, 0x1E, 0x00, 0xBD, 0x1C, 0x00, 0x99, 0x1C, 0x00, 0xBD, 0x1A, +0x00, 0x99, 0x1A, 0x00, 0xBD, 0x18, 0x00, 0x99, 0x18, 0x00, 0xBD, 0x16, 0x00, 0x99, 0x16, 0x00, +0xBD, 0x14, 0x00, 0x99, 0x14, 0x00, 0xBD, 0x12, 0x00, 0x99, 0x12, 0x00, 0xBD, 0x10, 0x00, 0x99, +0x10, 0x00, 0xBD, 0x0E, 0x00, 0x99, 0x0E, 0x00, 0xBD, 0x0C, 0x00, 0x99, 0x0C, 0x00, 0xBD, 0x0A, +0x00, 0x99, 0x0A, 0x00, 0xBD, 0x08, 0x00, 0x99, 0x08, 0x00, 0xBD, 0x06, 0x00, 0x99, 0x06, 0x00, +0xBD, 0x04, 0x00, 0x99, 0x04, 0x00, 0xBD, 0x02, 0x00, 0x99, 0x02, 0x00, 0x6B, 0x20, 0x41, 0x33, +0x90, 0x0A, 0xA9, 0x90, 0x00, 0x22, 0xF8, 0x1E, 0xE0, 0x90, 0x01, 0x6B, 0x20, 0xC0, 0x23, 0x5C, +0xDC, 0x1F, 0xE0, 0x8B, 0xA5, 0xCC, 0x45, 0x0C, 0x29, 0x80, 0x00, 0xF0, 0x06, 0xA9, 0x20, 0x04, +0x4C, 0x2E, 0x33, 0xA5, 0xD4, 0xC5, 0xDC, 0x30, 0x0C, 0x38, 0xE5, 0xDC, 0x18, 0x65, 0x1C, 0x85, +0x1C, 0xA5, 0xD4, 0x85, 0xDC, 0xA5, 0xD6, 0xC5, 0xDE, 0x30, 0x0C, 0x38, 0xE5, 0xDE, 0x18, 0x65, +0x1E, 0x85, 0x1E, 0xA5, 0xD6, 0x85, 0xDE, 0xA5, 0xD8, 0xC5, 0xE0, 0x10, 0x02, 0x85, 0xE0, 0xA5, +0xDA, 0xC5, 0xE2, 0x10, 0x02, 0x85, 0xE2, 0xA5, 0xDC, 0xC5, 0xE0, 0x30, 0x03, 0x4C, 0x28, 0x33, +0xA5, 0xDE, 0xC5, 0xE2, 0x30, 0x03, 0x4C, 0x28, 0x33, 0xA2, 0x02, 0x00, 0xB5, 0xE0, 0x38, 0xF5, +0xDC, 0x18, 0x75, 0x1C, 0x95, 0x20, 0xCA, 0xCA, 0x10, 0xF2, 0x22, 0xE0, 0x1F, 0xE0, 0x90, 0x03, +0x4C, 0x24, 0x33, 0xA2, 0x06, 0x00, 0xB5, 0x00, 0x38, 0xF5, 0x1C, 0xF0, 0x05, 0x18, 0x75, 0xDC, +0x95, 0xDC, 0xCA, 0xCA, 0x10, 0xF0, 0xA5, 0x00, 0x85, 0x1C, 0xA5, 0x02, 0x85, 0x1E, 0xA5, 0x04, +0x85, 0x20, 0xA5, 0x06, 0x85, 0x22, 0x22, 0xE4, 0x1F, 0xE0, 0x22, 0x98, 0x1E, 0xE0, 0xA5, 0x1C, +0x85, 0x00, 0xA5, 0x1E, 0x85, 0x02, 0xA5, 0x20, 0x85, 0x04, 0xA5, 0x22, 0x85, 0x06, 0xA2, 0x00, +0x00, 0x9B, 0x20, 0x31, 0x33, 0x90, 0x24, 0xA5, 0x1C, 0x38, 0xE5, 0x14, 0x48, 0xA5, 0xDC, 0x38, +0xE5, 0xD4, 0xC3, 0x01, 0xB0, 0x03, 0x88, 0x80, 0x11, 0xA5, 0x1E, 0x38, 0xE5, 0x16, 0x83, 0x01, +0xA5, 0xDE, 0x38, 0xE5, 0x16, 0xC3, 0x01, 0xB0, 0x01, 0xCA, 0x68, 0x84, 0xC8, 0x86, 0xCA, 0xF4, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x10, 0x05, 0xA5, 0xE0, 0x3A, 0x80, 0x02, 0xA5, +0xDC, 0x38, 0xE5, 0xD4, 0x48, 0xD4, 0xD2, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xFA, +0x18, 0x65, 0xCE, 0x85, 0xB2, 0x8A, 0x65, 0xD0, 0x85, 0xB4, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0x24, 0xC8, 0x10, 0x05, 0xA5, 0x20, 0x3A, 0x80, 0x02, 0xA5, 0x1C, 0x38, 0xE5, 0x14, 0x48, 0xD4, +0x12, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xFA, 0x18, 0x65, 0x0E, 0x85, 0xBE, 0x8A, +0x65, 0x10, 0x85, 0xC0, 0x22, 0x7C, 0x1E, 0xE0, 0x22, 0xA4, 0x1E, 0xE0, 0x22, 0xC4, 0x1E, 0xE0, +0x22, 0xEC, 0x1E, 0xE0, 0xD4, 0xBF, 0xAB, 0xAB, 0xB8, 0xA5, 0xE4, 0x10, 0x02, 0xE2, 0x40, 0x08, +0xA5, 0x20, 0x3A, 0x85, 0x40, 0x24, 0xC8, 0x30, 0x35, 0xA5, 0x1C, 0x85, 0x40, 0x22, 0xD0, 0x1E, +0xE0, 0x28, 0x08, 0x22, 0x00, 0x1E, 0xE0, 0xA5, 0x40, 0x1A, 0xC5, 0x20, 0x10, 0x51, 0x85, 0x40, +0xA5, 0xD2, 0x18, 0x65, 0xB2, 0x85, 0xB2, 0x90, 0x02, 0xE6, 0xB4, 0xA5, 0x12, 0x18, 0x65, 0xBE, +0x85, 0xBE, 0x90, 0x08, 0xE6, 0xC0, 0x8B, 0xA5, 0xBF, 0x83, 0x00, 0xAB, 0x80, 0xCF, 0x22, 0xD0, +0x1E, 0xE0, 0x28, 0x08, 0x22, 0x00, 0x1E, 0xE0, 0xA5, 0x40, 0x3A, 0xC5, 0x1C, 0x30, 0x20, 0x85, +0x40, 0xA5, 0xB2, 0x38, 0xE5, 0xD2, 0x85, 0xB2, 0xB0, 0x02, 0xC6, 0xB4, 0xA5, 0xBE, 0x38, 0xE5, +0x12, 0x85, 0xBE, 0xB0, 0x08, 0xC6, 0xC0, 0x8B, 0xA5, 0xBF, 0x83, 0x00, 0xAB, 0x80, 0xCF, 0x22, +0x9C, 0x1E, 0xE0, 0x28, 0x22, 0xB4, 0x1E, 0xE0, 0xAB, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0xAB, 0x38, +0x6B, 0xA5, 0xCE, 0xC5, 0x0E, 0xD0, 0x08, 0xA5, 0xCF, 0xC5, 0x0F, 0xD0, 0x02, 0x38, 0x60, 0x18, +0x60, 0xA0, 0x0E, 0x00, 0xBB, 0xB7, 0x24, 0xD5, 0x0C, 0xD0, 0x06, 0x88, 0x88, 0x10, 0xF5, 0x38, +0x60, 0x18, 0x60, 0x20, 0xA7, 0x45, 0x20, 0xB8, 0x45, 0x20, 0xC9, 0x45, 0xA0, 0x02, 0x00, 0xB7, +0x74, 0xC5, 0x1C, 0x10, 0x02, 0xA5, 0x1C, 0x85, 0x00, 0xC8, 0xC8, 0xB7, 0x74, 0xC5, 0x1E, 0x10, +0x02, 0xA5, 0x1E, 0x85, 0x02, 0xC8, 0xC8, 0xB7, 0x74, 0xC5, 0x20, 0x30, 0x02, 0xA5, 0x20, 0x85, +0x04, 0xC8, 0xC8, 0xB7, 0x74, 0xC5, 0x22, 0x30, 0x02, 0xA5, 0x22, 0x85, 0x06, 0x24, 0xE6, 0x10, +0x2E, 0x20, 0x41, 0x33, 0x90, 0x29, 0xA0, 0x10, 0x00, 0xB7, 0x24, 0xC5, 0x00, 0x30, 0x02, 0x85, +0x00, 0xC8, 0xC8, 0xB7, 0x24, 0xC5, 0x02, 0x30, 0x02, 0x85, 0x02, 0xC8, 0xC8, 0xB7, 0x24, 0xC5, +0x04, 0x10, 0x02, 0x85, 0x04, 0xC8, 0xC8, 0xB7, 0x24, 0xC5, 0x06, 0x10, 0x02, 0x85, 0x06, 0x22, +0x94, 0x1E, 0xE0, 0x6B, 0x20, 0x31, 0x33, 0x90, 0x28, 0xA5, 0x1C, 0xC5, 0xDC, 0x30, 0x02, 0xA5, +0xDC, 0x85, 0x00, 0xA5, 0x1E, 0xC5, 0xDE, 0x30, 0x02, 0xA5, 0xDE, 0x85, 0x02, 0xA5, 0x20, 0xC5, +0xE0, 0x10, 0x02, 0xA5, 0xE0, 0x85, 0x04, 0xA5, 0x22, 0xC5, 0xE2, 0x10, 0x02, 0xA5, 0xE2, 0x85, +0x06, 0x6B, 0x20, 0xB3, 0x0D, 0xA3, 0x13, 0x85, 0x2E, 0xA3, 0x15, 0x85, 0x30, 0xA0, 0x0E, 0x00, +0xBB, 0xB7, 0x2E, 0x95, 0xCC, 0x88, 0x88, 0x10, 0xF7, 0x22, 0x3C, 0x1E, 0xE0, 0xA3, 0x0F, 0x85, +0x2E, 0xA3, 0x11, 0x85, 0x30, 0xA0, 0x06, 0x00, 0xBB, 0xB7, 0x2E, 0x95, 0xDC, 0x88, 0x88, 0x10, +0xF7, 0xA3, 0x0B, 0x85, 0x1C, 0xA3, 0x0D, 0x85, 0x1E, 0xA5, 0xE0, 0x38, 0xE5, 0xDC, 0x18, 0x65, +0x1C, 0x85, 0x20, 0xA5, 0xE2, 0x38, 0xE5, 0xDE, 0x18, 0x65, 0x1E, 0x85, 0x22, 0xA3, 0x09, 0x85, +0xE4, 0x22, 0xA0, 0x1E, 0xE0, 0xA9, 0xF5, 0x0D, 0x85, 0x70, 0xA9, 0xFE, 0x00, 0x85, 0x72, 0xA9, +0x00, 0x80, 0x85, 0xE6, 0x22, 0x5F, 0x34, 0xFE, 0xAA, 0xA0, 0x0E, 0x00, 0x4C, 0x22, 0xFF, 0x20, +0x41, 0x33, 0x90, 0x11, 0xA0, 0x9C, 0x00, 0xB7, 0x24, 0x85, 0x2A, 0xC8, 0xC8, 0xB7, 0x24, 0x85, +0x2C, 0x05, 0x2A, 0xD0, 0x04, 0x5C, 0x24, 0x1E, 0xE0, 0x8B, 0xA0, 0x20, 0x00, 0xB7, 0x2A, 0x48, +0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, 0x20, 0xB3, 0x0D, 0xA0, 0x16, 0x00, 0xBB, 0xB7, 0x24, 0x95, +0xCC, 0x95, 0x0C, 0x88, 0x88, 0x10, 0xF5, 0x8B, 0xA3, 0x12, 0xAA, 0xA3, 0x13, 0x8B, 0x83, 0x00, +0xAB, 0xBD, 0x00, 0x00, 0xC5, 0xDC, 0x30, 0x04, 0x85, 0xDC, 0x85, 0x1C, 0xBD, 0x02, 0x00, 0xC5, +0xDE, 0x30, 0x04, 0x85, 0xDE, 0x85, 0x1E, 0xBD, 0x04, 0x00, 0xC5, 0xE0, 0x10, 0x04, 0x85, 0xE0, +0x85, 0x20, 0xBD, 0x06, 0x00, 0xC5, 0xE2, 0x10, 0x04, 0x85, 0xE2, 0x85, 0x22, 0xAB, 0xA3, 0x0D, +0x30, 0x0E, 0x18, 0x65, 0x1C, 0x85, 0x1C, 0xA5, 0xE0, 0x38, 0xE3, 0x0D, 0x85, 0xE0, 0x80, 0x0C, +0x18, 0x65, 0x20, 0x85, 0x20, 0xA5, 0xDC, 0x38, 0xE3, 0x0D, 0x85, 0xDC, 0xA3, 0x0F, 0x30, 0x0E, +0x18, 0x65, 0x1E, 0x85, 0x1E, 0xA5, 0xE2, 0x38, 0xE3, 0x0F, 0x85, 0xE2, 0x80, 0x0C, 0x18, 0x65, +0x22, 0x85, 0x22, 0xA5, 0xDE, 0x38, 0xE3, 0x0F, 0x85, 0xDE, 0x64, 0xE4, 0x7B, 0xAA, 0xA0, 0x42, +0x00, 0xBF, 0xA6, 0x00, 0x00, 0x9F, 0x00, 0x02, 0x00, 0xE8, 0xE8, 0x88, 0x88, 0x10, 0xF2, 0xA5, +0x26, 0x48, 0xA5, 0x24, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x04, 0x67, 0x22, 0x00, +0x00, 0xE1, 0x90, 0x05, 0xFA, 0xFA, 0x4C, 0x7B, 0x36, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, +0x04, 0x67, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x12, 0xFA, 0xFA, 0xFA, 0x7A, 0x48, 0x5A, 0xDA, 0xA2, +0x04, 0x68, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x4C, 0x7B, 0x36, 0x0B, 0x3B, 0x5B, 0xD4, 0x05, 0xD4, +0x03, 0xD4, 0x21, 0xD4, 0x1F, 0xA2, 0x04, 0x6C, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, 0x4C, 0x62, +0x36, 0xD4, 0x05, 0xD4, 0x03, 0xA0, 0x1E, 0x00, 0xB7, 0x0B, 0x48, 0x88, 0x88, 0xB7, 0x0B, 0x48, +0xD4, 0x05, 0xD4, 0x03, 0xA2, 0x04, 0x71, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, 0x4C, 0x62, 0x36, +0xD4, 0x05, 0xD4, 0x03, 0xA0, 0x1A, 0x00, 0xB7, 0x0B, 0x48, 0x88, 0x88, 0xB7, 0x0B, 0x48, 0xD4, +0x05, 0xD4, 0x03, 0xA2, 0x04, 0x71, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, 0x4C, 0x62, 0x36, 0xD4, +0x05, 0xD4, 0x03, 0xD4, 0x09, 0xD4, 0x07, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, +0x4C, 0x62, 0x36, 0xD4, 0x09, 0xD4, 0x07, 0xD4, 0x1D, 0xD4, 0x1B, 0xA2, 0x04, 0x6F, 0x22, 0x00, +0x00, 0xE1, 0x90, 0x03, 0x4C, 0x62, 0x36, 0x2B, 0x68, 0x85, 0x50, 0x68, 0x85, 0x52, 0x68, 0x85, +0x60, 0x68, 0x85, 0x62, 0x68, 0x68, 0xA9, 0xF5, 0x0D, 0x85, 0x70, 0xA9, 0xFE, 0x00, 0x85, 0x72, +0x7B, 0xAA, 0xA0, 0x42, 0x00, 0xBF, 0x00, 0x02, 0x00, 0x9F, 0xA6, 0x00, 0x00, 0xE8, 0xE8, 0x88, +0x88, 0x10, 0xF2, 0x64, 0xE6, 0x22, 0xDC, 0x1F, 0xE0, 0xB0, 0x70, 0xD4, 0x62, 0xD4, 0x60, 0xD4, +0x52, 0xD4, 0x50, 0x0B, 0x3B, 0x5B, 0xD4, 0x05, 0xD4, 0x03, 0xD4, 0x09, 0xD4, 0x07, 0xD4, 0x05, +0xD4, 0x03, 0xA2, 0x04, 0x73, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x37, 0xD4, 0x05, 0xD4, 0x03, 0xA2, +0x04, 0x7B, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x13, 0x05, 0x15, 0xF0, 0x11, 0xD4, 0x05, 0xD4, 0x03, +0xD4, 0x15, 0xD4, 0x13, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x15, 0x2B, 0xA2, 0x04, +0x68, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x04, 0x68, 0x22, 0x00, 0x00, 0xE1, 0xA0, 0x0C, 0x00, 0x4C, +0x1F, 0xFF, 0x48, 0xD4, 0x05, 0xD4, 0x03, 0xA2, 0x04, 0x68, 0x22, 0x00, 0x00, 0xE1, 0xD4, 0x09, +0xD4, 0x07, 0xA2, 0x04, 0x68, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x2B, 0xAA, 0xA0, 0x0C, 0x00, 0x4C, +0x22, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2A, 0xAA, 0xA3, 0x0A, 0x8B, 0x48, 0xAB, 0xAB, +0xBD, 0x00, 0x00, 0x85, 0x2E, 0xBD, 0x01, 0x00, 0x85, 0x2F, 0xA0, 0x0E, 0x00, 0xBB, 0xB7, 0x2E, +0x95, 0xCC, 0x88, 0x88, 0x10, 0xF7, 0xA6, 0x2A, 0xBD, 0x04, 0x00, 0x85, 0x2E, 0xBD, 0x05, 0x00, +0x85, 0x2F, 0xA0, 0x0E, 0x00, 0xBB, 0xB7, 0x2E, 0x95, 0x0C, 0x88, 0x88, 0x10, 0xF7, 0xA6, 0x2A, +0xBD, 0x08, 0x00, 0x85, 0x2E, 0xBD, 0x09, 0x00, 0x85, 0x2F, 0xA0, 0x06, 0x00, 0xBB, 0xB7, 0x2E, +0x95, 0xDC, 0x88, 0x88, 0x10, 0xF7, 0xA6, 0x2A, 0xBD, 0x0C, 0x00, 0x85, 0x2E, 0xBD, 0x0D, 0x00, +0x85, 0x2F, 0xA7, 0x2E, 0x85, 0x1C, 0xA0, 0x02, 0x00, 0xB7, 0x2E, 0x85, 0x1E, 0xA5, 0xE0, 0x38, +0xE5, 0xDC, 0x18, 0x65, 0x1C, 0x85, 0x20, 0xA5, 0xE2, 0x38, 0xE5, 0xDE, 0x18, 0x65, 0x1E, 0x85, +0x22, 0xBD, 0x10, 0x00, 0x85, 0xE4, 0xA9, 0xF5, 0x0D, 0x85, 0x50, 0x85, 0x60, 0x85, 0x70, 0xA9, +0xFE, 0x00, 0x85, 0x52, 0x85, 0x62, 0x85, 0x72, 0xBD, 0x12, 0x00, 0x1D, 0x14, 0x00, 0xF0, 0x0A, +0xBD, 0x12, 0x00, 0x85, 0x70, 0xBD, 0x14, 0x00, 0x85, 0x72, 0xAB, 0x64, 0xE6, 0x22, 0x5F, 0x34, +0xFE, 0xAA, 0xA0, 0x04, 0x00, 0x4C, 0x22, 0xFF, 0x24, 0xCB, 0x30, 0x4F, 0xA5, 0xDE, 0x38, 0xE5, +0xD6, 0x85, 0x42, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xAA, 0xA5, 0xE2, 0x3A, 0x38, 0xE5, 0xD6, 0x4A, +0x29, 0xFE, 0xFF, 0x85, 0xAC, 0xA5, 0x1E, 0x38, 0xE5, 0x16, 0xAA, 0x4A, 0x29, 0xFE, 0xFF, 0x85, +0xB6, 0xA5, 0x22, 0x3A, 0x38, 0xE5, 0x16, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xB8, 0xA5, 0x42, 0x29, +0x03, 0x00, 0x85, 0x42, 0x8A, 0x29, 0x03, 0x00, 0xC5, 0x42, 0xB0, 0x08, 0xC6, 0xB6, 0xC6, 0xB6, +0x18, 0x69, 0x04, 0x00, 0x38, 0xE5, 0x42, 0x0A, 0x0A, 0x80, 0x50, 0xA5, 0xDE, 0x38, 0xE5, 0xD6, +0x85, 0x42, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xAA, 0xA5, 0xE2, 0x3A, 0x38, 0xE5, 0xD6, 0x4A, +0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xAC, 0xA5, 0x1E, 0x38, 0xE5, 0x16, 0xAA, 0x4A, 0x4A, 0x29, 0xFE, +0xFF, 0x85, 0xB6, 0xA5, 0x22, 0x3A, 0x38, 0xE5, 0x16, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0xB8, +0xA5, 0x42, 0x29, 0x07, 0x00, 0x85, 0x42, 0x8A, 0x29, 0x07, 0x00, 0xC5, 0x42, 0xB0, 0x08, 0xC6, +0xB6, 0xC6, 0xB6, 0x18, 0x69, 0x08, 0x00, 0x38, 0xE5, 0x42, 0x0A, 0x0A, 0x85, 0x42, 0xA5, 0xB8, +0x38, 0xE5, 0xB6, 0x85, 0xBA, 0xA5, 0xAC, 0x38, 0xE5, 0xAA, 0x85, 0xAE, 0xC5, 0xBA, 0xF0, 0x18, +0x90, 0x0E, 0xA9, 0x00, 0x00, 0x85, 0xA0, 0xC6, 0xB6, 0xC6, 0xB6, 0xE6, 0xBA, 0xE6, 0xBA, 0x6B, +0xE6, 0xAC, 0xE6, 0xAC, 0xE6, 0xAE, 0xE6, 0xAE, 0x6B, 0xA5, 0xE4, 0x29, 0x7F, 0x00, 0x0A, 0x0A, +0xAA, 0xA5, 0x42, 0xF0, 0x23, 0x24, 0xCA, 0x10, 0x0E, 0xBF, 0xA6, 0x38, 0xFE, 0x8F, 0x00, 0x1E, +0xE0, 0xBF, 0xA8, 0x38, 0xFE, 0x80, 0x0C, 0xBF, 0x96, 0x38, 0xFE, 0x8F, 0x00, 0x1E, 0xE0, 0xBF, +0x98, 0x38, 0xFE, 0x8F, 0x02, 0x1E, 0xE0, 0x6B, 0xA5, 0xE4, 0xD0, 0x19, 0xA5, 0xA4, 0xD0, 0x15, +0xA5, 0xBA, 0xC9, 0x04, 0x00, 0x90, 0x0E, 0xA5, 0xCF, 0xC5, 0x0F, 0xD0, 0x08, 0xC9, 0x20, 0xE1, +0xD0, 0x03, 0x38, 0x80, 0x01, 0x18, 0x24, 0xCA, 0x10, 0x1E, 0x90, 0x0E, 0xAF, 0xD6, 0x38, 0xFE, +0x8F, 0x00, 0x1E, 0xE0, 0xAF, 0xD8, 0x38, 0xFE, 0x80, 0xC9, 0xBF, 0xC6, 0x38, 0xFE, 0x8F, 0x00, +0x1E, 0xE0, 0xBF, 0xC8, 0x38, 0xFE, 0x80, 0xBB, 0x90, 0x0E, 0xAF, 0xDA, 0x38, 0xFE, 0x8F, 0x00, +0x1E, 0xE0, 0xAF, 0xDC, 0x38, 0xFE, 0x80, 0xAB, 0xBF, 0xB6, 0x38, 0xFE, 0x8F, 0x00, 0x1E, 0xE0, +0xBF, 0xB8, 0x38, 0xFE, 0x80, 0x9D, 0x5C, 0xA9, 0x26, 0xFE, 0x5C, 0x21, 0x27, 0xFE, 0x5C, 0x94, +0x27, 0xFE, 0x5C, 0x07, 0x28, 0xFE, 0x5C, 0x80, 0x28, 0xFE, 0x5C, 0xF1, 0x28, 0xFE, 0x5C, 0x5D, +0x29, 0xFE, 0x5C, 0xC9, 0x29, 0xFE, 0x5C, 0x3B, 0x2A, 0xFE, 0x5C, 0x8D, 0x2A, 0xFE, 0x5C, 0xDA, +0x2A, 0xFE, 0x5C, 0x27, 0x2B, 0xFE, 0x5C, 0x7A, 0x2B, 0xFE, 0x5C, 0xC5, 0x2B, 0xFE, 0x5C, 0x0B, +0x2C, 0xFE, 0x5C, 0x51, 0x2C, 0xFE, 0x5C, 0xF9, 0x2E, 0xFE, 0x5C, 0x9D, 0x2C, 0xFE, 0xA6, 0x42, +0x7C, 0xE3, 0x38, 0x68, 0x39, 0x64, 0x39, 0x5F, 0x39, 0x59, 0x39, 0x52, 0x39, 0x4A, 0x39, 0x41, +0x39, 0x37, 0x39, 0x32, 0x39, 0x2C, 0x39, 0x25, 0x39, 0x1D, 0x39, 0x15, 0x39, 0x0E, 0x39, 0x08, +0x39, 0x03, 0x39, 0x2A, 0x29, 0x00, 0x01, 0x6B, 0x2A, 0x2A, 0x29, 0x00, 0x03, 0x6B, 0x2A, 0x2A, +0x2A, 0x29, 0x00, 0x07, 0x6B, 0x2A, 0x2A, 0x2A, 0x2A, 0x29, 0x00, 0x0F, 0x6B, 0xEB, 0x4A, 0x4A, +0x4A, 0x29, 0x00, 0x1F, 0x6B, 0xEB, 0x4A, 0x4A, 0x29, 0x00, 0x3F, 0x6B, 0xEB, 0x4A, 0x29, 0x00, +0x7F, 0x6B, 0xEB, 0x29, 0x00, 0xFF, 0x6B, 0x18, 0x69, 0x00, 0x80, 0x2A, 0x29, 0xFF, 0x01, 0xEB, +0x6B, 0xEB, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0xEB, 0x6B, 0xEB, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, +0xEB, 0x6B, 0xEB, 0x4A, 0x4A, 0x4A, 0x4A, 0xEB, 0x6B, 0xEB, 0x4A, 0x4A, 0x4A, 0xEB, 0x6B, 0xEB, +0x4A, 0x4A, 0xEB, 0x6B, 0xEB, 0x4A, 0xEB, 0x6B, 0x6B, 0xA6, 0x42, 0x7C, 0x6E, 0x39, 0x8E, 0x39, +0x92, 0x39, 0x97, 0x39, 0x9D, 0x39, 0xA4, 0x39, 0xAC, 0x39, 0xB4, 0x39, 0xBB, 0x39, 0xC1, 0x39, +0xC6, 0x39, 0xD0, 0x39, 0xD9, 0x39, 0xE1, 0x39, 0xE8, 0x39, 0xEE, 0x39, 0xF3, 0x39, 0xA9, 0x00, +0x00, 0x6B, 0x6A, 0x29, 0x80, 0x00, 0x6B, 0x6A, 0x6A, 0x29, 0xC0, 0x00, 0x6B, 0x6A, 0x6A, 0x6A, +0x29, 0xE0, 0x00, 0x6B, 0x6A, 0x6A, 0x6A, 0x6A, 0x29, 0xF0, 0x00, 0x6B, 0xEB, 0x2A, 0x2A, 0x2A, +0x29, 0xF8, 0x00, 0x6B, 0xEB, 0x2A, 0x2A, 0x29, 0xFC, 0x00, 0x6B, 0xEB, 0x2A, 0x29, 0xFE, 0x00, +0x6B, 0xEB, 0x29, 0xFF, 0x00, 0x6B, 0xEB, 0x6A, 0x08, 0x0A, 0x28, 0x6A, 0x29, 0xFF, 0x80, 0x6B, +0xEB, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xEB, 0x6B, 0xEB, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xEB, +0x6B, 0xEB, 0x0A, 0x0A, 0x0A, 0x0A, 0xEB, 0x6B, 0xEB, 0x0A, 0x0A, 0x0A, 0xEB, 0x6B, 0xEB, 0x0A, +0x0A, 0xEB, 0x6B, 0xEB, 0x0A, 0xEB, 0x6B, 0x20, 0x94, 0x3A, 0xA5, 0x00, 0xA0, 0x02, 0x00, 0xC5, +0x1C, 0x10, 0x02, 0xA5, 0x1C, 0xC5, 0x14, 0x10, 0x02, 0xA5, 0x14, 0xD7, 0x54, 0x10, 0x02, 0xB7, +0x54, 0xD7, 0x64, 0x10, 0x02, 0xB7, 0x64, 0x85, 0x00, 0xA5, 0x02, 0xC8, 0xC8, 0xC5, 0x1E, 0x10, +0x02, 0xA5, 0x1E, 0xC5, 0x16, 0x10, 0x02, 0xA5, 0x16, 0xD7, 0x54, 0x10, 0x02, 0xB7, 0x54, 0xD7, +0x64, 0x10, 0x02, 0xB7, 0x64, 0x85, 0x02, 0xA5, 0x04, 0xC8, 0xC8, 0xC5, 0x20, 0x30, 0x02, 0xA5, +0x20, 0xC5, 0x18, 0x30, 0x02, 0xA5, 0x18, 0xD7, 0x54, 0x30, 0x02, 0xB7, 0x54, 0xD7, 0x64, 0x30, +0x02, 0xB7, 0x64, 0x85, 0x04, 0xA5, 0x06, 0xC8, 0xC8, 0xC5, 0x22, 0x30, 0x02, 0xA5, 0x22, 0xC5, +0x1A, 0x30, 0x02, 0xA5, 0x1A, 0xD7, 0x54, 0x30, 0x02, 0xB7, 0x54, 0xD7, 0x64, 0x30, 0x02, 0xB7, +0x64, 0x85, 0x06, 0xA5, 0x00, 0xC5, 0x04, 0x10, 0x08, 0xA5, 0x02, 0xC5, 0x06, 0x10, 0x02, 0x18, +0x6B, 0x38, 0x6B, 0xA5, 0x00, 0x85, 0xA6, 0xA5, 0x02, 0x85, 0xA8, 0xA5, 0x04, 0x85, 0xAA, 0xA5, +0x06, 0x85, 0xAC, 0x60, 0xA5, 0xA6, 0x85, 0x00, 0xA5, 0xA8, 0x85, 0x02, 0xA5, 0xAA, 0x85, 0x04, +0xA5, 0xAC, 0x85, 0x06, 0x60, 0x0B, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, +0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x02, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, +0x00, 0x3F, 0xC0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3F, 0xFF, 0x00, +0x00, 0x3C, 0xF0, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, +0x00, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xF0, 0x00, +0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xC0, +0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x7B, 0xAA, 0x0B, +0x18, 0x69, 0x00, 0x01, 0x5B, 0xBF, 0x0A, 0x00, 0x00, 0xAA, 0xA9, 0x00, 0x04, 0xA0, 0x00, 0x80, +0x20, 0x24, 0x11, 0x90, 0x03, 0x4C, 0x37, 0x3C, 0x86, 0xB0, 0x84, 0xB2, 0xA0, 0x02, 0x00, 0xB7, +0xB0, 0x85, 0xB6, 0xA7, 0xB0, 0x85, 0xB4, 0x20, 0x39, 0x3C, 0xB0, 0x4B, 0x48, 0x48, 0xF4, 0x0A, +0x00, 0xA2, 0x03, 0x11, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8F, 0xFC, 0x1F, 0xE0, 0x68, 0x8F, 0xFE, +0x1F, 0xE0, 0xF4, 0x18, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0xCE, 0x3F, 0xA2, 0x03, 0x10, 0x22, 0x00, +0x00, 0xE1, 0xF4, 0x0A, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0x4E, 0x40, 0xA2, 0x03, 0x10, 0x22, 0x00, +0x00, 0xE1, 0xF4, 0x0C, 0x00, 0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, 0xE1, 0xA9, 0x00, 0x80, 0x85, +0x52, 0x2B, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0x2B, 0x6B, 0x7B, 0x38, 0xE9, 0x00, 0x01, 0xAA, 0xBF, +0x08, 0x00, 0x00, 0x85, 0x6A, 0x64, 0xCE, 0xA9, 0xFF, 0xFF, 0x85, 0xCC, 0x24, 0x69, 0x30, 0x08, +0xF4, 0xFE, 0x00, 0xF4, 0xA5, 0x3A, 0x80, 0x06, 0xF4, 0xFE, 0x00, 0xF4, 0x5D, 0x3B, 0xA2, 0x04, +0x8E, 0x22, 0x00, 0x00, 0xE1, 0x60, 0x20, 0xB3, 0x0D, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x08, 0x78, +0xA2, 0x04, 0x90, 0x22, 0x00, 0x00, 0xE1, 0x20, 0x39, 0x3C, 0xB0, 0x0B, 0xA2, 0x04, 0x91, 0x22, +0x00, 0x00, 0xE1, 0x28, 0x4C, 0x3F, 0xFF, 0x28, 0xAA, 0x4C, 0x42, 0xFF, 0xA0, 0x04, 0x00, 0xB7, +0xB0, 0x09, 0x00, 0x80, 0x97, 0xB0, 0xA7, 0xB0, 0x85, 0xB4, 0xA0, 0x02, 0x00, 0xB7, 0xB0, 0x85, +0xB6, 0x60, 0xA0, 0x04, 0x00, 0xB7, 0xB0, 0x29, 0xFF, 0x7F, 0x97, 0xB0, 0x60, 0x0B, 0x7B, 0x18, +0x69, 0x00, 0x01, 0x5B, 0xF4, 0x0D, 0x00, 0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, 0xE1, 0x64, 0x52, +0xD4, 0xB2, 0xD4, 0xB0, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x0A, 0x00, 0xAF, 0xFE, +0x1F, 0xE0, 0x48, 0xAF, 0xFC, 0x1F, 0xE0, 0x48, 0xA2, 0x03, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x2B, +0x60, 0xA2, 0x00, 0x00, 0x24, 0x69, 0x30, 0x16, 0xA9, 0x08, 0x00, 0x85, 0xEC, 0x20, 0x14, 0x3D, +0xA5, 0xEC, 0x18, 0x69, 0x08, 0x00, 0x85, 0xEC, 0xE0, 0x18, 0x00, 0x90, 0xF0, 0x60, 0xA9, 0x04, +0x00, 0x85, 0xEC, 0x20, 0x14, 0x3D, 0xA5, 0xEC, 0x18, 0x69, 0x04, 0x00, 0x85, 0xEC, 0xE0, 0x38, +0x00, 0x90, 0xF0, 0x60, 0xA5, 0x74, 0x85, 0xDC, 0xA5, 0x76, 0x85, 0xDE, 0xB5, 0x7C, 0x85, 0xE0, +0xB5, 0x7E, 0x85, 0xE2, 0xDA, 0x20, 0x45, 0x3D, 0xFA, 0xA5, 0x70, 0x85, 0xDC, 0xA5, 0x72, 0x85, +0xDE, 0xB5, 0x78, 0x85, 0xE0, 0xB5, 0x7A, 0x85, 0xE2, 0xDA, 0x20, 0x45, 0x3D, 0xFA, 0x8A, 0x18, +0x69, 0x08, 0x00, 0xAA, 0x60, 0xA5, 0x5E, 0x85, 0xEA, 0xA5, 0x60, 0x3A, 0x85, 0xE8, 0x64, 0xDA, +0xA0, 0x00, 0x00, 0xB7, 0xDC, 0x85, 0xE4, 0xA6, 0xEC, 0x22, 0x6B, 0x39, 0xFE, 0x85, 0xD8, 0xA5, +0xE4, 0xA6, 0xEC, 0x22, 0xE0, 0x38, 0xFE, 0x05, 0xDA, 0x97, 0xE0, 0xA5, 0xD8, 0x85, 0xDA, 0xC8, +0xC8, 0xC6, 0xE8, 0x10, 0xDE, 0xA5, 0x60, 0x0A, 0xAA, 0x18, 0x65, 0xDC, 0x85, 0xDC, 0x8A, 0x18, +0x65, 0xE0, 0x85, 0xE0, 0xC6, 0xEA, 0x10, 0xC1, 0x60, 0x20, 0xB3, 0x0D, 0x18, 0x69, 0x00, 0x01, +0x5B, 0x08, 0x78, 0x24, 0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, 0x04, 0x22, 0xD0, 0x1F, 0xE0, 0x20, +0x55, 0x3E, 0x48, 0x20, 0xA2, 0x3C, 0xA3, 0x01, 0x0A, 0x0A, 0x0A, 0x24, 0x69, 0x10, 0x01, 0x0A, +0x38, 0xE3, 0x01, 0xF4, 0x00, 0x00, 0x48, 0xD4, 0xB2, 0xD4, 0xB0, 0xA2, 0x02, 0x19, 0x22, 0x00, +0x00, 0xE1, 0x90, 0x16, 0x48, 0x20, 0x8C, 0x3C, 0x24, 0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, 0x04, +0x22, 0xCC, 0x1F, 0xE0, 0xFA, 0x68, 0x28, 0x4C, 0x6E, 0xFF, 0x20, 0x8C, 0x3C, 0xFA, 0xA3, 0x0A, +0x85, 0x6C, 0xA3, 0x0C, 0x85, 0x6E, 0xA7, 0x6C, 0x85, 0x5E, 0xA0, 0x02, 0x00, 0xB7, 0x6C, 0x85, +0x60, 0xA5, 0x6C, 0x18, 0x69, 0x04, 0x00, 0x85, 0x70, 0xA5, 0x6E, 0x85, 0x72, 0x8A, 0x85, 0xB8, +0x38, 0xE5, 0x5E, 0x38, 0xE5, 0x5E, 0xA8, 0x18, 0x65, 0x70, 0x85, 0x74, 0xA5, 0x72, 0x85, 0x76, +0xB7, 0x74, 0x85, 0xC2, 0xC8, 0xC8, 0xB7, 0x74, 0x85, 0xC4, 0xA5, 0xB4, 0x18, 0x65, 0xB8, 0x85, +0x78, 0xA5, 0xB6, 0x69, 0x00, 0x00, 0x85, 0x7A, 0xA2, 0x00, 0x00, 0xB5, 0x78, 0x18, 0x65, 0xB8, +0x95, 0x7C, 0xB5, 0x7A, 0x69, 0x00, 0x00, 0x95, 0x7E, 0xE8, 0xE8, 0xE8, 0xE8, 0xE0, 0x34, 0x00, +0x90, 0xE9, 0x20, 0xE1, 0x3C, 0x24, 0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, 0x04, 0x22, 0xCC, 0x1F, +0xE0, 0x28, 0x4C, 0x6B, 0xFF, 0x0B, 0x3B, 0x5B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA7, 0x0E, +0x48, 0xA0, 0x02, 0x00, 0xB7, 0x0E, 0x1A, 0x0A, 0x48, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, +0x68, 0xFA, 0x2B, 0x60, 0x20, 0xB3, 0x0D, 0x18, 0x69, 0x00, 0x01, 0x5B, 0xA5, 0x6C, 0x83, 0x09, +0xA5, 0x6E, 0x83, 0x0B, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, 0x0D, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x08, +0x78, 0x24, 0xCE, 0x10, 0x08, 0x64, 0xCE, 0xA5, 0xCC, 0x30, 0x02, 0xC6, 0xCC, 0xE6, 0xCC, 0x30, +0x0A, 0xA5, 0xCC, 0xD0, 0x04, 0x22, 0xCC, 0x1F, 0xE0, 0x64, 0xCC, 0x28, 0x4C, 0x3F, 0xFF, 0x20, +0xB3, 0x0D, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x08, 0x78, 0xA5, 0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, +0x04, 0x22, 0xD0, 0x1F, 0xE0, 0xC6, 0xCC, 0x28, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, 0x0D, 0x18, 0x69, +0x00, 0x01, 0x5B, 0x08, 0x78, 0xA5, 0xCC, 0x30, 0x08, 0xA5, 0xCE, 0x30, 0x04, 0x22, 0xD0, 0x1F, +0xE0, 0xA9, 0x00, 0x80, 0x85, 0xCE, 0x28, 0x4C, 0x3F, 0xFF, 0x0B, 0x7B, 0xAA, 0x18, 0x69, 0x00, +0x01, 0x5B, 0x8B, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0x64, 0xEE, 0x24, 0xCC, 0x30, 0x6A, 0x24, 0xCE, +0x30, 0x66, 0xBD, 0x0E, 0x00, 0xC9, 0x00, 0x20, 0xD0, 0x5E, 0xBD, 0x0F, 0x00, 0xC9, 0x20, 0xE1, +0xD0, 0x56, 0xA9, 0x00, 0x80, 0x04, 0xEE, 0xBD, 0x00, 0x00, 0x38, 0xFD, 0x14, 0x00, 0xC5, 0xF8, +0x10, 0x02, 0xA5, 0xF8, 0x85, 0xF0, 0xBD, 0x02, 0x00, 0x38, 0xFD, 0x16, 0x00, 0xC5, 0xFA, 0x10, +0x02, 0xA5, 0xFA, 0x85, 0xF2, 0xBD, 0x04, 0x00, 0x38, 0xFD, 0x14, 0x00, 0xC5, 0xFC, 0x30, 0x02, +0xA5, 0xFC, 0x85, 0xF4, 0xBD, 0x06, 0x00, 0x38, 0xFD, 0x16, 0x00, 0xC5, 0xFE, 0x30, 0x02, 0xA5, +0xFE, 0x85, 0xF6, 0xA5, 0xF4, 0xC5, 0xF0, 0x30, 0x0F, 0xA5, 0xF6, 0xC5, 0xF2, 0x30, 0x09, 0x22, +0xD0, 0x1F, 0xE0, 0xA9, 0x00, 0x40, 0x04, 0xEE, 0xAB, 0x2B, 0x6B, 0x0B, 0x7B, 0xAA, 0x18, 0x69, +0x00, 0x01, 0x5B, 0x24, 0xEE, 0x70, 0x0B, 0xA9, 0x00, 0x20, 0x25, 0xEE, 0xF0, 0x08, 0x22, 0xD0, +0x1F, 0xE0, 0x22, 0xCC, 0x1F, 0xE0, 0x64, 0xEE, 0x2B, 0x6B, 0x20, 0xB3, 0x0D, 0x18, 0x69, 0x00, +0x01, 0x5B, 0x24, 0xCC, 0x30, 0x0A, 0x24, 0xCE, 0x30, 0x06, 0xDA, 0x22, 0xD0, 0x1F, 0xE0, 0xFA, +0xA3, 0x09, 0x85, 0x56, 0xA3, 0x0B, 0x85, 0x58, 0x24, 0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, 0x04, +0x22, 0xCC, 0x1F, 0xE0, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x08, +0x78, 0xA3, 0x0A, 0xF0, 0x03, 0xA9, 0x00, 0x80, 0x85, 0x52, 0x28, 0x4C, 0x60, 0xFF, 0xAF, 0xCA, +0x03, 0xE1, 0x48, 0xAF, 0xC8, 0x03, 0xE1, 0x48, 0x0B, 0x3B, 0x5B, 0xA0, 0x10, 0x00, 0xB7, 0x03, +0xF0, 0x60, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x24, 0x52, 0x10, 0x2A, 0xA5, 0x54, 0xF0, 0x03, 0x20, +0xA4, 0x40, 0xA3, 0x0C, 0x85, 0x5C, 0xA3, 0x0A, 0x85, 0x5A, 0xC9, 0xC8, 0x00, 0x90, 0x03, 0xA9, +0x00, 0x00, 0xAA, 0xBF, 0x00, 0x9D, 0xE1, 0x09, 0x40, 0x00, 0x9F, 0x00, 0x9D, 0xE1, 0xA9, 0x00, +0x80, 0x85, 0x54, 0x80, 0x2D, 0x24, 0xEE, 0x30, 0x0C, 0x24, 0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, +0x04, 0x22, 0xD0, 0x1F, 0xE0, 0xA3, 0x0A, 0x85, 0x56, 0xA3, 0x0C, 0x85, 0x58, 0x24, 0xCC, 0x30, +0x0A, 0x64, 0xCE, 0x24, 0xEE, 0x30, 0x06, 0x22, 0xCC, 0x1F, 0xE0, 0x80, 0x05, 0xA9, 0x00, 0x20, +0x04, 0xEE, 0x2B, 0x68, 0x68, 0x8B, 0xFA, 0x7A, 0x68, 0x68, 0x5A, 0xDA, 0xAB, 0x6B, 0x08, 0xC2, +0x30, 0xAF, 0xCA, 0x03, 0xE1, 0x48, 0xAF, 0xC8, 0x03, 0xE1, 0x48, 0x0B, 0x3B, 0x5B, 0xA0, 0x10, +0x00, 0xB7, 0x03, 0x18, 0x69, 0x00, 0x01, 0x5B, 0x20, 0xA4, 0x40, 0x24, 0xEE, 0x30, 0x0C, 0x24, +0xCC, 0x30, 0x08, 0x24, 0xCE, 0x30, 0x04, 0x22, 0xD0, 0x1F, 0xE0, 0xA5, 0x5A, 0x85, 0x56, 0xA5, +0x5C, 0x85, 0x58, 0x24, 0xCC, 0x30, 0x0A, 0x64, 0xCE, 0x24, 0xEE, 0x30, 0x06, 0x22, 0xCC, 0x1F, +0xE0, 0x80, 0x05, 0xA9, 0x00, 0x20, 0x04, 0xEE, 0x2B, 0x68, 0x68, 0x28, 0xA9, 0xDF, 0x8F, 0x32, +0xC0, 0x00, 0x18, 0x6B, 0xA5, 0x5A, 0xC9, 0xC8, 0x00, 0x90, 0x03, 0xA9, 0x00, 0x00, 0xAA, 0xBF, +0x00, 0x9D, 0xE1, 0x29, 0xBF, 0xFF, 0x9F, 0x00, 0x9D, 0xE1, 0x64, 0x54, 0x60, 0x8B, 0xF4, 0xE1, +0xE1, 0xAB, 0xAB, 0xA5, 0x56, 0x38, 0xE5, 0xC2, 0x85, 0x62, 0x85, 0xF8, 0x85, 0xD6, 0x18, 0x65, +0x5E, 0x85, 0x66, 0x85, 0xFC, 0xA5, 0x58, 0x38, 0xE5, 0xC4, 0x85, 0x64, 0x85, 0xFA, 0xA5, 0x60, +0x0A, 0x0A, 0x24, 0x69, 0x10, 0x01, 0x0A, 0x18, 0x65, 0x64, 0x85, 0x68, 0x85, 0xFE, 0x18, 0xA9, +0xFC, 0xFF, 0x24, 0x69, 0x10, 0x01, 0x0A, 0xA8, 0x25, 0xFA, 0x85, 0xFA, 0x98, 0x25, 0xFE, 0xB0, +0x05, 0x69, 0x04, 0x00, 0x80, 0x03, 0x69, 0x07, 0x00, 0x85, 0xFE, 0x24, 0x69, 0x30, 0x12, 0xA5, +0x64, 0x0A, 0xA5, 0x64, 0x6A, 0x29, 0xFE, 0xFF, 0x85, 0xD0, 0xA5, 0x64, 0x29, 0x03, 0x00, 0x80, +0x13, 0xA5, 0x64, 0x0A, 0x08, 0xA5, 0x64, 0x6A, 0x28, 0x6A, 0x29, 0xFE, 0xFF, 0x85, 0xD0, 0xA5, +0x64, 0x29, 0x07, 0x00, 0x0A, 0x0A, 0x0A, 0xAA, 0xB5, 0x70, 0x85, 0xBA, 0xB5, 0x71, 0x85, 0xBB, +0xB5, 0x74, 0x85, 0xBE, 0xB5, 0x75, 0x85, 0xBF, 0xA5, 0xB4, 0x85, 0xC6, 0xA5, 0xB5, 0x85, 0xC7, +0xA5, 0x62, 0x85, 0xD6, 0xA5, 0xD6, 0x10, 0x03, 0x4C, 0xB4, 0x41, 0xC9, 0xC8, 0x00, 0x30, 0x03, +0x4C, 0xD0, 0x41, 0xC5, 0x66, 0x30, 0x03, 0x4C, 0xD0, 0x41, 0xA5, 0x60, 0x3A, 0x85, 0xE8, 0xA5, +0xD0, 0x85, 0xD2, 0xA5, 0xD6, 0x0A, 0xAA, 0xBF, 0x74, 0xBD, 0xFF, 0x85, 0xCA, 0x64, 0xD4, 0xA4, +0xD2, 0x30, 0x27, 0xC0, 0xA0, 0x00, 0x10, 0x22, 0xB1, 0xCA, 0xA4, 0xD4, 0x97, 0xC6, 0xB7, 0xBE, +0xBB, 0xA4, 0xD2, 0x11, 0xCA, 0x9B, 0x57, 0xBA, 0xA4, 0xD2, 0x91, 0xCA, 0xE8, 0xE8, 0x86, 0xD4, +0xC8, 0xC8, 0x84, 0xD2, 0xC6, 0xE8, 0x10, 0xD7, 0x80, 0x0A, 0xE6, 0xD2, 0xE6, 0xD2, 0xE6, 0xD4, +0xE6, 0xD4, 0x80, 0xF0, 0xE6, 0xD6, 0xA5, 0x60, 0x0A, 0xAA, 0x18, 0x65, 0xBA, 0x85, 0xBA, 0x8A, +0x18, 0x65, 0xBE, 0x85, 0xBE, 0x8A, 0x1A, 0x1A, 0x18, 0x65, 0xC6, 0x85, 0xC6, 0x4C, 0x54, 0x41, +0xAB, 0x6B, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xA5, 0x62, 0x85, 0xD6, 0xA5, 0xB4, 0x85, 0xC6, +0xA5, 0xB5, 0x85, 0xC7, 0x64, 0xD4, 0xA5, 0xD6, 0x10, 0x03, 0x4C, 0x3A, 0x42, 0xC9, 0xC8, 0x00, +0x30, 0x03, 0x4C, 0x48, 0x42, 0xC5, 0x66, 0x30, 0x03, 0x4C, 0x48, 0x42, 0xA5, 0x60, 0x3A, 0x85, +0xE8, 0xA5, 0xD0, 0x85, 0xD2, 0xA5, 0xD6, 0x0A, 0xAA, 0xBF, 0x74, 0xBD, 0xFF, 0x85, 0xCA, 0x64, +0xD4, 0xA4, 0xD2, 0x30, 0x1B, 0xC0, 0xA0, 0x00, 0x10, 0x16, 0xBB, 0xA4, 0xD4, 0xB7, 0xC6, 0xC8, +0xC8, 0x84, 0xD4, 0x9B, 0x91, 0xCA, 0xC8, 0xC8, 0x84, 0xD2, 0xC6, 0xE8, 0x10, 0xE3, 0x80, 0x0A, +0xE6, 0xD2, 0xE6, 0xD2, 0xE6, 0xD4, 0xE6, 0xD4, 0x80, 0xF0, 0xE6, 0xD6, 0xA5, 0x60, 0x1A, 0x0A, +0x18, 0x65, 0xC6, 0x85, 0xC6, 0x4C, 0xE6, 0x41, 0xAB, 0x6B, 0xA2, 0x00, 0x00, 0x80, 0x0D, 0xA2, +0x01, 0x00, 0x80, 0x08, 0xA2, 0x02, 0x00, 0x80, 0x03, 0xA2, 0x03, 0x00, 0x20, 0xB3, 0x0D, 0xA3, +0x09, 0x85, 0x70, 0xA3, 0x0B, 0x85, 0x72, 0x22, 0x89, 0x42, 0xFE, 0xAA, 0x4C, 0x6E, 0xFF, 0x20, +0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, 0xA3, 0x0D, 0x85, 0x70, 0xA3, 0x0F, 0x85, 0x72, 0xA2, 0x04, +0x00, 0x22, 0x89, 0x42, 0xFE, 0xAA, 0x4C, 0x84, 0xFF, 0x86, 0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x04, +0x5C, 0x20, 0x1E, 0xE0, 0x8B, 0xA0, 0x1C, 0x00, 0xB7, 0x2A, 0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, +0x6B, 0xA9, 0x80, 0x00, 0x85, 0x3A, 0x22, 0xF8, 0x1E, 0xE0, 0x90, 0x01, 0x6B, 0xA5, 0x38, 0xD0, +0x0C, 0x20, 0x21, 0x54, 0x90, 0x12, 0x22, 0x84, 0x1F, 0xE0, 0x90, 0x0C, 0x6B, 0x4C, 0xAB, 0x21, +0xA9, 0x80, 0x00, 0x85, 0x3A, 0x4C, 0xAB, 0x21, 0x20, 0xC0, 0x23, 0x20, 0xC9, 0x45, 0xA7, 0x74, +0xC9, 0x0A, 0x00, 0xD0, 0x20, 0xA0, 0x02, 0x00, 0xB7, 0x74, 0x85, 0xA6, 0xC8, 0xC8, 0xB7, 0x74, +0x85, 0xA8, 0xC8, 0xC8, 0xB7, 0x74, 0x85, 0xAA, 0xC8, 0xC8, 0xB7, 0x74, 0x85, 0xAC, 0x20, 0xD4, +0x45, 0x5C, 0x2C, 0x1F, 0xE0, 0x20, 0xD4, 0x45, 0xA0, 0x44, 0x00, 0xB7, 0x24, 0x48, 0xC8, 0xC8, +0xB7, 0x24, 0x48, 0xD4, 0x72, 0xD4, 0x70, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x04, 0x67, +0x22, 0x00, 0x00, 0xE1, 0x0B, 0x3B, 0x5B, 0xD4, 0x09, 0xD4, 0x07, 0xD4, 0x05, 0xD4, 0x03, 0xA2, +0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xD4, 0x05, 0xD4, 0x03, 0xD4, 0x0B, 0xD4, 0x0D, 0xA2, 0x04, +0x70, 0x22, 0x00, 0x00, 0xE1, 0xD4, 0x09, 0xD4, 0x07, 0xD4, 0x05, 0xD4, 0x03, 0xD4, 0x05, 0xD4, +0x03, 0xA2, 0x04, 0x73, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x03, 0xA6, 0x05, 0x2B, 0x7A, 0x7A, 0x7A, +0x7A, 0x7A, 0x7A, 0x85, 0x70, 0x86, 0x72, 0x22, 0xC0, 0x42, 0xFE, 0xD4, 0x72, 0xD4, 0x70, 0xA2, +0x04, 0x68, 0x22, 0x00, 0x00, 0xE1, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0x8B, 0x22, 0xC4, 0x1E, 0xE0, +0x22, 0xE8, 0x1E, 0xE0, 0x22, 0x70, 0x1E, 0xE0, 0x20, 0xE6, 0x23, 0x20, 0x0E, 0x24, 0x22, 0xD0, +0x1E, 0xE0, 0x22, 0x00, 0x1E, 0xE0, 0xA5, 0x40, 0x1A, 0xC5, 0xAA, 0x10, 0x07, 0x85, 0x40, 0x20, +0x41, 0x24, 0x80, 0xE7, 0xAB, 0x6B, 0xA0, 0x02, 0x00, 0xA2, 0x00, 0x00, 0xB7, 0x74, 0x95, 0x00, +0xC8, 0xC8, 0xE8, 0xE8, 0xC0, 0x0A, 0x00, 0x90, 0xF3, 0x60, 0x20, 0xB3, 0x0D, 0xA9, 0x0A, 0x00, +0xA6, 0x0A, 0xA0, 0x00, 0x00, 0x20, 0x24, 0x11, 0xB0, 0x1B, 0x86, 0x50, 0x84, 0x52, 0x8A, 0x83, +0x09, 0x98, 0x83, 0x0B, 0x20, 0xA7, 0x45, 0xA9, 0x0A, 0x00, 0x87, 0x54, 0x20, 0x15, 0x44, 0x20, +0xB2, 0x45, 0xA9, 0x00, 0x00, 0xAA, 0x4C, 0x42, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0xAA, 0xA3, +0x0B, 0x48, 0xDA, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xAA, 0x4C, 0x6E, 0xFF, 0x20, 0xB3, +0x0D, 0xA3, 0x09, 0x85, 0x50, 0xA3, 0x0B, 0x85, 0x52, 0x20, 0xA7, 0x45, 0xA9, 0x0A, 0x00, 0xC7, +0x54, 0xF0, 0x05, 0x20, 0xDA, 0x45, 0xB0, 0x09, 0x20, 0x15, 0x44, 0x20, 0xB2, 0x45, 0x4C, 0x6B, +0xFF, 0xAA, 0x4C, 0x6E, 0xFF, 0xA0, 0x02, 0x00, 0xA9, 0x00, 0x00, 0x97, 0x54, 0xC8, 0xC8, 0xC0, +0x0A, 0x00, 0x90, 0xF7, 0x60, 0x20, 0xB3, 0x0D, 0xA3, 0x11, 0x85, 0x50, 0xA3, 0x13, 0x85, 0x52, +0x20, 0xA7, 0x45, 0xA9, 0x0A, 0x00, 0xC7, 0x54, 0xF0, 0x05, 0x20, 0xDA, 0x45, 0xB0, 0x22, 0xA0, +0x02, 0x00, 0xA3, 0x0D, 0x97, 0x54, 0xC8, 0xC8, 0xA3, 0x0F, 0x97, 0x54, 0xC8, 0xC8, 0xA3, 0x09, +0x97, 0x54, 0xC8, 0xC8, 0xA3, 0x0B, 0x97, 0x54, 0x20, 0x65, 0x44, 0x20, 0xB2, 0x45, 0x4C, 0x55, +0xFF, 0xAA, 0x4C, 0x58, 0xFF, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0xA0, 0x06, 0x00, 0xD7, 0x54, 0x10, +0x0D, 0xA0, 0x04, 0x00, 0xB7, 0x54, 0xA0, 0x08, 0x00, 0xD7, 0x54, 0x10, 0x01, 0x60, 0x20, 0x15, +0x44, 0x80, 0xFA, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0x85, 0x50, 0xA3, 0x0F, 0x85, 0x52, 0x20, 0xA7, +0x45, 0xA9, 0x0A, 0x00, 0xC7, 0x54, 0xF0, 0x05, 0x20, 0xDA, 0x45, 0xB0, 0x1F, 0xA3, 0x09, 0x85, +0x2A, 0xA3, 0x0B, 0x85, 0x2C, 0xA0, 0x00, 0x00, 0xB7, 0x2A, 0xC8, 0xC8, 0x97, 0x54, 0xC0, 0x08, +0x00, 0x90, 0xF5, 0x20, 0x65, 0x44, 0x20, 0xB2, 0x45, 0x4C, 0x81, 0xFF, 0xAA, 0x4C, 0x84, 0xFF, +0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0x85, 0x50, 0xA3, 0x0F, 0x85, 0x52, 0x20, 0xA7, 0x45, 0xA3, 0x09, +0x85, 0x60, 0xA3, 0x0B, 0x85, 0x62, 0x20, 0xB8, 0x45, 0xA7, 0x54, 0xC7, 0x64, 0xF0, 0x05, 0x20, +0xE9, 0x45, 0xB0, 0x1E, 0xD4, 0x56, 0xD4, 0x54, 0xD4, 0x66, 0xD4, 0x64, 0xF4, 0x00, 0x00, 0xA7, +0x54, 0x48, 0xA2, 0x02, 0x2B, 0x22, 0x00, 0x00, 0xE1, 0x20, 0xB2, 0x45, 0x20, 0xC3, 0x45, 0x4C, +0x81, 0xFF, 0xAA, 0x4C, 0x84, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x50, 0xA3, 0x0B, 0x85, +0x52, 0x20, 0xA7, 0x45, 0xA3, 0x0D, 0x85, 0x60, 0xA3, 0x0F, 0x85, 0x62, 0x20, 0xB8, 0x45, 0xA7, +0x54, 0xC7, 0x64, 0xD0, 0x1B, 0xA8, 0x88, 0x88, 0xB7, 0x54, 0xD7, 0x64, 0xD0, 0x12, 0x88, 0x88, +0xD0, 0xF6, 0xA9, 0xFF, 0xFF, 0x83, 0x11, 0x20, 0xB2, 0x45, 0x20, 0xC3, 0x45, 0x4C, 0x81, 0xFF, +0xA9, 0x00, 0x00, 0x80, 0xF0, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x50, 0xA3, 0x0B, 0x85, 0x52, +0x20, 0xA7, 0x45, 0xA7, 0x54, 0xC9, 0x0A, 0x00, 0xD0, 0x23, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0xA0, +0x06, 0x00, 0xD7, 0x54, 0x10, 0x0C, 0xA0, 0x04, 0x00, 0xB7, 0x54, 0xA0, 0x08, 0x00, 0xD7, 0x54, +0x30, 0x0B, 0xA9, 0xFF, 0xFF, 0x83, 0x0D, 0x20, 0xB2, 0x45, 0x4C, 0x6B, 0xFF, 0xA9, 0x00, 0x00, +0x80, 0xF3, 0x85, 0x2A, 0x86, 0x2C, 0xA0, 0x04, 0x00, 0xB7, 0x2A, 0x09, 0x00, 0x80, 0x97, 0x2A, +0x88, 0x88, 0xB7, 0x2A, 0xAA, 0xA7, 0x2A, 0x60, 0x85, 0x2A, 0x86, 0x2C, 0xA0, 0x04, 0x00, 0xB7, +0x2A, 0x29, 0xFF, 0x7F, 0x97, 0x2A, 0x60, 0xA2, 0x50, 0x00, 0x20, 0x07, 0x46, 0x85, 0x54, 0x86, +0x56, 0x60, 0xA2, 0x50, 0x00, 0x4C, 0x22, 0x46, 0xA2, 0x60, 0x00, 0x20, 0x07, 0x46, 0x85, 0x64, +0x86, 0x66, 0x60, 0xA2, 0x60, 0x00, 0x4C, 0x22, 0x46, 0xA2, 0x70, 0x00, 0x20, 0x07, 0x46, 0x85, +0x74, 0x86, 0x76, 0x60, 0xA2, 0x70, 0x00, 0x4C, 0x22, 0x46, 0xA2, 0x50, 0x00, 0x20, 0x35, 0x46, +0xB0, 0x06, 0x85, 0x54, 0x86, 0x56, 0xA7, 0x54, 0x60, 0xA2, 0x60, 0x00, 0x20, 0x35, 0x46, 0xB0, +0x06, 0x85, 0x64, 0x86, 0x66, 0xA7, 0x64, 0x60, 0xA2, 0x70, 0x00, 0x20, 0x35, 0x46, 0xB0, 0x06, +0x85, 0x74, 0x86, 0x76, 0xA7, 0x74, 0x60, 0xB5, 0x00, 0x85, 0x2A, 0xB5, 0x02, 0x85, 0x2C, 0xA0, +0x04, 0x00, 0xB7, 0x2A, 0x09, 0x00, 0x80, 0x97, 0x2A, 0xA0, 0x02, 0x00, 0xB7, 0x2A, 0xAA, 0xA7, +0x2A, 0x60, 0xB5, 0x00, 0x85, 0x2A, 0xB5, 0x02, 0x85, 0x2C, 0xA0, 0x04, 0x00, 0xB7, 0x2A, 0x29, +0xFF, 0x7F, 0x97, 0x2A, 0x60, 0x48, 0xF4, 0x00, 0x00, 0x48, 0x20, 0x22, 0x46, 0xD4, 0x2C, 0xD4, +0x2A, 0xA2, 0x02, 0x19, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x0D, 0x20, 0x0F, 0x46, 0x85, 0x2A, 0x86, +0x2C, 0x68, 0x87, 0x2A, 0xA5, 0x2A, 0x60, 0x7A, 0xA2, 0xFF, 0xFF, 0x60, 0x48, 0xDA, 0xA6, 0x0A, +0xA0, 0x00, 0x00, 0x20, 0x24, 0x11, 0xB0, 0x0D, 0x86, 0x2A, 0x84, 0x2C, 0xFA, 0x94, 0x02, 0xA4, +0x2A, 0x94, 0x00, 0x80, 0xD5, 0x7A, 0x7A, 0x60, 0x20, 0x91, 0x46, 0x20, 0xA2, 0x46, 0x22, 0xA4, +0x1E, 0xE0, 0x6B, 0x20, 0xD4, 0x45, 0x20, 0xC3, 0x45, 0x20, 0xB2, 0x45, 0x22, 0x16, 0x47, 0xFE, +0x6B, 0xA0, 0x18, 0x00, 0xB7, 0x24, 0x85, 0x50, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0x52, 0x20, 0xA7, +0x45, 0x60, 0xA0, 0x1C, 0x00, 0xB7, 0x24, 0x85, 0x60, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0x62, 0x20, +0xB8, 0x45, 0x60, 0xA5, 0x3C, 0xA6, 0x3E, 0x20, 0x82, 0x45, 0x85, 0x4C, 0x86, 0x4E, 0x18, 0x65, +0x28, 0x85, 0x5C, 0xA5, 0x4E, 0x69, 0x00, 0x00, 0x85, 0x5E, 0xA5, 0x28, 0x4A, 0x18, 0x65, 0x5C, +0x85, 0x6C, 0xA5, 0x5E, 0x69, 0x00, 0x00, 0x85, 0x6E, 0xA5, 0x28, 0x4A, 0x18, 0x65, 0x6C, 0x85, +0x7C, 0xA5, 0x6E, 0x69, 0x00, 0x00, 0x85, 0x7E, 0xA5, 0x28, 0x4A, 0x18, 0x65, 0x7C, 0x85, 0x58, +0xA5, 0x7E, 0x69, 0x00, 0x00, 0x85, 0x5A, 0xA5, 0x58, 0x18, 0x69, 0x1A, 0x00, 0x85, 0x68, 0xA5, +0x5A, 0x69, 0x00, 0x00, 0x85, 0x6A, 0xA5, 0x68, 0x18, 0x69, 0x1A, 0x00, 0x85, 0x78, 0xA5, 0x6A, +0x69, 0x00, 0x00, 0x85, 0x7A, 0x6B, 0xA5, 0x3C, 0xA6, 0x3E, 0x20, 0x98, 0x45, 0x6B, 0x64, 0xA4, +0xA5, 0x02, 0x85, 0x90, 0xA5, 0x06, 0x85, 0x92, 0xA5, 0x16, 0x85, 0x94, 0xA5, 0x54, 0x85, 0x80, +0xA5, 0x56, 0x85, 0x82, 0xA5, 0x5C, 0x85, 0x88, 0xA5, 0x5E, 0x85, 0x8A, 0xA5, 0x58, 0x85, 0x84, +0xA5, 0x5A, 0x85, 0x86, 0x22, 0xD4, 0x1E, 0xE0, 0xA5, 0x64, 0x85, 0x80, 0xA5, 0x66, 0x85, 0x82, +0xA5, 0x6C, 0x85, 0x88, 0xA5, 0x6E, 0x85, 0x8A, 0xA5, 0x68, 0x85, 0x84, 0xA5, 0x6A, 0x85, 0x86, +0x22, 0xD4, 0x1E, 0xE0, 0xA5, 0x74, 0x85, 0x80, 0xA5, 0x76, 0x85, 0x82, 0xA5, 0x7C, 0x85, 0x88, +0xA5, 0x7E, 0x85, 0x8A, 0xA5, 0x78, 0x85, 0x84, 0xA5, 0x7A, 0x85, 0x86, 0x22, 0xD4, 0x1E, 0xE0, +0x6B, 0x64, 0x9E, 0xA5, 0x58, 0x85, 0x84, 0xA5, 0x5A, 0x85, 0x86, 0x22, 0xD8, 0x1E, 0xE0, 0xF0, +0x02, 0xE6, 0x9E, 0xA5, 0x68, 0x85, 0x84, 0xA5, 0x6A, 0x85, 0x86, 0x22, 0xD8, 0x1E, 0xE0, 0xF0, +0x02, 0xE6, 0x9E, 0xA5, 0x78, 0x85, 0x84, 0xA5, 0x7A, 0x85, 0x86, 0x22, 0xD8, 0x1E, 0xE0, 0xF0, +0x02, 0xE6, 0x9E, 0xA5, 0x9E, 0xF0, 0x07, 0x20, 0x75, 0x48, 0x22, 0xE4, 0x1E, 0xE0, 0x6B, 0x64, +0xA4, 0xA5, 0x02, 0x85, 0x90, 0xA5, 0x06, 0x85, 0x92, 0xA5, 0x16, 0x85, 0x94, 0xA5, 0x54, 0x85, +0x80, 0xA5, 0x56, 0x85, 0x82, 0xA5, 0x5C, 0x85, 0x88, 0xA5, 0x5E, 0x85, 0x8A, 0xA5, 0x58, 0x85, +0x84, 0xA5, 0x5A, 0x85, 0x86, 0x22, 0xD4, 0x1E, 0xE0, 0xA5, 0x64, 0x85, 0x80, 0xA5, 0x66, 0x85, +0x82, 0xA5, 0x6C, 0x85, 0x88, 0xA5, 0x6E, 0x85, 0x8A, 0xA5, 0x68, 0x85, 0x84, 0xA5, 0x6A, 0x85, +0x86, 0x22, 0xD4, 0x1E, 0xE0, 0x6B, 0x64, 0x9E, 0xA5, 0x58, 0x85, 0x84, 0xA5, 0x5A, 0x85, 0x86, +0x22, 0xD8, 0x1E, 0xE0, 0xF0, 0x02, 0xE6, 0x9E, 0xA5, 0x68, 0x85, 0x84, 0xA5, 0x6A, 0x85, 0x86, +0x22, 0xD8, 0x1E, 0xE0, 0xF0, 0x02, 0xE6, 0x9E, 0xA5, 0x9E, 0xF0, 0x07, 0x20, 0x75, 0x48, 0x22, +0xE0, 0x1E, 0xE0, 0x6B, 0x64, 0xA4, 0xA5, 0x02, 0x85, 0x90, 0xA5, 0x06, 0x85, 0x92, 0xA5, 0x16, +0x85, 0x94, 0xA5, 0x54, 0x85, 0x80, 0xA5, 0x56, 0x85, 0x82, 0xA5, 0x5C, 0x85, 0x88, 0xA5, 0x5E, +0x85, 0x8A, 0xA5, 0x58, 0x85, 0x84, 0xA5, 0x5A, 0x85, 0x86, 0x22, 0xD4, 0x1E, 0xE0, 0x6B, 0xA5, +0x58, 0x85, 0x84, 0xA5, 0x5A, 0x85, 0x86, 0x22, 0xD8, 0x1E, 0xE0, 0xF0, 0x07, 0x20, 0x75, 0x48, +0x22, 0xDC, 0x1E, 0xE0, 0x6B, 0xA5, 0x90, 0x38, 0xE5, 0x94, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, +0x85, 0x9A, 0xA5, 0x92, 0x3A, 0x38, 0xE5, 0x94, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0x9C, +0x60, 0xA6, 0x90, 0xA5, 0x92, 0x20, 0x53, 0x49, 0x20, 0x3F, 0x49, 0xA7, 0x80, 0xC9, 0x0A, 0x00, +0xF0, 0x3E, 0xE6, 0xA4, 0xA9, 0x00, 0x00, 0x87, 0x84, 0xA5, 0x80, 0xA0, 0x02, 0x00, 0x97, 0x84, +0xA5, 0x82, 0xC8, 0xC8, 0x97, 0x84, 0x20, 0x2A, 0x49, 0x20, 0x16, 0x49, 0xA9, 0x01, 0xC0, 0xC8, +0xC8, 0x97, 0x84, 0xA0, 0x02, 0x00, 0xB7, 0x80, 0xA0, 0x12, 0x00, 0x97, 0x84, 0xA5, 0x90, 0xC8, +0xC8, 0x97, 0x84, 0xA5, 0x92, 0xC8, 0xC8, 0x97, 0x84, 0xA5, 0x94, 0xC8, 0xC8, 0x97, 0x84, 0x6B, +0xA9, 0x00, 0x80, 0x87, 0x84, 0xA5, 0x9A, 0xA0, 0x02, 0x00, 0x97, 0x84, 0xA5, 0x96, 0xC8, 0xC8, +0x97, 0x84, 0xA5, 0x9C, 0xC8, 0xC8, 0x97, 0x84, 0xA5, 0x98, 0xC8, 0xC8, 0x97, 0x84, 0x20, 0x16, +0x49, 0xA0, 0x02, 0x00, 0xB7, 0x80, 0xA0, 0x10, 0x00, 0x97, 0x84, 0xA0, 0x06, 0x00, 0xB7, 0x80, +0xA0, 0x12, 0x00, 0x97, 0x84, 0x6B, 0xA5, 0x88, 0xA0, 0x0A, 0x00, 0x97, 0x84, 0xA5, 0x8A, 0xC8, +0xC8, 0x97, 0x84, 0xA5, 0x28, 0xC8, 0xC8, 0x97, 0x84, 0x60, 0xA5, 0x80, 0x18, 0x69, 0x0A, 0x00, +0xA0, 0x06, 0x00, 0x97, 0x84, 0xA5, 0x82, 0x69, 0x00, 0x00, 0xC8, 0xC8, 0x97, 0x84, 0x60, 0xA4, +0x9A, 0xF0, 0x02, 0x88, 0x88, 0xA9, 0x00, 0x00, 0x97, 0x88, 0xC8, 0xC8, 0xC4, 0x9C, 0x90, 0xF8, +0xF0, 0xF6, 0x60, 0x9B, 0x3A, 0x38, 0xE5, 0x94, 0xAA, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, +0x9C, 0x8A, 0x29, 0x0F, 0x00, 0x0A, 0xAA, 0xBF, 0xA7, 0x49, 0xFE, 0x85, 0x98, 0x98, 0x38, 0xE5, +0x94, 0xAA, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0x9A, 0x8A, 0x29, 0x0F, 0x00, 0x0A, 0xAA, +0xBF, 0x87, 0x49, 0xFE, 0x85, 0x96, 0x60, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 0xFF, 0x1F, 0xFF, 0x0F, +0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x01, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x3F, 0x00, 0x1F, 0x00, +0x0F, 0x00, 0x07, 0x00, 0x03, 0x00, 0x01, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xF8, +0x00, 0xFC, 0x00, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, 0xFF, 0xF0, 0xFF, +0xF8, 0xFF, 0xFC, 0xFF, 0xFE, 0xFF, 0xFF, 0xA7, 0x84, 0x10, 0x03, 0x4C, 0xA1, 0x4A, 0xA5, 0x40, +0xA0, 0x10, 0x00, 0xD7, 0x84, 0x30, 0x0A, 0xA0, 0x12, 0x00, 0xD7, 0x84, 0x10, 0x3A, 0x4C, 0xD8, +0x4A, 0xA0, 0x02, 0x00, 0xB7, 0x84, 0x18, 0x69, 0x0A, 0x00, 0xAA, 0xC8, 0xC8, 0xB7, 0x84, 0x69, +0x00, 0x00, 0xA0, 0x08, 0x00, 0x97, 0x84, 0x88, 0x88, 0x8A, 0x97, 0x84, 0x20, 0xDB, 0x4A, 0xA6, +0x90, 0xA5, 0x92, 0x20, 0x53, 0x49, 0xA0, 0x0A, 0x00, 0xB7, 0x84, 0x85, 0x88, 0xC8, 0xC8, 0xB7, +0x84, 0x85, 0x8A, 0x20, 0x3F, 0x49, 0x80, 0x03, 0x20, 0xDB, 0x4A, 0xA7, 0x8C, 0xA0, 0x10, 0x00, +0x97, 0x84, 0xA5, 0x8C, 0xA6, 0x8E, 0x1A, 0xD0, 0x01, 0xE8, 0x1A, 0xD0, 0x01, 0xE8, 0x85, 0x8C, +0x86, 0x8E, 0xA7, 0x8C, 0xC9, 0xFF, 0x3F, 0xF0, 0x39, 0xAA, 0xE6, 0x8C, 0xD0, 0x02, 0xE6, 0x8E, +0xE6, 0x8C, 0xD0, 0x02, 0xE6, 0x8E, 0xA7, 0x8C, 0xE6, 0x8C, 0xD0, 0x02, 0xE6, 0x8E, 0xE6, 0x8C, +0xD0, 0x02, 0xE6, 0x8E, 0xC5, 0x90, 0x30, 0xDA, 0xF0, 0xD8, 0xE4, 0x92, 0x10, 0xD4, 0xE4, 0x90, +0x10, 0x02, 0xA6, 0x90, 0xC5, 0x92, 0x30, 0x02, 0xA5, 0x92, 0x20, 0x53, 0x49, 0x20, 0x17, 0x4B, +0x80, 0xC0, 0xA5, 0x8C, 0xA6, 0x8E, 0x1A, 0xD0, 0x01, 0xE8, 0x1A, 0xD0, 0x01, 0xE8, 0x85, 0x8C, +0x86, 0x8E, 0xA7, 0x8C, 0xA0, 0x12, 0x00, 0x97, 0x84, 0xC5, 0x40, 0xF0, 0x02, 0x10, 0x03, 0x4C, +0x1B, 0x4A, 0xA0, 0x06, 0x00, 0xA5, 0x8C, 0x97, 0x84, 0xC8, 0xC8, 0xA5, 0x8E, 0x97, 0x84, 0x80, +0x34, 0xA5, 0x40, 0xA0, 0x10, 0x00, 0xD7, 0x84, 0x30, 0x1A, 0xA0, 0x12, 0x00, 0xD7, 0x84, 0x10, +0x13, 0xA7, 0x84, 0x29, 0x01, 0x00, 0xD0, 0x20, 0x20, 0xFE, 0x4A, 0xA7, 0x84, 0x09, 0x01, 0x00, +0x87, 0x84, 0x80, 0x11, 0xA7, 0x84, 0x29, 0x01, 0x00, 0xF0, 0x0D, 0x20, 0xFE, 0x4A, 0xA7, 0x84, +0x29, 0xFE, 0xFF, 0x87, 0x84, 0xC2, 0x02, 0x6B, 0xE2, 0x02, 0x6B, 0xA0, 0x14, 0x00, 0xB7, 0x84, +0x85, 0x90, 0xA0, 0x16, 0x00, 0xB7, 0x84, 0x85, 0x92, 0xA0, 0x18, 0x00, 0xB7, 0x84, 0x85, 0x94, +0xA0, 0x06, 0x00, 0xB7, 0x84, 0x85, 0x8C, 0xC8, 0xC8, 0xB7, 0x84, 0x85, 0x8E, 0x60, 0xA0, 0x02, +0x00, 0xB7, 0x84, 0x85, 0x9A, 0xC8, 0xC8, 0xB7, 0x84, 0x85, 0x96, 0xC8, 0xC8, 0xB7, 0x84, 0x85, +0x9C, 0xC8, 0xC8, 0xB7, 0x84, 0x85, 0x98, 0x8B, 0xA0, 0x0A, 0x00, 0xB7, 0x84, 0x85, 0x88, 0x8B, +0xC8, 0xB7, 0x84, 0x83, 0x00, 0xAB, 0x20, 0x2B, 0x4B, 0xAB, 0x60, 0xA5, 0x96, 0xA4, 0x9A, 0xC4, +0x9C, 0x90, 0x02, 0x25, 0x98, 0x51, 0x88, 0x91, 0x88, 0x80, 0x07, 0xA9, 0xFF, 0xFF, 0x51, 0x88, +0x91, 0x88, 0xC8, 0xC8, 0xC4, 0x9C, 0x90, 0xF3, 0xD0, 0x06, 0xA5, 0x98, 0x51, 0x88, 0x91, 0x88, +0x60, 0x24, 0x0B, 0x10, 0x17, 0xA4, 0x9A, 0xF0, 0x02, 0x88, 0x88, 0xB7, 0x5C, 0x37, 0x6C, 0x37, +0x7C, 0x20, 0xD8, 0x4B, 0xC4, 0x9C, 0x90, 0xF3, 0xF0, 0xF1, 0x80, 0x15, 0xA4, 0x9A, 0xF0, 0x02, +0x88, 0x88, 0xB7, 0x5C, 0x37, 0x6C, 0x37, 0x7C, 0x20, 0xFD, 0x4B, 0xC4, 0x9C, 0x90, 0xF3, 0xF0, +0xF1, 0x6B, 0x24, 0x0B, 0x10, 0x15, 0xA4, 0x9A, 0xF0, 0x02, 0x88, 0x88, 0xB7, 0x5C, 0x37, 0x6C, +0x20, 0xD8, 0x4B, 0xC4, 0x9C, 0x90, 0xF5, 0xF0, 0xF3, 0x80, 0x13, 0xA4, 0x9A, 0xF0, 0x02, 0x88, +0x88, 0xB7, 0x5C, 0x37, 0x6C, 0x20, 0xFD, 0x4B, 0xC4, 0x9C, 0x90, 0xF5, 0xF0, 0xF3, 0x6B, 0x24, +0x0B, 0x10, 0x13, 0xA4, 0x9A, 0xF0, 0x02, 0x88, 0x88, 0xB7, 0x5C, 0x20, 0xD8, 0x4B, 0xC4, 0x9C, +0x90, 0xF7, 0xF0, 0xF5, 0x80, 0x11, 0xA4, 0x9A, 0xF0, 0x02, 0x88, 0x88, 0xB7, 0x5C, 0x20, 0xFD, +0x4B, 0xC4, 0x9C, 0x90, 0xF7, 0xF0, 0xF5, 0x6B, 0x48, 0x29, 0xFF, 0x00, 0x0A, 0xAA, 0xBF, 0x3B, +0x50, 0xFE, 0xAA, 0x98, 0x0A, 0xA8, 0x8A, 0x97, 0x4C, 0x68, 0xEB, 0x29, 0xFF, 0x00, 0x0A, 0xAA, +0xBF, 0x3B, 0x50, 0xFE, 0xC8, 0xC8, 0x97, 0x4C, 0x98, 0x4A, 0xA8, 0xC8, 0x60, 0x48, 0x29, 0xFF, +0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0x48, 0xBF, 0x3B, 0x4C, 0xFE, 0xAA, 0x98, 0x0A, +0x0A, 0xA8, 0x8A, 0x97, 0x4C, 0xC8, 0xC8, 0x68, 0x97, 0x4C, 0x68, 0xEB, 0x29, 0xFF, 0x00, 0x0A, +0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0x48, 0xBF, 0x3B, 0x4C, 0xFE, 0xC8, 0xC8, 0x97, 0x4C, 0xC8, +0xC8, 0x68, 0x97, 0x4C, 0xC8, 0xC8, 0x98, 0x4A, 0x4A, 0xA8, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x00, +0x00, 0x0F, 0x0F, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xF0, 0x00, 0x00, +0x00, 0xF0, 0x0F, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, +0x00, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0x00, 0x00, 0x00, +0x0F, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0xFF, 0x00, 0x0F, 0x0F, 0x00, 0x00, +0x0F, 0x0F, 0x0F, 0x00, 0x0F, 0x0F, 0xF0, 0x00, 0x0F, 0x0F, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0x00, +0x0F, 0xF0, 0x0F, 0x00, 0x0F, 0xF0, 0xF0, 0x00, 0x0F, 0xF0, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, +0x0F, 0xFF, 0x0F, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0xF0, 0x00, 0x00, 0x00, +0xF0, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0x00, 0xF0, 0x0F, 0x00, 0x00, +0xF0, 0x0F, 0x0F, 0x00, 0xF0, 0x0F, 0xF0, 0x00, 0xF0, 0x0F, 0xFF, 0x00, 0xF0, 0xF0, 0x00, 0x00, +0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0xF0, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, 0x00, 0x00, +0xF0, 0xFF, 0x0F, 0x00, 0xF0, 0xFF, 0xF0, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, +0xFF, 0x00, 0x0F, 0x00, 0xFF, 0x00, 0xF0, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x0F, 0x00, 0x00, +0xFF, 0x0F, 0x0F, 0x00, 0xFF, 0x0F, 0xF0, 0x00, 0xFF, 0x0F, 0xFF, 0x00, 0xFF, 0xF0, 0x00, 0x00, +0xFF, 0xF0, 0x0F, 0x00, 0xFF, 0xF0, 0xF0, 0x00, 0xFF, 0xF0, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, +0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0F, +0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x0F, 0x00, 0x0F, +0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x0F, 0xF0, 0x0F, 0x00, 0x0F, 0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x0F, +0x00, 0xF0, 0x0F, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xFF, 0x00, 0x0F, +0x00, 0xFF, 0x0F, 0x0F, 0x00, 0xFF, 0xF0, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x00, 0x00, 0x0F, +0x0F, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0xF0, 0x0F, 0x0F, 0x00, 0xFF, 0x0F, 0x0F, 0x0F, 0x00, 0x0F, +0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0x0F, 0x0F, 0x0F, 0xFF, 0x0F, 0x0F, 0xF0, 0x00, 0x0F, +0x0F, 0xF0, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0x0F, 0x0F, 0xF0, 0xFF, 0x0F, 0x0F, 0xFF, 0x00, 0x0F, +0x0F, 0xFF, 0x0F, 0x0F, 0x0F, 0xFF, 0xF0, 0x0F, 0x0F, 0xFF, 0xFF, 0x0F, 0xF0, 0x00, 0x00, 0x0F, +0xF0, 0x00, 0x0F, 0x0F, 0xF0, 0x00, 0xF0, 0x0F, 0xF0, 0x00, 0xFF, 0x0F, 0xF0, 0x0F, 0x00, 0x0F, +0xF0, 0x0F, 0x0F, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0xF0, 0x00, 0x0F, +0xF0, 0xF0, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0x0F, 0xF0, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x00, 0x0F, +0xF0, 0xFF, 0x0F, 0x0F, 0xF0, 0xFF, 0xF0, 0x0F, 0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0x00, 0x00, 0x0F, +0xFF, 0x00, 0x0F, 0x0F, 0xFF, 0x00, 0xF0, 0x0F, 0xFF, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x0F, +0xFF, 0x0F, 0x0F, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, +0xFF, 0xF0, 0x0F, 0x0F, 0xFF, 0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, +0xFF, 0xFF, 0x0F, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0xF0, +0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0x00, 0xF0, +0x00, 0x0F, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0xF0, +0x00, 0xF0, 0x0F, 0xF0, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0xF0, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0xF0, +0x00, 0xFF, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0xF0, +0x0F, 0x00, 0x0F, 0xF0, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0xFF, 0xF0, 0x0F, 0x0F, 0x00, 0xF0, +0x0F, 0x0F, 0x0F, 0xF0, 0x0F, 0x0F, 0xF0, 0xF0, 0x0F, 0x0F, 0xFF, 0xF0, 0x0F, 0xF0, 0x00, 0xF0, +0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xF0, 0xF0, 0x0F, 0xF0, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0xF0, +0x0F, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0xF0, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0xF0, 0x00, 0x00, 0xF0, +0xF0, 0x00, 0x0F, 0xF0, 0xF0, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0xFF, 0xF0, 0xF0, 0x0F, 0x00, 0xF0, +0xF0, 0x0F, 0x0F, 0xF0, 0xF0, 0x0F, 0xF0, 0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0xF0, 0xF0, 0x00, 0xF0, +0xF0, 0xF0, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xF0, 0xF0, 0xFF, 0x00, 0xF0, +0xF0, 0xFF, 0x0F, 0xF0, 0xF0, 0xFF, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xF0, 0xFF, 0x00, 0x00, 0xF0, +0xFF, 0x00, 0x0F, 0xF0, 0xFF, 0x00, 0xF0, 0xF0, 0xFF, 0x00, 0xFF, 0xF0, 0xFF, 0x0F, 0x00, 0xF0, +0xFF, 0x0F, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xF0, 0xFF, 0x0F, 0xFF, 0xF0, 0xFF, 0xF0, 0x00, 0xF0, +0xFF, 0xF0, 0x0F, 0xF0, 0xFF, 0xF0, 0xF0, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xFF, 0x00, 0xF0, +0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, +0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0x00, 0xFF, +0x00, 0x0F, 0x0F, 0xFF, 0x00, 0x0F, 0xF0, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0xF0, 0x00, 0xFF, +0x00, 0xF0, 0x0F, 0xFF, 0x00, 0xF0, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, +0x00, 0xFF, 0x0F, 0xFF, 0x00, 0xFF, 0xF0, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, +0x0F, 0x00, 0x0F, 0xFF, 0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x00, 0xFF, +0x0F, 0x0F, 0x0F, 0xFF, 0x0F, 0x0F, 0xF0, 0xFF, 0x0F, 0x0F, 0xFF, 0xFF, 0x0F, 0xF0, 0x00, 0xFF, +0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0x00, 0xFF, +0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF, +0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xF0, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xFF, +0xF0, 0x0F, 0x0F, 0xFF, 0xF0, 0x0F, 0xF0, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0xF0, 0x00, 0xFF, +0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0xF0, 0xF0, 0xFF, 0xF0, 0xF0, 0xFF, 0xFF, 0xF0, 0xFF, 0x00, 0xFF, +0xF0, 0xFF, 0x0F, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, +0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, +0xFF, 0x0F, 0x0F, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, +0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0xF0, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, +0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x00, +0x0C, 0x00, 0x0F, 0x00, 0x30, 0x00, 0x33, 0x00, 0x3C, 0x00, 0x3F, 0x00, 0xC0, 0x00, 0xC3, 0x00, +0xCC, 0x00, 0xCF, 0x00, 0xF0, 0x00, 0xF3, 0x00, 0xFC, 0x00, 0xFF, 0x03, 0x00, 0x03, 0x03, 0x03, +0x0C, 0x03, 0x0F, 0x03, 0x30, 0x03, 0x33, 0x03, 0x3C, 0x03, 0x3F, 0x03, 0xC0, 0x03, 0xC3, 0x03, +0xCC, 0x03, 0xCF, 0x03, 0xF0, 0x03, 0xF3, 0x03, 0xFC, 0x03, 0xFF, 0x0C, 0x00, 0x0C, 0x03, 0x0C, +0x0C, 0x0C, 0x0F, 0x0C, 0x30, 0x0C, 0x33, 0x0C, 0x3C, 0x0C, 0x3F, 0x0C, 0xC0, 0x0C, 0xC3, 0x0C, +0xCC, 0x0C, 0xCF, 0x0C, 0xF0, 0x0C, 0xF3, 0x0C, 0xFC, 0x0C, 0xFF, 0x0F, 0x00, 0x0F, 0x03, 0x0F, +0x0C, 0x0F, 0x0F, 0x0F, 0x30, 0x0F, 0x33, 0x0F, 0x3C, 0x0F, 0x3F, 0x0F, 0xC0, 0x0F, 0xC3, 0x0F, +0xCC, 0x0F, 0xCF, 0x0F, 0xF0, 0x0F, 0xF3, 0x0F, 0xFC, 0x0F, 0xFF, 0x30, 0x00, 0x30, 0x03, 0x30, +0x0C, 0x30, 0x0F, 0x30, 0x30, 0x30, 0x33, 0x30, 0x3C, 0x30, 0x3F, 0x30, 0xC0, 0x30, 0xC3, 0x30, +0xCC, 0x30, 0xCF, 0x30, 0xF0, 0x30, 0xF3, 0x30, 0xFC, 0x30, 0xFF, 0x33, 0x00, 0x33, 0x03, 0x33, +0x0C, 0x33, 0x0F, 0x33, 0x30, 0x33, 0x33, 0x33, 0x3C, 0x33, 0x3F, 0x33, 0xC0, 0x33, 0xC3, 0x33, +0xCC, 0x33, 0xCF, 0x33, 0xF0, 0x33, 0xF3, 0x33, 0xFC, 0x33, 0xFF, 0x3C, 0x00, 0x3C, 0x03, 0x3C, +0x0C, 0x3C, 0x0F, 0x3C, 0x30, 0x3C, 0x33, 0x3C, 0x3C, 0x3C, 0x3F, 0x3C, 0xC0, 0x3C, 0xC3, 0x3C, +0xCC, 0x3C, 0xCF, 0x3C, 0xF0, 0x3C, 0xF3, 0x3C, 0xFC, 0x3C, 0xFF, 0x3F, 0x00, 0x3F, 0x03, 0x3F, +0x0C, 0x3F, 0x0F, 0x3F, 0x30, 0x3F, 0x33, 0x3F, 0x3C, 0x3F, 0x3F, 0x3F, 0xC0, 0x3F, 0xC3, 0x3F, +0xCC, 0x3F, 0xCF, 0x3F, 0xF0, 0x3F, 0xF3, 0x3F, 0xFC, 0x3F, 0xFF, 0xC0, 0x00, 0xC0, 0x03, 0xC0, +0x0C, 0xC0, 0x0F, 0xC0, 0x30, 0xC0, 0x33, 0xC0, 0x3C, 0xC0, 0x3F, 0xC0, 0xC0, 0xC0, 0xC3, 0xC0, +0xCC, 0xC0, 0xCF, 0xC0, 0xF0, 0xC0, 0xF3, 0xC0, 0xFC, 0xC0, 0xFF, 0xC3, 0x00, 0xC3, 0x03, 0xC3, +0x0C, 0xC3, 0x0F, 0xC3, 0x30, 0xC3, 0x33, 0xC3, 0x3C, 0xC3, 0x3F, 0xC3, 0xC0, 0xC3, 0xC3, 0xC3, +0xCC, 0xC3, 0xCF, 0xC3, 0xF0, 0xC3, 0xF3, 0xC3, 0xFC, 0xC3, 0xFF, 0xCC, 0x00, 0xCC, 0x03, 0xCC, +0x0C, 0xCC, 0x0F, 0xCC, 0x30, 0xCC, 0x33, 0xCC, 0x3C, 0xCC, 0x3F, 0xCC, 0xC0, 0xCC, 0xC3, 0xCC, +0xCC, 0xCC, 0xCF, 0xCC, 0xF0, 0xCC, 0xF3, 0xCC, 0xFC, 0xCC, 0xFF, 0xCF, 0x00, 0xCF, 0x03, 0xCF, +0x0C, 0xCF, 0x0F, 0xCF, 0x30, 0xCF, 0x33, 0xCF, 0x3C, 0xCF, 0x3F, 0xCF, 0xC0, 0xCF, 0xC3, 0xCF, +0xCC, 0xCF, 0xCF, 0xCF, 0xF0, 0xCF, 0xF3, 0xCF, 0xFC, 0xCF, 0xFF, 0xF0, 0x00, 0xF0, 0x03, 0xF0, +0x0C, 0xF0, 0x0F, 0xF0, 0x30, 0xF0, 0x33, 0xF0, 0x3C, 0xF0, 0x3F, 0xF0, 0xC0, 0xF0, 0xC3, 0xF0, +0xCC, 0xF0, 0xCF, 0xF0, 0xF0, 0xF0, 0xF3, 0xF0, 0xFC, 0xF0, 0xFF, 0xF3, 0x00, 0xF3, 0x03, 0xF3, +0x0C, 0xF3, 0x0F, 0xF3, 0x30, 0xF3, 0x33, 0xF3, 0x3C, 0xF3, 0x3F, 0xF3, 0xC0, 0xF3, 0xC3, 0xF3, +0xCC, 0xF3, 0xCF, 0xF3, 0xF0, 0xF3, 0xF3, 0xF3, 0xFC, 0xF3, 0xFF, 0xFC, 0x00, 0xFC, 0x03, 0xFC, +0x0C, 0xFC, 0x0F, 0xFC, 0x30, 0xFC, 0x33, 0xFC, 0x3C, 0xFC, 0x3F, 0xFC, 0xC0, 0xFC, 0xC3, 0xFC, +0xCC, 0xFC, 0xCF, 0xFC, 0xF0, 0xFC, 0xF3, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0xFF, +0x0C, 0xFF, 0x0F, 0xFF, 0x30, 0xFF, 0x33, 0xFF, 0x3C, 0xFF, 0x3F, 0xFF, 0xC0, 0xFF, 0xC3, 0xFF, +0xCC, 0xFF, 0xCF, 0xFF, 0xF0, 0xFF, 0xF3, 0xFF, 0xFC, 0xFF, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, +0x85, 0x2A, 0xA3, 0x0F, 0x85, 0x2C, 0xA7, 0x2A, 0xAA, 0xA0, 0x02, 0x00, 0xB7, 0x2A, 0x85, 0xD8, +0x86, 0xD6, 0xA9, 0x00, 0x00, 0x83, 0x11, 0xA3, 0x09, 0x85, 0xBC, 0xA3, 0x0B, 0x85, 0xBE, 0xA2, +0xBC, 0x00, 0x20, 0x07, 0x46, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xA5, 0xD6, 0xD7, 0xC0, +0x30, 0x45, 0xA0, 0x06, 0x00, 0xD7, 0xC0, 0x10, 0x3E, 0xA5, 0xD8, 0xA0, 0x04, 0x00, 0xD7, 0xC0, +0x30, 0x35, 0xA0, 0x08, 0x00, 0xD7, 0xC0, 0x10, 0x2E, 0xA9, 0x0A, 0x00, 0xC7, 0xC0, 0xD0, 0x07, +0xA9, 0xFF, 0xFF, 0x83, 0x11, 0x80, 0x20, 0xC8, 0xC8, 0xA5, 0xD6, 0xD7, 0xC0, 0x30, 0x18, 0xC8, +0xC8, 0xB7, 0xC0, 0xC9, 0xFF, 0x3F, 0xF0, 0xEF, 0xC5, 0xD8, 0x30, 0x02, 0xD0, 0xF1, 0xA3, 0x11, +0x49, 0xFF, 0xFF, 0x83, 0x11, 0x80, 0xE8, 0xA3, 0x11, 0x49, 0xFF, 0xFF, 0x1A, 0x83, 0x11, 0xA2, +0xBC, 0x00, 0x20, 0x22, 0x46, 0x4C, 0x81, 0xFF, 0x20, 0xB3, 0x0D, 0xA9, 0x00, 0x00, 0x83, 0x11, +0x85, 0xBC, 0x85, 0xBE, 0xA3, 0x09, 0x85, 0x50, 0xA3, 0x0B, 0x85, 0x52, 0xA2, 0x50, 0x00, 0x20, +0x07, 0x46, 0x85, 0x54, 0x86, 0x56, 0xA3, 0x0D, 0x38, 0xE9, 0x02, 0x00, 0x85, 0x64, 0xA3, 0x0F, +0xE9, 0x00, 0x00, 0x85, 0x66, 0x20, 0xC9, 0x5E, 0xA5, 0xAE, 0xC5, 0xB2, 0x10, 0x10, 0xA5, 0xB0, +0xC5, 0xB4, 0x10, 0x0A, 0xA7, 0x54, 0xC9, 0x0A, 0x00, 0xD0, 0x06, 0x82, 0xE7, 0x00, 0x82, 0xE9, +0x00, 0x38, 0xA5, 0xB4, 0xE5, 0xB0, 0x18, 0x69, 0x0F, 0x00, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, +0x85, 0xC4, 0xA2, 0xBC, 0x00, 0x20, 0x5C, 0x46, 0x90, 0x0B, 0x48, 0xA2, 0x50, 0x00, 0x20, 0x22, +0x46, 0xFA, 0x4C, 0x84, 0xFF, 0x85, 0xC0, 0x86, 0xC2, 0xA4, 0xC4, 0x88, 0x88, 0xA9, 0x00, 0x00, +0x97, 0xC0, 0x88, 0x88, 0x10, 0xFA, 0x64, 0xC6, 0xA0, 0x0A, 0x00, 0xA5, 0xAE, 0xD7, 0x54, 0x30, +0x5F, 0xC8, 0xC8, 0xB7, 0x54, 0xC8, 0xC8, 0xC9, 0xFF, 0x3F, 0xF0, 0xEF, 0xC5, 0xB4, 0x10, 0xF3, +0x48, 0xA5, 0xC6, 0x49, 0xFF, 0xFF, 0x85, 0xC6, 0x68, 0xC5, 0xB0, 0x30, 0xE6, 0x5A, 0x38, 0xE5, +0xB0, 0x85, 0x2A, 0x29, 0x0F, 0x00, 0x0A, 0xAA, 0xBF, 0x90, 0x53, 0xFE, 0x85, 0x2C, 0xA5, 0x2A, +0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0xA8, 0xB7, 0xC0, 0x45, 0x2C, 0x97, 0xC0, 0x7A, 0x80, 0xC3, +0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, +0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, +0xA5, 0xC6, 0xD0, 0x41, 0x84, 0x2A, 0xA4, 0xC4, 0x88, 0x88, 0xB7, 0xC0, 0xD0, 0x37, 0x88, 0x88, +0x10, 0xF8, 0xA4, 0x2A, 0xB7, 0x54, 0xC8, 0xC8, 0xC5, 0xB2, 0x10, 0x2E, 0xB7, 0x54, 0xC8, 0xC8, +0xC9, 0xFF, 0x3F, 0xF0, 0xEF, 0xC5, 0xB0, 0x10, 0x09, 0xA5, 0xC6, 0x49, 0xFF, 0xFF, 0x85, 0xC6, +0x80, 0xEA, 0xC5, 0xB4, 0x30, 0x0F, 0xA5, 0xC6, 0xD0, 0x0B, 0xB7, 0x54, 0xC8, 0xC8, 0xC9, 0xFF, +0x3F, 0xD0, 0xF7, 0x80, 0xCF, 0xA9, 0x01, 0x00, 0x83, 0x11, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, +0xA5, 0xC0, 0x05, 0xC2, 0xF0, 0x15, 0xA2, 0xBC, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, 0xA5, +0xBC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x03, 0x4C, 0x81, 0xFF, 0x4C, 0x84, +0xFF, 0xA0, 0x94, 0x00, 0xB7, 0x24, 0x85, 0xBC, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0xBE, 0x05, 0xBC, +0xF0, 0x02, 0x38, 0x60, 0x18, 0x60, 0x97, 0xC0, 0xC8, 0xC8, 0x8A, 0x97, 0xC0, 0xC8, 0xC8, 0x60, +0xA2, 0xBC, 0x00, 0x20, 0x07, 0x46, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xB7, 0xC0, 0x48, +0x18, 0x69, 0x10, 0x00, 0x97, 0xC0, 0xC7, 0xC0, 0x90, 0x16, 0xF0, 0x14, 0xA7, 0xC0, 0x18, 0x69, +0x00, 0x01, 0xB0, 0x31, 0xA2, 0xBC, 0x00, 0x20, 0x35, 0x46, 0xB0, 0x2C, 0x85, 0xC0, 0x86, 0xC2, +0x7A, 0xA6, 0xA8, 0xA5, 0xA6, 0x20, 0x36, 0x54, 0xA6, 0xAC, 0xA5, 0xA6, 0x20, 0x36, 0x54, 0xA6, +0xA8, 0xA5, 0xAA, 0x20, 0x36, 0x54, 0xA6, 0xAC, 0xA5, 0xAA, 0x20, 0x36, 0x54, 0xA2, 0xBC, 0x00, +0x20, 0x22, 0x46, 0x18, 0x6B, 0xA9, 0x33, 0x04, 0x48, 0xA2, 0xBC, 0x00, 0x20, 0x22, 0x46, 0x68, +0x38, 0x6B, 0xA2, 0xBC, 0x00, 0x20, 0x07, 0x46, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xB7, +0xC0, 0x85, 0xC6, 0x38, 0xA5, 0xAC, 0xE5, 0xA8, 0xD0, 0x03, 0x4C, 0xFC, 0x55, 0x85, 0xCA, 0x10, +0x04, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x2A, 0xA5, 0xA6, 0x85, 0xAE, 0xA5, 0xA8, 0x85, 0xB0, 0xA5, +0xAA, 0x85, 0xB2, 0xA5, 0xAC, 0x85, 0xB4, 0x38, 0xA5, 0xB2, 0xE5, 0xAE, 0x85, 0xCC, 0x10, 0x04, +0x49, 0xFF, 0xFF, 0x1A, 0xC5, 0x2A, 0x30, 0x02, 0xA5, 0x2A, 0x1A, 0xC9, 0x00, 0x20, 0xB0, 0x18, +0x0A, 0x0A, 0x0A, 0x18, 0x65, 0xC6, 0xB0, 0x10, 0xC7, 0xC0, 0x90, 0x1D, 0xF0, 0x1B, 0xA2, 0xBC, +0x00, 0x20, 0x35, 0x46, 0x90, 0x0F, 0x80, 0x03, 0xA9, 0x33, 0x04, 0x48, 0xA2, 0xBC, 0x00, 0x20, +0x22, 0x46, 0x68, 0x38, 0x6B, 0x85, 0xC0, 0x86, 0xC2, 0xA5, 0xAE, 0xC5, 0xB2, 0xD0, 0x13, 0xA5, +0xAE, 0xA6, 0xB0, 0xA4, 0xC6, 0x20, 0x36, 0x54, 0xA5, 0xB2, 0xA6, 0xB4, 0x20, 0x36, 0x54, 0x4C, +0xF1, 0x55, 0x30, 0x0E, 0xA6, 0xB2, 0x85, 0xB2, 0x86, 0xAE, 0xA5, 0xB0, 0xA6, 0xB4, 0x85, 0xB4, +0x86, 0xB0, 0xA5, 0xAE, 0x85, 0xD6, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xD4, 0xCA, 0xD4, 0xCC, +0xA2, 0x0B, 0x0E, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0xCE, 0x68, 0x85, 0xD0, 0xA5, 0xB0, 0x85, +0xD4, 0xA9, 0x00, 0x80, 0x85, 0xD2, 0xA5, 0xD0, 0x0A, 0xA5, 0xD0, 0x6A, 0x85, 0x2A, 0xA5, 0xCE, +0x6A, 0x18, 0x65, 0xD2, 0x85, 0xD2, 0xA5, 0x2A, 0x65, 0xD4, 0x85, 0xD4, 0xA5, 0xD0, 0x30, 0x11, +0xD0, 0x16, 0x18, 0xA5, 0xCE, 0x65, 0xD2, 0x85, 0xD2, 0xA5, 0xD0, 0x65, 0xD4, 0x85, 0xD4, 0x80, +0x07, 0x49, 0xFF, 0xFF, 0xF0, 0x02, 0xE6, 0xD4, 0xA5, 0xB0, 0x85, 0xD8, 0xA4, 0xC6, 0xA5, 0xD8, +0xC5, 0xD4, 0xF0, 0x1A, 0xA5, 0xD6, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0xD8, 0x97, 0xC0, 0xC8, 0xC8, +0xA5, 0xD6, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0xD4, 0x97, 0xC0, 0x85, 0xD8, 0xC8, 0xC8, 0xE6, 0xD6, +0x18, 0xA5, 0xCE, 0x65, 0xD2, 0x85, 0xD2, 0xA5, 0xD0, 0x65, 0xD4, 0x85, 0xD4, 0xA5, 0xD6, 0xC5, +0xB2, 0xD0, 0xCB, 0xA5, 0xD8, 0xC5, 0xB4, 0xF0, 0x18, 0xA5, 0xD6, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, +0xD8, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0xD6, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0xB4, 0x97, 0xC0, 0xC8, +0xC8, 0x98, 0xA0, 0x02, 0x00, 0x97, 0xC0, 0x4A, 0x4A, 0x3A, 0x85, 0xC4, 0xA2, 0xBC, 0x00, 0x20, +0x22, 0x46, 0x18, 0x6B, 0xA2, 0xBC, 0x00, 0x20, 0x07, 0x46, 0x85, 0xC0, 0x86, 0xC2, 0xA2, 0x50, +0x00, 0x20, 0x07, 0x46, 0x85, 0x54, 0x86, 0x56, 0xA0, 0x02, 0x00, 0xB7, 0xC0, 0x85, 0xC6, 0xA7, +0x54, 0x0A, 0x18, 0x65, 0xC6, 0xC7, 0x54, 0x90, 0x22, 0xF0, 0x20, 0x69, 0x00, 0x01, 0xB0, 0x0A, +0xA2, 0xBC, 0x00, 0x20, 0x35, 0x46, 0x90, 0x0F, 0x80, 0x03, 0xA9, 0x33, 0x04, 0x48, 0xA2, 0xBC, +0x00, 0x20, 0x22, 0x46, 0x68, 0x38, 0x6B, 0x85, 0xC0, 0x86, 0xC2, 0xA9, 0x0A, 0x00, 0xC7, 0x54, +0xD0, 0x5C, 0xA0, 0x08, 0x00, 0xB7, 0x54, 0x48, 0xA0, 0x06, 0x00, 0xB7, 0x54, 0x48, 0xA0, 0x04, +0x00, 0xB7, 0x54, 0x48, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0xA4, 0xC6, 0xAA, 0x97, 0xC0, 0xC8, 0xC8, +0xA3, 0x01, 0x97, 0xC0, 0xC8, 0xC8, 0x8A, 0x97, 0xC0, 0xC8, 0xC8, 0xA3, 0x05, 0x97, 0xC0, 0xC8, +0xC8, 0xA3, 0x03, 0xAA, 0x97, 0xC0, 0xC8, 0xC8, 0x68, 0x97, 0xC0, 0xC8, 0xC8, 0x68, 0x97, 0xC0, +0xC8, 0xC8, 0x68, 0x97, 0xC0, 0xC8, 0xC8, 0x98, 0xA0, 0x02, 0x00, 0x97, 0xC0, 0x4A, 0x4A, 0x3A, +0x85, 0xC4, 0xA2, 0xBC, 0x00, 0x20, 0x22, 0x46, 0x18, 0x6B, 0xA5, 0xC6, 0x80, 0xEA, 0xA0, 0x0A, +0x00, 0xB7, 0x54, 0xC9, 0xFF, 0x3F, 0xF0, 0xF2, 0x85, 0x2A, 0xC8, 0xC8, 0xB7, 0x54, 0xC8, 0xC8, +0xC9, 0xFF, 0x3F, 0xF0, 0xEC, 0xAA, 0xB7, 0x54, 0x85, 0x2C, 0xC8, 0xC8, 0x84, 0xC8, 0xA4, 0xC6, +0xA5, 0x2A, 0x97, 0xC0, 0xC8, 0xC8, 0x8A, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0x2A, 0x97, 0xC0, 0xC8, +0xC8, 0xA5, 0x2C, 0x97, 0xC0, 0xC8, 0xC8, 0x84, 0xC6, 0xA4, 0xC8, 0x80, 0xCF, 0xA6, 0xC4, 0xF0, +0x17, 0xA0, 0x04, 0x00, 0xB7, 0xC0, 0x85, 0xE0, 0xA0, 0x06, 0x00, 0xB7, 0xC0, 0x85, 0xE2, 0xA0, +0x08, 0x00, 0x84, 0xDC, 0x64, 0xDA, 0x80, 0x35, 0x6B, 0xA5, 0xDA, 0xD0, 0x08, 0x38, 0xA5, 0xDC, +0xE9, 0x08, 0x00, 0x85, 0xDE, 0x82, 0x81, 0x00, 0xCA, 0xCA, 0xF0, 0xED, 0xA5, 0xDA, 0xD0, 0x0A, +0xE6, 0xDA, 0xA5, 0xDC, 0x38, 0xE9, 0x08, 0x00, 0x85, 0xDE, 0xB7, 0xC0, 0x85, 0xE0, 0xC8, 0xC8, +0xB7, 0xC0, 0x85, 0xE2, 0xC8, 0xC8, 0x84, 0xDC, 0xE0, 0x01, 0x00, 0xF0, 0x40, 0xA4, 0xDC, 0xB7, +0xC0, 0x85, 0x2A, 0xC8, 0xC8, 0xB7, 0xC0, 0x85, 0x2C, 0xC8, 0xC8, 0x84, 0xDC, 0xC5, 0xE2, 0xD0, +0x06, 0xA5, 0x2A, 0xC5, 0xE0, 0xF0, 0xC1, 0xA5, 0xDA, 0xF0, 0x10, 0xA4, 0xDE, 0xA5, 0xE0, 0x97, +0xC0, 0xC8, 0xC8, 0xA5, 0xE2, 0x97, 0xC0, 0xC8, 0xC8, 0x84, 0xDE, 0xCA, 0xF0, 0x2B, 0xE0, 0x01, +0x00, 0xF0, 0x12, 0xA5, 0x2A, 0x85, 0xE0, 0xA5, 0x2C, 0x85, 0xE2, 0x80, 0xC0, 0xA5, 0xE0, 0x85, +0x2A, 0xA5, 0xE2, 0x85, 0x2C, 0xA5, 0xDA, 0xF0, 0x17, 0xA5, 0x2A, 0xA4, 0xDE, 0x97, 0xC0, 0xA5, +0x2C, 0xC8, 0xC8, 0x97, 0xC0, 0xC8, 0xC8, 0x84, 0xDE, 0xA5, 0xDE, 0x4A, 0x4A, 0x3A, 0x85, 0xC4, +0x6B, 0xA0, 0x04, 0x00, 0x84, 0xD0, 0xA2, 0x01, 0x00, 0x86, 0xD8, 0x98, 0x48, 0xA5, 0xC4, 0x0A, +0x0A, 0x48, 0x68, 0x85, 0xD2, 0x68, 0x85, 0xD0, 0xC6, 0xD8, 0xA5, 0xD0, 0x85, 0xC6, 0xA5, 0xD2, +0x85, 0xC8, 0x18, 0x65, 0xC6, 0x6A, 0x29, 0xFC, 0xFF, 0xA8, 0xB7, 0xC0, 0x85, 0xD4, 0xC8, 0xC8, +0xB7, 0xC0, 0x85, 0xD6, 0xA4, 0xC6, 0xA5, 0xD4, 0x80, 0x04, 0xC8, 0xC8, 0xC8, 0xC8, 0xD7, 0xC0, +0x30, 0x16, 0xD0, 0xF6, 0xA5, 0xD6, 0xC8, 0xC8, 0xD7, 0xC0, 0x30, 0x08, 0xF0, 0x06, 0xC8, 0xC8, +0xA5, 0xD4, 0x80, 0xEA, 0x88, 0x88, 0xA5, 0xD4, 0x84, 0xC6, 0xA4, 0xC8, 0x80, 0x04, 0x88, 0x88, +0x88, 0x88, 0xD7, 0xC0, 0x30, 0xF8, 0xD0, 0x14, 0xA5, 0xD6, 0xC8, 0xC8, 0xD7, 0xC0, 0x10, 0x0A, +0x98, 0x38, 0xE9, 0x06, 0x00, 0xA8, 0xA5, 0xD4, 0x80, 0xE8, 0x88, 0x88, 0x84, 0xC8, 0xC4, 0xC6, +0x90, 0x43, 0xF0, 0x2A, 0xB7, 0xC0, 0x85, 0x2A, 0xC8, 0xC8, 0xB7, 0xC0, 0x85, 0x2C, 0xA4, 0xC6, +0xB7, 0xC0, 0xAA, 0xC8, 0xC8, 0xB7, 0xC0, 0xA4, 0xC8, 0xC8, 0xC8, 0x97, 0xC0, 0x8A, 0x88, 0x88, +0x97, 0xC0, 0xA4, 0xC6, 0xA5, 0x2A, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0x2C, 0x97, 0xC0, 0xA4, 0xC6, +0xC8, 0xC8, 0xC8, 0xC8, 0x84, 0xC6, 0xA4, 0xC8, 0x88, 0x88, 0x88, 0x88, 0x84, 0xC8, 0xC4, 0xC6, +0x90, 0x03, 0x4C, 0xD4, 0x57, 0x38, 0xA5, 0xD2, 0xE5, 0xC6, 0x85, 0x2A, 0x38, 0xA5, 0xC8, 0xE5, +0xD0, 0xC5, 0x2A, 0xB0, 0x12, 0xA5, 0xC6, 0xC5, 0xD2, 0xB0, 0x06, 0xE6, 0xD8, 0x48, 0xA5, 0xD2, +0x48, 0xA5, 0xC8, 0x85, 0xD2, 0x80, 0x10, 0xA5, 0xD0, 0xC5, 0xC8, 0xB0, 0x06, 0xE6, 0xD8, 0x48, +0xA5, 0xC8, 0x48, 0xA5, 0xC6, 0x85, 0xD0, 0xA5, 0xD0, 0xC5, 0xD2, 0xB0, 0x03, 0x4C, 0xBA, 0x57, +0xA5, 0xD8, 0xF0, 0x03, 0x4C, 0xB2, 0x57, 0x6B, 0xA9, 0x0A, 0x00, 0x87, 0x54, 0xA9, 0x00, 0x00, +0xA0, 0x02, 0x00, 0x97, 0x54, 0xA0, 0x04, 0x00, 0x97, 0x54, 0xA0, 0x06, 0x00, 0x97, 0x54, 0xA0, +0x08, 0x00, 0x97, 0x54, 0xA9, 0x04, 0x00, 0xC5, 0xC4, 0x90, 0x2E, 0xD0, 0x26, 0xA8, 0xB7, 0xC0, +0xA0, 0x02, 0x00, 0x97, 0x54, 0xA0, 0x06, 0x00, 0xB7, 0xC0, 0xA0, 0x04, 0x00, 0x97, 0x54, 0xA0, +0x10, 0x00, 0xB7, 0xC0, 0xA0, 0x06, 0x00, 0x97, 0x54, 0xA0, 0x12, 0x00, 0xB7, 0xC0, 0xA0, 0x08, +0x00, 0x97, 0x54, 0xA0, 0x0A, 0x00, 0x4C, 0xAB, 0x59, 0xA0, 0x04, 0x00, 0xB7, 0xC0, 0xA0, 0x02, +0x00, 0x97, 0x54, 0xA0, 0x06, 0x00, 0xB7, 0xC0, 0x85, 0xCA, 0x85, 0xCC, 0xA6, 0xC4, 0xCA, 0xF0, +0x16, 0xC8, 0xC8, 0xC8, 0xC8, 0xB7, 0xC0, 0xC5, 0xCA, 0x10, 0x04, 0x85, 0xCA, 0x80, 0xEF, 0xC5, +0xCC, 0x30, 0xEB, 0x85, 0xCC, 0x80, 0xE7, 0xA0, 0x04, 0x00, 0xA5, 0xCA, 0x97, 0x54, 0xA0, 0x08, +0x00, 0xA5, 0xCC, 0x97, 0x54, 0xA5, 0xC4, 0x0A, 0x0A, 0xA8, 0xB7, 0xC0, 0xA0, 0x06, 0x00, 0x97, +0x54, 0xA5, 0xC4, 0x1A, 0x0A, 0x0A, 0x69, 0x0C, 0x00, 0xA2, 0x50, 0x00, 0x20, 0x35, 0x46, 0xB0, +0x14, 0x85, 0x54, 0x86, 0x56, 0xA0, 0x04, 0x00, 0x84, 0xC6, 0xA9, 0x0A, 0x00, 0x85, 0xC8, 0xB7, +0xC0, 0xA6, 0xC4, 0x80, 0x16, 0x6B, 0xA4, 0xC6, 0xB7, 0xC0, 0xC5, 0xCE, 0xF0, 0x1F, 0x84, 0xC6, +0xA4, 0xC8, 0xA9, 0xFF, 0x3F, 0x97, 0x54, 0xC8, 0xC8, 0x84, 0xC8, 0xA4, 0xC6, 0xB7, 0xC0, 0x84, +0xC6, 0xA4, 0xC8, 0x85, 0xCE, 0x97, 0x54, 0xC8, 0xC8, 0x84, 0xC8, 0xA4, 0xC6, 0xC8, 0xC8, 0xB7, +0xC0, 0xC8, 0xC8, 0x84, 0xC6, 0xA4, 0xC8, 0x97, 0x54, 0xC8, 0xC8, 0x84, 0xC8, 0xCA, 0xD0, 0xC6, +0xA9, 0xFF, 0x3F, 0x97, 0x54, 0xC8, 0xC8, 0x97, 0x54, 0xC8, 0xC8, 0x98, 0xA2, 0x50, 0x00, 0x20, +0x35, 0x46, 0x85, 0x54, 0x86, 0x56, 0x6B, 0x20, 0xB3, 0x0D, 0x20, 0x21, 0x54, 0xB0, 0x40, 0xA0, +0x96, 0x00, 0xB7, 0x24, 0xD0, 0x39, 0xA2, 0xBC, 0x00, 0xA9, 0x00, 0x01, 0x20, 0x5C, 0x46, 0xB0, +0x2A, 0x85, 0xC0, 0x86, 0xC2, 0xA5, 0xBC, 0xA0, 0x94, 0x00, 0x97, 0x24, 0xA5, 0xBE, 0xA0, 0x96, +0x00, 0x97, 0x24, 0xA0, 0x02, 0x00, 0xA9, 0x04, 0x00, 0x97, 0xC0, 0xA2, 0xBC, 0x00, 0x20, 0x22, +0x46, 0xA2, 0x04, 0x27, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0x3F, 0xFF, 0xAA, 0x4C, 0x42, 0xFF, 0xA2, +0x31, 0x40, 0x4C, 0x42, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x21, 0x54, 0x90, 0x72, 0xA9, 0x00, 0x00, +0xA0, 0x94, 0x00, 0x97, 0x24, 0xA0, 0x96, 0x00, 0x97, 0x24, 0xA2, 0x04, 0x28, 0x22, 0x00, 0x00, +0xE1, 0xA2, 0xBC, 0x00, 0x20, 0x07, 0x46, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xB7, 0xC0, +0x4A, 0x4A, 0x3A, 0x85, 0xC4, 0xA3, 0x09, 0x85, 0x50, 0xA3, 0x0B, 0x85, 0x52, 0xA2, 0x50, 0x00, +0x20, 0x07, 0x46, 0x85, 0x54, 0x86, 0x56, 0x22, 0x90, 0x1F, 0xE0, 0x22, 0x8C, 0x1F, 0xE0, 0x22, +0x94, 0x1F, 0xE0, 0x64, 0xC4, 0x90, 0x04, 0xE6, 0xC4, 0x85, 0xBA, 0xA2, 0xBC, 0x00, 0x20, 0x22, +0x46, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, +0x22, 0x00, 0x00, 0xE1, 0xA4, 0xC4, 0xF0, 0x05, 0xA6, 0xBA, 0x4C, 0x6E, 0xFF, 0xB0, 0x03, 0x4C, +0x6B, 0xFF, 0xAA, 0x4C, 0x6E, 0xFF, 0xA9, 0x0A, 0x00, 0xC7, 0x54, 0xD0, 0x49, 0xA5, 0xE0, 0x85, +0xD0, 0xA5, 0xE2, 0x85, 0xD2, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0x87, 0xD0, 0xA0, 0x04, 0x00, 0xB7, +0x54, 0xA0, 0x02, 0x00, 0x97, 0xD0, 0xA0, 0x0A, 0x00, 0x97, 0xD0, 0xA0, 0x06, 0x00, 0xB7, 0x54, +0xA0, 0x08, 0x00, 0x97, 0xD0, 0xB7, 0x54, 0xA0, 0x04, 0x00, 0x97, 0xD0, 0xA0, 0x0C, 0x00, 0x97, +0xD0, 0xA9, 0xFF, 0x3F, 0xA0, 0x06, 0x00, 0x97, 0xD0, 0xA0, 0x0E, 0x00, 0x97, 0xD0, 0xA0, 0x10, +0x00, 0x97, 0xD0, 0x64, 0xD4, 0x60, 0xA5, 0x54, 0x85, 0xD0, 0xA5, 0x56, 0x85, 0xD2, 0xA9, 0x0A, +0x00, 0x85, 0xD4, 0x60, 0xA9, 0x0A, 0x00, 0xC7, 0x64, 0xD0, 0x52, 0xA5, 0xE0, 0x85, 0xD6, 0xA5, +0xE2, 0x85, 0xD8, 0xA0, 0x02, 0x00, 0xB7, 0x64, 0xA0, 0x12, 0x00, 0x97, 0xD6, 0xA0, 0x04, 0x00, +0xB7, 0x64, 0xA0, 0x14, 0x00, 0x97, 0xD6, 0xA0, 0x1C, 0x00, 0x97, 0xD6, 0xA0, 0x06, 0x00, 0xB7, +0x64, 0xA0, 0x1A, 0x00, 0x97, 0xD6, 0xA0, 0x08, 0x00, 0xB7, 0x64, 0xA0, 0x16, 0x00, 0x97, 0xD6, +0xA0, 0x1E, 0x00, 0x97, 0xD6, 0xA9, 0xFF, 0x3F, 0xA0, 0x18, 0x00, 0x97, 0xD6, 0xA0, 0x20, 0x00, +0x97, 0xD6, 0xA0, 0x22, 0x00, 0x97, 0xD6, 0xA9, 0x12, 0x00, 0x85, 0xDA, 0x60, 0xA5, 0x64, 0x85, +0xD6, 0xA5, 0x66, 0x85, 0xD8, 0xA9, 0x0A, 0x00, 0x85, 0xDA, 0x60, 0x64, 0x7C, 0x64, 0x7E, 0x80, +0x0E, 0x64, 0x7C, 0xA9, 0xFF, 0xFF, 0x80, 0x05, 0xA9, 0xFF, 0xFF, 0x85, 0x7C, 0x85, 0x7E, 0xA4, +0xF2, 0xB7, 0xEE, 0x85, 0x78, 0xC8, 0xC8, 0x84, 0xF2, 0xA4, 0xF4, 0xB7, 0xE0, 0x85, 0x7A, 0xC8, +0xC8, 0x84, 0xF4, 0xA5, 0x7A, 0xC5, 0x78, 0x30, 0x5C, 0xD0, 0x39, 0xC9, 0xFF, 0x3F, 0xF0, 0x77, +0xA5, 0x7C, 0xC5, 0x7E, 0xD0, 0x0A, 0xA5, 0x78, 0xA4, 0xF6, 0x97, 0xE0, 0xC8, 0xC8, 0x84, 0xF6, +0xA4, 0xF2, 0xB7, 0xEE, 0x85, 0x78, 0xC8, 0xC8, 0x84, 0xF2, 0xA5, 0x7C, 0x49, 0xFF, 0xFF, 0x85, +0x7C, 0xA4, 0xF4, 0xB7, 0xE0, 0x85, 0x7A, 0xC8, 0xC8, 0x84, 0xF4, 0xA5, 0x7E, 0x49, 0xFF, 0xFF, +0x85, 0x7E, 0x80, 0xBF, 0xA5, 0x7E, 0xF0, 0x0A, 0xA5, 0x78, 0xA4, 0xF6, 0x97, 0xE0, 0xC8, 0xC8, +0x84, 0xF6, 0xA4, 0xF2, 0xB7, 0xEE, 0x85, 0x78, 0xC8, 0xC8, 0x84, 0xF2, 0xA5, 0x7C, 0x49, 0xFF, +0xFF, 0x85, 0x7C, 0x80, 0x9E, 0xA5, 0x7C, 0xF0, 0x0A, 0xA5, 0x7A, 0xA4, 0xF6, 0x97, 0xE0, 0xC8, +0xC8, 0x84, 0xF6, 0xA4, 0xF4, 0xB7, 0xE0, 0x85, 0x7A, 0xC8, 0xC8, 0x84, 0xF4, 0xA5, 0x7E, 0x49, +0xFF, 0xFF, 0x85, 0x7E, 0x4C, 0x73, 0x5B, 0xA9, 0xFF, 0x3F, 0xA4, 0xF6, 0x97, 0xE0, 0xC8, 0xC8, +0xC8, 0xC8, 0x84, 0xF6, 0x60, 0xA5, 0xB8, 0x30, 0x41, 0xA4, 0xF2, 0xB7, 0xEE, 0x85, 0x2A, 0xC9, +0xFF, 0x3F, 0xF0, 0x2A, 0xC8, 0xC8, 0xB7, 0xEE, 0xC8, 0xC8, 0x84, 0xF2, 0x38, 0xE5, 0xB8, 0x85, +0x2C, 0xA5, 0x2A, 0x18, 0x65, 0xB8, 0x85, 0x2A, 0xC5, 0x2C, 0x10, 0xDD, 0xA4, 0xF6, 0x97, 0xE0, +0xC8, 0xC8, 0xA5, 0x2C, 0x97, 0xE0, 0xC8, 0xC8, 0x84, 0xF6, 0x80, 0xCD, 0x84, 0xF2, 0xA4, 0xF6, +0xA9, 0xFF, 0x3F, 0x97, 0xE0, 0xC8, 0xC8, 0x84, 0xF6, 0x60, 0xA9, 0x01, 0xC0, 0x85, 0x80, 0xA4, +0xF2, 0xB7, 0xEE, 0xC8, 0xC8, 0x85, 0x2A, 0xC9, 0xFF, 0x3F, 0xF0, 0xE0, 0xB7, 0xEE, 0xC8, 0xC8, +0x84, 0xF2, 0xA4, 0xF6, 0x38, 0xE5, 0xB8, 0x85, 0x2C, 0xA5, 0x2A, 0x18, 0x65, 0xB8, 0xC5, 0x80, +0x10, 0x04, 0x88, 0x88, 0x80, 0x06, 0x97, 0xE0, 0xC8, 0xC8, 0xA5, 0x2C, 0x97, 0xE0, 0xC8, 0xC8, +0x84, 0xF6, 0x80, 0xC9, 0xA4, 0xF2, 0xB7, 0xEE, 0x85, 0x78, 0xC8, 0xC8, 0x84, 0xF2, 0xA4, 0xF4, +0xB7, 0xE0, 0x85, 0x7A, 0xC8, 0xC8, 0x84, 0xF4, 0xA4, 0xF6, 0xA5, 0x7A, 0xC5, 0x78, 0xF0, 0x28, +0x10, 0x12, 0x97, 0xE0, 0xC8, 0xC8, 0x84, 0xF6, 0xA4, 0xF4, 0xB7, 0xE0, 0x85, 0x7A, 0xC8, 0xC8, +0x84, 0xF4, 0x80, 0xE4, 0xA5, 0x78, 0x97, 0xE0, 0xC8, 0xC8, 0x84, 0xF6, 0xA4, 0xF2, 0xB7, 0xEE, +0x85, 0x78, 0xC8, 0xC8, 0x84, 0xF2, 0x80, 0xD0, 0xC9, 0xFF, 0x3F, 0xD0, 0xB7, 0x97, 0xE0, 0xC8, +0xC8, 0x84, 0xF6, 0x60, 0x86, 0xB8, 0x64, 0xBC, 0x64, 0xBE, 0xA2, 0xDC, 0x00, 0xA9, 0x28, 0x28, +0x20, 0x5C, 0x46, 0x90, 0x01, 0x6B, 0x85, 0xE0, 0x86, 0xE2, 0xA5, 0xC4, 0xA2, 0xBC, 0x00, 0x20, +0x5C, 0x46, 0x90, 0x03, 0x82, 0x7D, 0x01, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xA9, 0x04, +0x00, 0x97, 0xC0, 0x20, 0x86, 0x5A, 0x20, 0xE4, 0x5A, 0x38, 0xA5, 0xC4, 0xE9, 0x04, 0x00, 0x29, +0xF8, 0xFF, 0x18, 0x69, 0x04, 0x00, 0x85, 0xC8, 0xA0, 0x04, 0x00, 0x84, 0xC6, 0xA0, 0x24, 0x00, +0xA9, 0xFF, 0x3F, 0x97, 0xE0, 0x84, 0xE4, 0xA0, 0x24, 0x08, 0x97, 0xE0, 0x84, 0xE6, 0xA0, 0x24, +0x10, 0x97, 0xE0, 0x84, 0xE8, 0xA0, 0x24, 0x18, 0x84, 0xEA, 0xA0, 0x24, 0x20, 0x84, 0xEC, 0xA5, +0xE0, 0x85, 0xEE, 0xA5, 0xE2, 0x85, 0xF0, 0xA4, 0xD4, 0xB7, 0xD0, 0x85, 0xCA, 0xC8, 0xC8, 0x84, +0xD4, 0xA4, 0xDA, 0xB7, 0xD6, 0x85, 0xCC, 0xC8, 0xC8, 0x84, 0xDA, 0xA5, 0xBA, 0xC9, 0x08, 0x00, +0xD0, 0x05, 0xA9, 0xFF, 0x3F, 0x85, 0xCC, 0xA5, 0xCA, 0xC5, 0xCC, 0xF0, 0x40, 0x10, 0x46, 0x20, +0x74, 0x5D, 0x80, 0x76, 0xA5, 0xCA, 0x85, 0xCE, 0xA5, 0xD0, 0x85, 0xEE, 0xA5, 0xD2, 0x85, 0xF0, +0xA4, 0xD4, 0x84, 0xF2, 0xA4, 0xE4, 0x84, 0xF4, 0xA4, 0xEA, 0x84, 0xF6, 0x20, 0x84, 0x5C, 0xA5, +0xE0, 0x85, 0xEE, 0xA5, 0xE2, 0x85, 0xF0, 0xA4, 0xF2, 0xB7, 0xD0, 0x85, 0xCA, 0xC8, 0xC8, 0x84, +0xD4, 0xA6, 0xEA, 0xA5, 0xE4, 0x86, 0xE4, 0x85, 0xEA, 0x60, 0x4C, 0x7B, 0x5E, 0xC9, 0xFF, 0x3F, +0xF0, 0xF8, 0x20, 0x74, 0x5D, 0xA5, 0xCC, 0x85, 0xCE, 0xA5, 0xD6, 0x85, 0xEE, 0xA5, 0xD8, 0x85, +0xF0, 0xA5, 0xDA, 0x85, 0xF2, 0xA5, 0xE6, 0x85, 0xF4, 0xA5, 0xEA, 0x85, 0xF6, 0x20, 0x84, 0x5C, +0xA5, 0xE0, 0x85, 0xEE, 0xA5, 0xE2, 0x85, 0xF0, 0xA4, 0xF2, 0xB7, 0xD6, 0x85, 0xCC, 0xC8, 0xC8, +0x84, 0xDA, 0xA6, 0xEA, 0xA5, 0xE6, 0x86, 0xE6, 0x85, 0xEA, 0xA5, 0xE4, 0x85, 0xF2, 0xA5, 0xE6, +0x85, 0xF4, 0xA5, 0xEA, 0x85, 0xF6, 0xA6, 0xBA, 0xFC, 0xFD, 0x5D, 0x80, 0x0A, 0x4B, 0x5B, 0x51, +0x5B, 0x58, 0x5B, 0x84, 0x5C, 0x05, 0x5C, 0xA5, 0xEA, 0x85, 0xF2, 0xA5, 0xE8, 0x85, 0xF4, 0xA4, +0xEC, 0x84, 0xF6, 0x20, 0x84, 0x5C, 0xA6, 0xEA, 0xA5, 0xE8, 0x86, 0xE8, 0x85, 0xEA, 0xA4, 0xEC, +0x84, 0xF2, 0xA4, 0xC6, 0x80, 0x2A, 0xB7, 0xE0, 0x85, 0x2A, 0xC8, 0xC8, 0xB7, 0xE0, 0x85, 0x2C, +0xC8, 0xC8, 0x84, 0xF2, 0xA4, 0xC6, 0xA5, 0xCE, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0x2A, 0x97, 0xC0, +0xC8, 0xC8, 0xA5, 0xCE, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, 0x2C, 0x97, 0xC0, 0xC8, 0xC8, 0x84, 0xC6, +0xC4, 0xC8, 0x90, 0x14, 0xA5, 0xC8, 0x18, 0x69, 0x00, 0x01, 0x85, 0xC8, 0xA2, 0xBC, 0x00, 0x20, +0x35, 0x46, 0xB0, 0x10, 0x85, 0xC0, 0x86, 0xC2, 0xA4, 0xF2, 0xB7, 0xE0, 0xC9, 0xFF, 0x3F, 0xD0, +0xB5, 0x4C, 0x67, 0x5D, 0x48, 0x20, 0x87, 0x5E, 0x68, 0x38, 0x6B, 0xA0, 0x02, 0x00, 0xA5, 0xC6, +0x97, 0xC0, 0x4A, 0x4A, 0x3A, 0x85, 0xC4, 0xA2, 0xDC, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xDE, 0x48, +0xA5, 0xDC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x6B, 0xA0, 0x04, 0x00, 0xB7, 0x54, +0xA0, 0x08, 0x00, 0xD7, 0x54, 0x10, 0x0A, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0xA0, 0x06, 0x00, 0xD7, +0x54, 0x60, 0xA0, 0x04, 0x00, 0xB7, 0x64, 0xA0, 0x08, 0x00, 0xD7, 0x64, 0x10, 0x0A, 0xA0, 0x02, +0x00, 0xB7, 0x64, 0xA0, 0x06, 0x00, 0xD7, 0x64, 0x60, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0xD7, 0x64, +0x10, 0x02, 0xB7, 0x64, 0x85, 0xAE, 0xA0, 0x06, 0x00, 0xB7, 0x64, 0xD7, 0x54, 0x30, 0x02, 0xB7, +0x54, 0x85, 0xB2, 0xA0, 0x08, 0x00, 0xB7, 0x64, 0xD7, 0x54, 0x30, 0x02, 0xB7, 0x54, 0x85, 0xB4, +0xA0, 0x04, 0x00, 0xB7, 0x54, 0xD7, 0x64, 0x10, 0x02, 0xB7, 0x64, 0x85, 0xB0, 0x60, 0x20, 0xB3, +0x0D, 0xA9, 0x00, 0x00, 0x4C, 0x22, 0x5F, 0x20, 0xB3, 0x0D, 0xA9, 0x04, 0x00, 0x4C, 0x22, 0x5F, +0x20, 0xB3, 0x0D, 0xA9, 0x02, 0x00, 0x4C, 0x22, 0x5F, 0x20, 0xB3, 0x0D, 0xA9, 0x06, 0x00, 0x4C, +0x22, 0x5F, 0x85, 0xBA, 0x48, 0xA3, 0x15, 0x48, 0xA3, 0x15, 0x48, 0xA3, 0x15, 0x48, 0xA3, 0x15, +0x48, 0xA2, 0x04, 0x77, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xF0, 0x3F, 0xA5, 0xBA, 0x29, 0x02, 0x00, +0xD0, 0x1B, 0xA3, 0x13, 0x48, 0xA3, 0x13, 0x48, 0xA3, 0x0F, 0x48, 0xA3, 0x0F, 0x48, 0xA2, 0x04, +0x69, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x1B, 0x20, 0x78, 0x60, 0x4C, 0x55, 0xFF, 0xA3, 0x0B, 0x48, +0xA3, 0x0B, 0x48, 0xA2, 0x04, 0x6A, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x06, 0x20, 0x78, 0x60, 0x4C, +0x55, 0xFF, 0x48, 0x20, 0x78, 0x60, 0xFA, 0x4C, 0x58, 0xFF, 0xA3, 0x11, 0x85, 0x50, 0xA3, 0x13, +0x85, 0x52, 0x20, 0xA7, 0x45, 0xA3, 0x0D, 0x85, 0x60, 0xA3, 0x0F, 0x85, 0x62, 0x20, 0xB8, 0x45, +0xA9, 0x02, 0x00, 0xC5, 0xBA, 0x90, 0x53, 0xD0, 0x05, 0x20, 0xB2, 0x5E, 0x10, 0xA4, 0x20, 0xC9, +0x5E, 0xA5, 0xB0, 0xC5, 0xB4, 0x10, 0x06, 0xA5, 0xAE, 0xC5, 0xB2, 0x30, 0x07, 0xA5, 0xBA, 0xF0, +0xAC, 0x4C, 0x42, 0x5F, 0xA5, 0xBA, 0xD0, 0x62, 0xA9, 0x0A, 0x00, 0xC7, 0x54, 0xD0, 0x5B, 0xC7, +0x64, 0xD0, 0x57, 0xA3, 0x0B, 0x48, 0xA3, 0x0B, 0x48, 0x18, 0xA9, 0x00, 0x00, 0x48, 0x7B, 0x69, +0xAE, 0x00, 0x48, 0xA2, 0x04, 0x6C, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x06, 0x20, 0x78, 0x60, 0x4C, +0x55, 0xFF, 0x48, 0x20, 0x78, 0x60, 0xFA, 0x4C, 0x58, 0xFF, 0x20, 0xB2, 0x5E, 0x30, 0x03, 0x82, +0x50, 0xFF, 0x20, 0x9B, 0x5E, 0x30, 0x23, 0xA3, 0x0F, 0x48, 0xA3, 0x0F, 0x48, 0xA3, 0x0F, 0x48, +0xA3, 0x0F, 0x48, 0xA2, 0x04, 0x69, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x06, 0x20, 0x78, 0x60, 0x4C, +0x55, 0xFF, 0x48, 0x20, 0x78, 0x60, 0xFA, 0x4C, 0x58, 0xFF, 0x18, 0xA7, 0x54, 0x67, 0x64, 0x0A, +0x85, 0xC4, 0xA2, 0x00, 0x00, 0x22, 0x98, 0x1F, 0xE0, 0xB0, 0x2C, 0xA3, 0x09, 0x85, 0x50, 0xA3, +0x0B, 0x85, 0x52, 0x20, 0xA7, 0x45, 0x22, 0x94, 0x1F, 0xE0, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, +0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x06, 0x20, 0x78, 0x60, 0x4C, 0x55, 0xFF, 0x48, +0x20, 0x78, 0x60, 0xFA, 0x4C, 0x58, 0xFF, 0x48, 0xA5, 0xBC, 0x05, 0xBE, 0xF0, 0x13, 0xA2, 0xBC, +0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, +0xE1, 0x20, 0x78, 0x60, 0xFA, 0x4C, 0x58, 0xFF, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xA2, 0x60, +0x00, 0x20, 0x22, 0x46, 0x60, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0x85, 0x50, 0xA3, 0x0F, 0x85, 0x52, +0xA2, 0x50, 0x00, 0x20, 0x07, 0x46, 0x85, 0x54, 0x86, 0x56, 0xA7, 0x54, 0xC9, 0x0A, 0x00, 0xD0, +0x44, 0xA3, 0x0B, 0x85, 0xB8, 0xA3, 0x09, 0x85, 0xB6, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0x18, 0x65, +0xB6, 0x97, 0x54, 0xA0, 0x04, 0x00, 0xB7, 0x54, 0x18, 0x65, 0xB8, 0x97, 0x54, 0xA0, 0x06, 0x00, +0xB7, 0x54, 0x38, 0xE5, 0xB6, 0x97, 0x54, 0xA0, 0x08, 0x00, 0xB7, 0x54, 0x38, 0xE5, 0xB8, 0x97, +0x54, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0x4C, 0x81, 0xFF, 0x48, 0xA2, 0x50, 0x00, 0x20, 0x22, +0x46, 0xFA, 0x4C, 0x84, 0xFF, 0xA3, 0x0B, 0xAA, 0x20, 0xF3, 0x60, 0xA3, 0x09, 0xAA, 0x20, 0xF3, +0x60, 0x80, 0xDE, 0xA5, 0x50, 0x85, 0x60, 0xA5, 0x52, 0x85, 0x62, 0xA5, 0x54, 0x85, 0x64, 0xA5, +0x56, 0x85, 0x66, 0xA7, 0x54, 0x0A, 0x85, 0xC4, 0xA9, 0x08, 0x00, 0x85, 0xBA, 0x22, 0x98, 0x1F, +0xE0, 0xB0, 0x74, 0xA0, 0x02, 0x00, 0xB7, 0xC0, 0x85, 0xC4, 0xC9, 0x05, 0x00, 0x10, 0x2D, 0xA2, +0xBC, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, +0x00, 0xE1, 0xB0, 0x13, 0xA5, 0x52, 0x48, 0xA5, 0x50, 0x48, 0xA2, 0x04, 0x6A, 0x22, 0x00, 0x00, +0xE1, 0xB0, 0x04, 0xFA, 0x82, 0x8A, 0xFF, 0xAA, 0x7A, 0x4C, 0x84, 0xFF, 0xA0, 0x04, 0x00, 0xB7, +0xC0, 0x48, 0xC8, 0xC8, 0xB7, 0xC0, 0xAA, 0x68, 0x97, 0xC0, 0x8A, 0x88, 0x88, 0x97, 0xC0, 0xC8, +0xC8, 0xC8, 0xC8, 0xC4, 0xC4, 0xD0, 0xE8, 0x98, 0x4A, 0x4A, 0x3A, 0x85, 0xC4, 0x22, 0x90, 0x1F, +0xE0, 0x22, 0x94, 0x1F, 0xE0, 0xB0, 0x2F, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, +0x22, 0x00, 0x00, 0xE1, 0xB0, 0x39, 0x60, 0x48, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBC, +0x05, 0xBE, 0xF0, 0x0D, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, +0xE1, 0xFA, 0x7A, 0x4C, 0x84, 0xFF, 0x48, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, +0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xFA, 0x7A, 0x4C, 0x84, 0xFF, 0xAA, +0x7A, 0x4C, 0x84, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0x85, 0x50, 0xA3, 0x0F, 0x85, 0x52, 0xA3, +0x0B, 0x85, 0xB8, 0xA3, 0x09, 0x85, 0xB6, 0xA2, 0x50, 0x00, 0x20, 0x07, 0x46, 0x85, 0x54, 0x86, +0x56, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0x18, 0x65, 0xB6, 0x97, 0x54, 0xA0, 0x04, 0x00, 0xB7, 0x54, +0x18, 0x65, 0xB8, 0x97, 0x54, 0xA0, 0x06, 0x00, 0xB7, 0x54, 0x18, 0x65, 0xB6, 0x97, 0x54, 0xA0, +0x08, 0x00, 0xB7, 0x54, 0x18, 0x65, 0xB8, 0x97, 0x54, 0xA9, 0x0A, 0x00, 0xC7, 0x54, 0xF0, 0x2C, +0xA8, 0xB7, 0x54, 0x18, 0x65, 0xB6, 0x97, 0x54, 0xC8, 0xC8, 0xB7, 0x54, 0x18, 0x65, 0xB8, 0x97, +0x54, 0xC8, 0xC8, 0xB7, 0x54, 0x18, 0x65, 0xB8, 0x97, 0x54, 0xC8, 0xC8, 0xB7, 0x54, 0xC9, 0xFF, +0x3F, 0xD0, 0xE9, 0xC8, 0xC8, 0xB7, 0x54, 0xC9, 0xFF, 0x3F, 0xD0, 0xD7, 0xA2, 0x50, 0x00, 0x20, +0x22, 0x46, 0x4C, 0x81, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x4C, 0x63, 0xA2, 0x06, 0x00, 0xB5, 0xDA, +0xD5, 0xE2, 0xD0, 0x06, 0xCA, 0xCA, 0x10, 0xF6, 0x80, 0x2A, 0x22, 0xC8, 0x1F, 0xE0, 0xA3, 0x11, +0x85, 0x50, 0xA3, 0x13, 0x85, 0x52, 0x20, 0xA7, 0x45, 0xA7, 0x54, 0xC9, 0x0A, 0x00, 0xD0, 0x1A, +0xA5, 0x54, 0x85, 0x64, 0xA5, 0x56, 0x85, 0x66, 0xA0, 0x02, 0x00, 0x20, 0x77, 0x64, 0xA0, 0x06, +0x00, 0x20, 0x77, 0x64, 0x20, 0xB2, 0x45, 0x4C, 0x55, 0xFF, 0x0A, 0x18, 0x69, 0x04, 0x00, 0xA2, +0xBC, 0x00, 0x20, 0x5C, 0x46, 0x90, 0x0B, 0x48, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xFA, 0x4C, +0x58, 0xFF, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xA9, 0x04, 0x00, 0x97, 0xC0, 0x22, 0x84, +0x1F, 0xE0, 0x90, 0x1E, 0x48, 0xA2, 0xBC, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, +0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xFA, 0x4C, +0x58, 0xFF, 0xA0, 0x02, 0x00, 0xB7, 0xC0, 0x85, 0xEA, 0xA0, 0x04, 0x00, 0x84, 0xEE, 0xA4, 0xEE, +0xC4, 0xEA, 0x10, 0x21, 0x84, 0xEC, 0xB7, 0xC0, 0x85, 0xF0, 0xC8, 0xC8, 0xB7, 0xC0, 0x85, 0xF2, +0xC8, 0xC8, 0x84, 0xEE, 0x20, 0xBC, 0x63, 0xA4, 0xEC, 0xA5, 0xF0, 0x97, 0xC0, 0xC8, 0xC8, 0xA5, +0xF2, 0x97, 0xC0, 0x80, 0xD9, 0xA5, 0xEA, 0x4A, 0x4A, 0x3A, 0x85, 0xC4, 0x22, 0x90, 0x1F, 0xE0, +0x22, 0x8C, 0x1F, 0xE0, 0x22, 0x94, 0x1F, 0xE0, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, +0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x1B, 0x4C, 0x55, 0xFF, +0x48, 0xA2, 0x50, 0x00, 0x20, 0x22, 0x46, 0xA5, 0xBE, 0x48, 0xA5, 0xBC, 0x48, 0xA2, 0x02, 0x10, +0x22, 0x00, 0x00, 0xE1, 0xFA, 0x4C, 0x58, 0xFF, 0xAA, 0x4C, 0x58, 0xFF, 0xA3, 0x0F, 0x85, 0x2A, +0xA3, 0x11, 0x85, 0x2C, 0xA7, 0x2A, 0x85, 0xDA, 0xA0, 0x02, 0x00, 0xB7, 0x2A, 0x85, 0xDC, 0xA0, +0x04, 0x00, 0xB7, 0x2A, 0x85, 0xDE, 0xA0, 0x06, 0x00, 0xB7, 0x2A, 0x85, 0xE0, 0xA3, 0x0B, 0x85, +0x2A, 0xA3, 0x0D, 0x85, 0x2C, 0xA7, 0x2A, 0x85, 0xE2, 0xA0, 0x02, 0x00, 0xB7, 0x2A, 0x85, 0xE4, +0xA0, 0x04, 0x00, 0xB7, 0x2A, 0x85, 0xE6, 0xA0, 0x06, 0x00, 0xB7, 0x2A, 0x85, 0xE8, 0x60, 0x38, +0xA5, 0xDE, 0xE5, 0xDA, 0x85, 0xFA, 0x4A, 0x85, 0x04, 0x38, 0xA5, 0xE0, 0xE5, 0xDC, 0x85, 0xFC, +0x4A, 0x85, 0x06, 0x38, 0xA5, 0xE6, 0xE5, 0xE2, 0x85, 0x00, 0x38, 0xE5, 0xFA, 0x85, 0xF6, 0x38, +0xA5, 0xE8, 0xE5, 0xE4, 0x85, 0x02, 0x38, 0xE5, 0xFC, 0x85, 0xF8, 0x6B, 0x64, 0xF4, 0x38, 0xA5, +0xF0, 0xE5, 0xDA, 0xA6, 0xF6, 0xF0, 0x4F, 0xAA, 0x10, 0x06, 0x49, 0xFF, 0xFF, 0x1A, 0xE6, 0xF4, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0x48, 0xA5, 0x00, 0x48, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x18, 0xA5, 0x04, +0x63, 0x01, 0x83, 0x01, 0xA9, 0x00, 0x00, 0x63, 0x03, 0x83, 0x03, 0xF4, 0x00, 0x00, 0xA5, 0xFA, +0x48, 0xA2, 0x0B, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xFA, 0xFA, 0xFA, 0xA6, 0xF4, 0xF0, 0x06, +0x49, 0xFF, 0xFF, 0x1A, 0x64, 0xF4, 0x18, 0x65, 0xE2, 0x85, 0xF0, 0x38, 0xA5, 0xF2, 0xE5, 0xDC, +0xA6, 0xF8, 0xF0, 0x4D, 0xAA, 0x10, 0x06, 0x49, 0xFF, 0xFF, 0x1A, 0xE6, 0xF4, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x48, +0xA5, 0x02, 0x48, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x18, 0xA5, 0x06, 0x63, 0x01, 0x83, +0x01, 0xA9, 0x00, 0x00, 0x63, 0x03, 0x83, 0x03, 0xF4, 0x00, 0x00, 0xA5, 0xFC, 0x48, 0xA2, 0x0B, +0x0D, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xFA, 0xFA, 0xFA, 0xA6, 0xF4, 0xF0, 0x04, 0x49, 0xFF, 0xFF, +0x1A, 0x18, 0x65, 0xE4, 0x85, 0xF2, 0x60, 0xB7, 0x64, 0x85, 0xF0, 0xC8, 0xC8, 0xB7, 0x64, 0x85, +0xF2, 0x5A, 0x20, 0xBC, 0x63, 0x7A, 0xA5, 0xF2, 0x97, 0x64, 0x88, 0x88, 0xA5, 0xF0, 0x97, 0x64, +0x60, 0x20, 0xB3, 0x0D, 0x20, 0x4C, 0x63, 0x22, 0xC8, 0x1F, 0xE0, 0xA3, 0x11, 0x85, 0x64, 0xA3, +0x13, 0x85, 0x66, 0xA0, 0x00, 0x00, 0x20, 0x77, 0x64, 0xA0, 0x04, 0x00, 0x20, 0x77, 0x64, 0x4C, +0x55, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x4C, 0x63, 0x22, 0xC8, 0x1F, 0xE0, 0xA3, 0x11, 0x85, 0x64, +0xA3, 0x13, 0x85, 0x66, 0xA0, 0x00, 0x00, 0x20, 0x77, 0x64, 0x4C, 0x55, 0xFF, 0x20, 0xB3, 0x0D, +0xA3, 0x09, 0x85, 0xD6, 0xA9, 0x00, 0x00, 0x22, 0x3E, 0x65, 0xFE, 0xA5, 0xDE, 0x83, 0x0B, 0x4C, +0x60, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xDA, 0xA3, 0x0B, 0x85, 0xDC, 0xA7, 0xDA, 0x29, +0xFF, 0x00, 0x85, 0xD8, 0xE6, 0xDA, 0xD0, 0x02, 0xE6, 0xDC, 0xA9, 0x01, 0x00, 0x22, 0x3E, 0x65, +0xFE, 0xA5, 0xDE, 0x83, 0x0D, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0B, 0x85, 0xDA, 0xA3, +0x0D, 0x85, 0xDC, 0xA3, 0x09, 0x85, 0xD8, 0xA9, 0x01, 0x00, 0x22, 0x3E, 0x65, 0xFE, 0xA5, 0xDE, +0x83, 0x0F, 0x4C, 0x76, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xDA, 0xA3, 0x0B, 0x85, 0xDC, +0xA9, 0x02, 0x00, 0x22, 0x3E, 0x65, 0xFE, 0xA5, 0xDE, 0x83, 0x0D, 0x4C, 0x6B, 0xFF, 0x85, 0x38, +0x20, 0xC5, 0x0D, 0xB0, 0x04, 0x5C, 0x2C, 0x1E, 0xE0, 0x8B, 0xA0, 0x28, 0x00, 0xB7, 0x2A, 0x48, +0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, 0xA5, 0x38, 0x0A, 0xAA, 0x7C, 0x5D, 0x65, 0x63, 0x65, 0x71, +0x65, 0x71, 0x65, 0x22, 0x64, 0x1F, 0xE0, 0x22, 0x50, 0x1F, 0xE0, 0x29, 0xFF, 0x00, 0x85, 0xDE, +0x6B, 0x64, 0xAC, 0x22, 0x54, 0x1F, 0xE0, 0xB0, 0x08, 0x22, 0x64, 0x1F, 0xE0, 0x22, 0x78, 0x1F, +0xE0, 0xA5, 0xAC, 0x85, 0xDE, 0x6B, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xD6, 0xA9, 0x00, 0x00, +0x22, 0xE7, 0x65, 0xFE, 0x4C, 0x60, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xDA, 0xA3, 0x0B, +0x85, 0xDC, 0xA7, 0xDA, 0x29, 0xFF, 0x00, 0x85, 0xD8, 0xE6, 0xDA, 0xD0, 0x02, 0xE6, 0xDC, 0xA9, +0x01, 0x00, 0x22, 0xE7, 0x65, 0xFE, 0x4C, 0x6B, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0B, 0x85, 0xDA, +0xA3, 0x0D, 0x85, 0xDC, 0xA3, 0x09, 0x85, 0xD8, 0xA9, 0x01, 0x00, 0x22, 0xE7, 0x65, 0xFE, 0x4C, +0x76, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xDA, 0xA3, 0x0B, 0x85, 0xDC, 0xA9, 0x02, 0x00, +0x22, 0xE7, 0x65, 0xFE, 0x4C, 0x6B, 0xFF, 0x85, 0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x04, 0x5C, 0x04, +0x1E, 0xE0, 0x8B, 0xA0, 0x00, 0x00, 0xB7, 0x2A, 0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, 0xA9, +0x00, 0x00, 0x22, 0xF8, 0x1E, 0xE0, 0xA5, 0x38, 0x0A, 0xAA, 0x7C, 0x0D, 0x66, 0x13, 0x66, 0x6E, +0x66, 0x6E, 0x66, 0x22, 0x3C, 0x1E, 0xE0, 0x22, 0xA0, 0x1E, 0xE0, 0x22, 0x64, 0x1F, 0xE0, 0xA0, +0x42, 0x00, 0xB7, 0x24, 0x85, 0xAC, 0x22, 0x58, 0x1F, 0xE0, 0x90, 0x11, 0x22, 0x50, 0x1F, 0xE0, +0x29, 0xFF, 0x00, 0x18, 0x65, 0xAC, 0xA0, 0x42, 0x00, 0x97, 0x24, 0x80, 0x2C, 0x22, 0xF4, 0x1F, +0xE0, 0x22, 0x68, 0x1F, 0xE0, 0x22, 0x74, 0x1F, 0xE0, 0xA5, 0x90, 0x18, 0x65, 0xA0, 0xA0, 0x42, +0x00, 0x97, 0x24, 0x22, 0xB0, 0x1F, 0xE0, 0x22, 0x5C, 0x1F, 0xE0, 0xB0, 0x08, 0x22, 0x60, 0x1F, +0xE0, 0x22, 0xF4, 0x1E, 0xE0, 0x22, 0x7C, 0x1F, 0xE0, 0x22, 0xA8, 0x1E, 0xE0, 0x6B, 0x22, 0x54, +0x1F, 0xE0, 0x90, 0x01, 0x6B, 0x22, 0x3C, 0x1E, 0xE0, 0x22, 0xA0, 0x1E, 0xE0, 0x22, 0x64, 0x1F, +0xE0, 0xA0, 0x42, 0x00, 0xB7, 0x24, 0x85, 0xAC, 0x22, 0x58, 0x1F, 0xE0, 0x90, 0x07, 0x22, 0x78, +0x1F, 0xE0, 0x82, 0x84, 0x00, 0x22, 0xF4, 0x1F, 0xE0, 0xA2, 0x00, 0x02, 0xB5, 0x00, 0x85, 0x2A, +0xA5, 0x06, 0x18, 0x65, 0x2A, 0xC5, 0xAC, 0x10, 0x07, 0x22, 0x78, 0x1F, 0xE0, 0x82, 0x69, 0x00, +0x85, 0xAA, 0xA5, 0x02, 0x38, 0xE5, 0x2A, 0x85, 0xA8, 0xA5, 0xAC, 0xC5, 0xA8, 0x10, 0x15, 0x22, +0x50, 0x1F, 0xE0, 0x29, 0xFF, 0x00, 0x18, 0x65, 0xAC, 0x85, 0xAC, 0x22, 0x54, 0x1F, 0xE0, 0x90, +0xE8, 0x82, 0x45, 0x00, 0x22, 0x68, 0x1F, 0xE0, 0xA5, 0xAA, 0x38, 0xE5, 0xA0, 0x85, 0x96, 0x22, +0x74, 0x1F, 0xE0, 0x22, 0x54, 0x1F, 0xE0, 0x90, 0x09, 0xA5, 0x90, 0x18, 0x65, 0xA0, 0x85, 0xAC, +0x80, 0x11, 0xA5, 0x96, 0xC5, 0x90, 0x10, 0xE7, 0xA5, 0x90, 0x18, 0x65, 0xA0, 0x85, 0xAC, 0x22, +0x78, 0x1F, 0xE0, 0x22, 0xB0, 0x1F, 0xE0, 0x22, 0x5C, 0x1F, 0xE0, 0xB0, 0x08, 0x22, 0x60, 0x1F, +0xE0, 0x22, 0xF4, 0x1E, 0xE0, 0x22, 0x7C, 0x1F, 0xE0, 0xA5, 0xAC, 0xA0, 0x42, 0x00, 0x97, 0x24, +0x22, 0xA8, 0x1E, 0xE0, 0x6B, 0xA2, 0x00, 0x01, 0xB5, 0x04, 0xD0, 0x1B, 0xA5, 0x9E, 0xC5, 0xE0, +0x10, 0x02, 0xA5, 0xE0, 0x18, 0x65, 0xF4, 0x18, 0x65, 0xF2, 0xA6, 0xF0, 0xF0, 0x01, 0x1A, 0x18, +0x65, 0xEE, 0xA6, 0xEC, 0xF0, 0x01, 0x1A, 0x1A, 0xA2, 0x00, 0x02, 0x95, 0x00, 0x6B, 0x20, 0xB3, +0x0D, 0xA3, 0x0D, 0x85, 0xD6, 0xA3, 0x09, 0x85, 0xD2, 0xA3, 0x0B, 0x85, 0xD4, 0xA9, 0x00, 0x00, +0x22, 0xCF, 0x67, 0xFE, 0x4C, 0x76, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0x85, 0xDA, 0xA3, 0x0F, +0x85, 0xDC, 0xA7, 0xDA, 0x29, 0xFF, 0x00, 0x85, 0xD8, 0xE6, 0xDA, 0xD0, 0x02, 0xE6, 0xDC, 0xA3, +0x09, 0x85, 0xD2, 0xA3, 0x0B, 0x85, 0xD4, 0xA9, 0x01, 0x00, 0x22, 0xCF, 0x67, 0xFE, 0x4C, 0x81, +0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0F, 0x85, 0xDA, 0xA3, 0x11, 0x85, 0xDC, 0xA3, 0x0D, 0x85, 0xD8, +0xA3, 0x09, 0x85, 0xD2, 0xA3, 0x0B, 0x85, 0xD4, 0xA9, 0x01, 0x00, 0x22, 0xCF, 0x67, 0xFE, 0x4C, +0x4A, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, 0x0D, 0x85, 0xDA, 0xA3, 0x0F, 0x85, 0xDC, 0xA3, 0x09, 0x85, +0xD2, 0xA3, 0x0B, 0x85, 0xD4, 0xA9, 0x02, 0x00, 0x22, 0xCF, 0x67, 0xFE, 0x4C, 0x81, 0xFF, 0x85, +0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x04, 0x5C, 0x30, 0x1E, 0xE0, 0x8B, 0xA0, 0x2C, 0x00, 0xB7, 0x2A, +0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, 0xA5, 0x38, 0x0A, 0xAA, 0x7C, 0xEE, 0x67, 0xF4, 0x67, +0x6A, 0x68, 0x6A, 0x68, 0x22, 0x64, 0x1F, 0xE0, 0xA0, 0x42, 0x00, 0xB7, 0x24, 0x85, 0x92, 0x22, +0x50, 0x1F, 0xE0, 0xAA, 0x29, 0xFF, 0x00, 0x18, 0x65, 0x92, 0x85, 0x90, 0xB7, 0x7C, 0x85, 0x2C, +0xC8, 0xC8, 0xB7, 0x7C, 0x38, 0xE5, 0x2C, 0xD0, 0x03, 0x82, 0x28, 0x00, 0x85, 0x2E, 0x8A, 0xEB, +0x29, 0xFF, 0x00, 0x18, 0x65, 0x8C, 0x18, 0x65, 0x92, 0x85, 0xCE, 0x18, 0x65, 0x2E, 0x85, 0xD0, +0x22, 0xB4, 0x1F, 0xE0, 0xA5, 0xCE, 0xC5, 0x92, 0x10, 0x02, 0x85, 0x92, 0xA5, 0xD0, 0xC5, 0x90, +0x30, 0x02, 0x85, 0x90, 0xA5, 0x92, 0xA0, 0x02, 0x00, 0x97, 0xD2, 0xA5, 0x90, 0xA0, 0x06, 0x00, +0x97, 0xD2, 0xA0, 0x40, 0x00, 0xB7, 0x24, 0xAA, 0x38, 0xE5, 0x84, 0xA0, 0x00, 0x00, 0x97, 0xD2, +0x8A, 0x18, 0x65, 0xE2, 0xA0, 0x04, 0x00, 0x97, 0xD2, 0x6B, 0xA0, 0x42, 0x00, 0xB7, 0x24, 0x85, +0x92, 0x85, 0x90, 0xA9, 0xFF, 0x3F, 0x85, 0xCE, 0xA9, 0x01, 0xC0, 0x85, 0xD0, 0x22, 0x54, 0x1F, +0xE0, 0x90, 0x03, 0x82, 0x4E, 0x00, 0x22, 0x64, 0x1F, 0xE0, 0x22, 0x50, 0x1F, 0xE0, 0xAA, 0x29, +0xFF, 0x00, 0x85, 0x2A, 0xA5, 0x90, 0x85, 0x98, 0x18, 0x65, 0x2A, 0x85, 0x90, 0xB7, 0x7C, 0x85, +0x2C, 0xC8, 0xC8, 0xB7, 0x7C, 0x38, 0xE5, 0x2C, 0xD0, 0x03, 0x82, 0x1D, 0x00, 0x85, 0x2E, 0x8A, +0xEB, 0x29, 0xFF, 0x00, 0x18, 0x65, 0x8C, 0x18, 0x65, 0x98, 0xAA, 0xC5, 0xCE, 0x10, 0x02, 0x85, +0xCE, 0x18, 0x65, 0x2E, 0xC5, 0xD0, 0x30, 0x02, 0x85, 0xD0, 0x22, 0x54, 0x1F, 0xE0, 0x90, 0xBA, +0x22, 0xB4, 0x1F, 0xE0, 0xA5, 0xCE, 0xC5, 0x92, 0x30, 0x02, 0xA5, 0x92, 0xA0, 0x02, 0x00, 0x97, +0xD2, 0xA5, 0xD0, 0xC5, 0x90, 0x10, 0x02, 0xA5, 0x90, 0xA0, 0x06, 0x00, 0x97, 0xD2, 0xA0, 0x40, +0x00, 0xB7, 0x24, 0xAA, 0x38, 0xE5, 0x84, 0xA0, 0x00, 0x00, 0x97, 0xD2, 0x8A, 0x18, 0x65, 0xE2, +0xA0, 0x04, 0x00, 0x97, 0xD2, 0x6B, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2E, 0xA3, 0x0B, 0x85, +0x30, 0x22, 0xF8, 0x1F, 0xE0, 0x4C, 0x6B, 0xFF, 0x22, 0x64, 0x1F, 0xE0, 0xA5, 0x84, 0x87, 0x2E, +0xA5, 0xE2, 0xA0, 0x02, 0x00, 0x97, 0x2E, 0xA5, 0xE0, 0x18, 0x65, 0xF4, 0xA0, 0x04, 0x00, 0x97, +0x2E, 0xA5, 0xE4, 0xA0, 0x06, 0x00, 0x97, 0x2E, 0x6B, 0x20, 0xB3, 0x0D, 0x22, 0xB8, 0x1E, 0xE0, +0x83, 0x09, 0x4C, 0x3F, 0xFF, 0xA9, 0x0C, 0x00, 0x6B, 0x85, 0x2A, 0x86, 0x2C, 0xA0, 0x02, 0x00, +0xB7, 0x2A, 0xAA, 0xA7, 0x2A, 0x60, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xD2, 0xA3, 0x0B, 0x85, +0xD4, 0x22, 0x6B, 0x69, 0xFE, 0xA0, 0x04, 0x00, 0x4C, 0x1F, 0xFF, 0xA9, 0xFE, 0xFF, 0x87, 0xD2, +0xA9, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x97, 0xD2, 0xA9, 0x08, 0x00, 0xA0, 0x04, 0x00, 0x97, 0xD2, +0xA9, 0xFE, 0x00, 0xA0, 0x08, 0x00, 0x97, 0xD2, 0xA9, 0xE0, 0x77, 0xA0, 0x06, 0x00, 0x97, 0xD2, +0xA9, 0xFE, 0x00, 0xA0, 0x0C, 0x00, 0x97, 0xD2, 0xA9, 0xA9, 0x69, 0xA0, 0x0A, 0x00, 0x97, 0xD2, +0xA9, 0x0C, 0x00, 0xA0, 0x0E, 0x00, 0x97, 0xD2, 0x6B, 0x07, 0x53, 0x68, 0x61, 0x73, 0x74, 0x6F, +0x6E, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x2E, 0xA3, 0x0B, 0x85, 0xD2, 0xA3, 0x0D, 0x85, 0xD4, +0x22, 0xCE, 0x69, 0xFE, 0xA5, 0x2E, 0x83, 0x0F, 0xA0, 0x06, 0x00, 0x4C, 0x1F, 0xFF, 0xA0, 0x76, +0x00, 0xB7, 0x24, 0x85, 0x30, 0x88, 0x88, 0xB7, 0x24, 0x85, 0x2A, 0xA7, 0x2A, 0x85, 0x70, 0xA0, +0x02, 0x00, 0xB7, 0x2A, 0x85, 0x72, 0xA7, 0x70, 0x0A, 0x18, 0x65, 0x70, 0x85, 0x74, 0xA5, 0x72, +0x69, 0x00, 0x00, 0x85, 0x76, 0xA6, 0x2E, 0x64, 0x2E, 0xCA, 0xCA, 0x10, 0x03, 0x82, 0x77, 0x00, +0xA0, 0x02, 0x00, 0xB7, 0x70, 0xA0, 0x00, 0x00, 0x97, 0xD2, 0xE6, 0x2E, 0xE6, 0x2E, 0xCA, 0xCA, +0x10, 0x03, 0x82, 0x62, 0x00, 0xA0, 0x04, 0x00, 0xB7, 0x70, 0xA0, 0x02, 0x00, 0x97, 0xD2, 0xE6, +0x2E, 0xE6, 0x2E, 0xCA, 0xCA, 0x10, 0x03, 0x82, 0x4D, 0x00, 0xA0, 0x06, 0x00, 0xB7, 0x70, 0xA0, +0x04, 0x00, 0x97, 0xD2, 0xE6, 0x2E, 0xE6, 0x2E, 0xCA, 0xCA, 0x10, 0x03, 0x82, 0x38, 0x00, 0xA0, +0x08, 0x00, 0xB7, 0x70, 0xA0, 0x06, 0x00, 0x97, 0xD2, 0xE6, 0x2E, 0xE6, 0x2E, 0xCA, 0xCA, 0x10, +0x03, 0x82, 0x23, 0x00, 0xA0, 0x06, 0x00, 0xB7, 0x74, 0xA0, 0x08, 0x00, 0x97, 0xD2, 0xE6, 0x2E, +0xE6, 0x2E, 0xCA, 0xCA, 0x10, 0x03, 0x82, 0x0E, 0x00, 0xA0, 0x0A, 0x00, 0xB7, 0x70, 0xA0, 0x0A, +0x00, 0x97, 0xD2, 0xE6, 0x2E, 0xE6, 0x2E, 0x6B, 0x20, 0xB3, 0x0D, 0xA3, 0x0B, 0x85, 0x56, 0xA3, +0x09, 0x85, 0x50, 0x22, 0x8D, 0x6A, 0xFE, 0xA0, 0x04, 0x00, 0x4C, 0x1F, 0xFF, 0xA5, 0x56, 0x18, +0x65, 0x56, 0x65, 0x56, 0x69, 0x24, 0x00, 0x1A, 0x85, 0x56, 0x65, 0x28, 0x0A, 0x0A, 0x85, 0xD4, +0xA5, 0x4A, 0xC5, 0x50, 0x30, 0x06, 0x85, 0x50, 0x64, 0xD2, 0x80, 0x05, 0xA9, 0x01, 0x00, 0x85, +0xD2, 0xA5, 0xD4, 0x4A, 0x4A, 0x4A, 0x4A, 0x85, 0x54, 0xA5, 0x48, 0xC5, 0x54, 0x30, 0x0B, 0x85, +0x54, 0xA2, 0x00, 0x01, 0xB5, 0x04, 0x85, 0x56, 0x80, 0x16, 0xA9, 0x01, 0x00, 0x85, 0xD2, 0xA2, +0x00, 0x01, 0xB5, 0x04, 0xF0, 0x08, 0xC5, 0x56, 0x30, 0x06, 0x85, 0x56, 0x80, 0x02, 0x64, 0x56, +0xA5, 0xD2, 0xF0, 0x04, 0x22, 0xAC, 0x1F, 0xE0, 0x6B, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0xD2, +0xA3, 0x0B, 0x85, 0xD4, 0x22, 0xB8, 0x1E, 0xE0, 0x85, 0x2E, 0x22, 0xCE, 0x69, 0xFE, 0xA0, 0x04, +0x00, 0x4C, 0x1F, 0xFF, 0xA5, 0xD6, 0x22, 0xE8, 0x1F, 0xE0, 0x89, 0xFF, 0x00, 0xF0, 0x0C, 0xA6, +0xF6, 0xF0, 0x04, 0x22, 0xEC, 0x1F, 0xE0, 0x22, 0xF0, 0x1F, 0xE0, 0x6B, 0xC5, 0x88, 0x30, 0x06, +0xC5, 0x8A, 0x30, 0x05, 0xF0, 0x03, 0xA5, 0x8A, 0x1A, 0x38, 0xE5, 0x88, 0x0A, 0xA8, 0xB7, 0x80, +0xC9, 0xFF, 0xFF, 0xD0, 0x04, 0xA4, 0x8E, 0xB7, 0x80, 0x6B, 0xAA, 0xA5, 0xF6, 0x89, 0x01, 0x00, +0xF0, 0x07, 0x8A, 0x29, 0x00, 0xFF, 0x05, 0xE0, 0x6B, 0x89, 0x02, 0x00, 0xF0, 0x07, 0x8A, 0x29, +0x00, 0xFF, 0x05, 0xF8, 0x6B, 0x8A, 0x6B, 0x18, 0x65, 0xF4, 0xAA, 0xA5, 0x94, 0x18, 0x65, 0xF0, +0x85, 0x94, 0x8A, 0x65, 0xF2, 0xA6, 0xD6, 0xE0, 0x20, 0x00, 0xD0, 0x0B, 0xAA, 0xA5, 0x94, 0x18, +0x65, 0xEC, 0x85, 0x94, 0x8A, 0x65, 0xEE, 0x6B, 0xA5, 0x38, 0xC9, 0x02, 0x00, 0xF0, 0x15, 0xA5, +0xD8, 0xF0, 0x22, 0xA7, 0xDA, 0x29, 0xFF, 0x00, 0x85, 0xD6, 0xC6, 0xD8, 0xE6, 0xDA, 0xD0, 0x02, +0xE6, 0xDC, 0x18, 0x6B, 0xA7, 0xDA, 0x29, 0xFF, 0x00, 0xF0, 0x0A, 0x85, 0xD6, 0xE6, 0xDA, 0xD0, +0x02, 0xE6, 0xDC, 0x18, 0x6B, 0x38, 0x6B, 0x22, 0x50, 0x1F, 0xE0, 0x29, 0xFF, 0x00, 0x18, 0x65, +0xAC, 0x85, 0xAC, 0x22, 0x54, 0x1F, 0xE0, 0x90, 0xEE, 0x6B, 0xA0, 0x72, 0x00, 0xB7, 0x24, 0x30, +0x16, 0xA9, 0x01, 0xC0, 0x85, 0x00, 0x85, 0x02, 0xA9, 0xFF, 0x3F, 0x85, 0x04, 0x85, 0x06, 0x22, +0x94, 0x1E, 0xE0, 0xB0, 0x03, 0x18, 0x6B, 0x38, 0x6B, 0xA5, 0xCE, 0xC5, 0x92, 0x30, 0x02, 0xA5, +0x92, 0x18, 0x65, 0xA0, 0xC5, 0x02, 0x30, 0x02, 0x85, 0x02, 0xA9, 0x01, 0x00, 0x18, 0x65, 0xA2, +0xC5, 0x00, 0x30, 0x02, 0x85, 0x00, 0xA5, 0xD0, 0x1A, 0xC5, 0x90, 0x10, 0x02, 0xA5, 0x90, 0x18, +0x65, 0xA0, 0xC5, 0x06, 0x10, 0x02, 0x85, 0x06, 0xA5, 0x02, 0xC5, 0x06, 0x30, 0x03, 0x82, 0x17, +0x00, 0xA5, 0xCA, 0x1A, 0x18, 0x65, 0xA2, 0xC5, 0x04, 0x10, 0x02, 0x85, 0x04, 0xA5, 0x00, 0xC5, +0x04, 0x30, 0x03, 0x82, 0x02, 0x00, 0x18, 0x6B, 0x38, 0x6B, 0xA5, 0x04, 0x3A, 0x38, 0xE5, 0x00, +0x85, 0xC8, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xD4, 0x12, 0xA5, 0x00, 0x38, 0xE5, 0x14, 0x48, +0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x2A, 0x68, 0x85, 0x2C, 0xA5, 0x0E, 0x18, +0x65, 0x2A, 0x85, 0xB6, 0xA5, 0x10, 0x65, 0x2C, 0x85, 0xB8, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xD4, 0xC4, 0xA5, 0x00, 0x38, 0xE5, 0xA2, 0x3A, 0x48, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, +0x68, 0x85, 0x2A, 0x68, 0x85, 0x2C, 0xA5, 0xAE, 0x18, 0x65, 0x2A, 0x85, 0xB2, 0xA5, 0xB0, 0x65, +0x2C, 0x85, 0xB4, 0xA5, 0x02, 0x38, 0xE5, 0x16, 0x4A, 0x24, 0x0B, 0x30, 0x05, 0x29, 0xF8, 0xFF, +0x80, 0x04, 0x4A, 0x29, 0xFC, 0xFF, 0x85, 0xBC, 0xA5, 0x02, 0x38, 0xE5, 0xA0, 0x4A, 0x4A, 0x4A, +0x4A, 0x85, 0x2A, 0x0A, 0x85, 0xBA, 0xA5, 0x06, 0x3A, 0x38, 0xE5, 0xA0, 0x4A, 0x4A, 0x4A, 0x4A, +0x38, 0xE5, 0x2A, 0x85, 0xC6, 0x6B, 0x8B, 0xA0, 0x76, 0x00, 0xB7, 0x24, 0x85, 0x2C, 0x88, 0x88, +0xB7, 0x24, 0x85, 0x2A, 0xA7, 0x2A, 0x85, 0x70, 0xA0, 0x02, 0x00, 0xB7, 0x2A, 0x85, 0x72, 0xA7, +0x70, 0x0A, 0x18, 0x65, 0x70, 0x85, 0x74, 0xA5, 0x72, 0x69, 0x00, 0x00, 0x85, 0x76, 0x85, 0x7A, +0x85, 0x82, 0xD4, 0x71, 0xAB, 0xAB, 0xA6, 0x74, 0xBD, 0x02, 0x00, 0x85, 0x88, 0xBD, 0x04, 0x00, +0x85, 0x8A, 0x1A, 0x38, 0xE5, 0x88, 0x0A, 0x85, 0x8E, 0xBD, 0x06, 0x00, 0x85, 0xE0, 0xBD, 0x08, +0x00, 0x85, 0x8C, 0xA9, 0x00, 0x01, 0xA0, 0x08, 0x00, 0xD7, 0x70, 0x10, 0x09, 0xA0, 0x0A, 0x00, +0xB7, 0x70, 0x85, 0x9E, 0x80, 0x11, 0xA0, 0x06, 0x00, 0xB7, 0x74, 0xA0, 0x0C, 0x00, 0xD7, 0x74, +0x10, 0x02, 0xB7, 0x74, 0x18, 0x65, 0x8C, 0x85, 0x9E, 0xBD, 0x0E, 0x00, 0x85, 0xCA, 0xBD, 0x12, +0x00, 0x85, 0x84, 0xBD, 0x14, 0x00, 0x85, 0xE2, 0xBD, 0x16, 0x00, 0x85, 0xE4, 0xBD, 0x10, 0x00, +0x0A, 0x18, 0x69, 0x10, 0x00, 0x90, 0x02, 0xE6, 0x82, 0x18, 0x65, 0x74, 0x90, 0x02, 0xE6, 0x82, +0x85, 0x80, 0xA5, 0x82, 0x85, 0x7E, 0xA5, 0x8E, 0x18, 0x69, 0x04, 0x00, 0x85, 0x2A, 0xA5, 0x80, +0x38, 0xE5, 0x2A, 0x85, 0x7C, 0xB0, 0x02, 0xC6, 0x7E, 0xA9, 0x1A, 0x00, 0x18, 0x65, 0x74, 0x85, +0x78, 0x90, 0x02, 0xE6, 0x7A, 0xBD, 0x18, 0x00, 0x0A, 0x85, 0x86, 0xA0, 0x04, 0x00, 0xB7, 0x70, +0x49, 0xFF, 0xFF, 0xA0, 0x80, 0x00, 0x37, 0x24, 0x85, 0xE6, 0x64, 0xF4, 0x89, 0x01, 0x00, 0xF0, +0x02, 0xE6, 0xF4, 0xA0, 0x84, 0x00, 0xB7, 0x24, 0x85, 0xEC, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0xEE, +0xA0, 0x88, 0x00, 0xB7, 0x24, 0x85, 0xF0, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0xF2, 0xA0, 0x7C, 0x00, +0xB7, 0x24, 0x85, 0xF6, 0xA9, 0x00, 0x80, 0x85, 0x94, 0xA5, 0xF6, 0x29, 0x02, 0x00, 0xF0, 0x0C, +0xA9, 0x30, 0x00, 0x22, 0xE8, 0x1F, 0xE0, 0x29, 0xFF, 0x00, 0x85, 0xF8, 0xAB, 0x6B, 0xA6, 0x46, +0xA5, 0x44, 0x20, 0x49, 0x69, 0x86, 0xB0, 0x85, 0xAE, 0xA5, 0x48, 0x0A, 0x85, 0xC4, 0xA5, 0xAC, +0x38, 0xE5, 0x16, 0x29, 0x0F, 0x00, 0x85, 0x2A, 0xA2, 0x00, 0x02, 0xB5, 0x00, 0x18, 0x69, 0x20, +0x00, 0x29, 0xF0, 0xFF, 0x05, 0x2A, 0x85, 0x92, 0x85, 0x90, 0xA5, 0xAC, 0x38, 0xE5, 0x92, 0x85, +0xA0, 0xA0, 0x40, 0x00, 0xB7, 0x24, 0x38, 0xE5, 0x84, 0x3A, 0x85, 0xA2, 0xA9, 0xFF, 0x3F, 0x85, +0xCE, 0xA9, 0x01, 0xC0, 0x85, 0xD0, 0x6B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xF4, 0x0F, 0x00, 0xA5, 0x0A, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, +0x02, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, 0xFA, 0xFA, 0x6B, 0x68, 0x85, 0x44, 0x68, 0x85, +0x46, 0xA9, 0x00, 0x00, 0x6B, 0x8B, 0xA5, 0xCE, 0x0A, 0x85, 0x2A, 0x18, 0x65, 0xAE, 0x85, 0xB2, +0xA5, 0xB0, 0x69, 0x00, 0x00, 0x85, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0xA5, 0xD0, 0x0A, 0x38, 0xE5, +0x2A, 0x85, 0xEA, 0xA5, 0xCA, 0x85, 0xC8, 0xA9, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x91, 0xB2, 0xC4, +0xEA, 0xF0, 0x04, 0xC8, 0xC8, 0x80, 0xF6, 0xC6, 0xC8, 0xF0, 0x11, 0xA5, 0xB2, 0x18, 0x65, 0xC4, +0x85, 0xB2, 0x90, 0x06, 0xE6, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0x80, 0xDB, 0xAB, 0x6B, 0xA5, 0xD0, +0xC5, 0xCE, 0x10, 0x02, 0x80, 0x12, 0x4A, 0x4A, 0x4A, 0x4A, 0x85, 0xD0, 0xA5, 0xCE, 0x4A, 0x4A, +0x4A, 0x4A, 0x85, 0xCE, 0x22, 0x70, 0x1F, 0xE0, 0x6B, 0x64, 0xE8, 0x80, 0x05, 0xA9, 0xFF, 0xFF, +0x85, 0xE8, 0xA5, 0xE6, 0xF0, 0x14, 0x89, 0x01, 0x00, 0xF0, 0x06, 0x22, 0xB8, 0x1F, 0xE0, 0xA5, +0xE6, 0x89, 0x04, 0x00, 0xF0, 0x04, 0x22, 0xBC, 0x1F, 0xE0, 0x6B, 0xA5, 0xD0, 0xC5, 0xCE, 0x10, +0x01, 0x6B, 0xE6, 0xD0, 0xA5, 0xE8, 0xF0, 0x01, 0x6B, 0x8B, 0xA5, 0xCA, 0x85, 0xC8, 0xA5, 0xCE, +0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0x2A, 0x18, 0x65, 0xAE, 0x85, 0xB2, 0xA5, 0xB0, 0x69, +0x00, 0x00, 0x85, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0xA5, 0xD0, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, +0x38, 0xE5, 0x2A, 0xD0, 0x03, 0x82, 0x48, 0x00, 0x85, 0xEA, 0xA4, 0xEA, 0xB1, 0xB2, 0xEB, 0x4A, +0x85, 0x2A, 0xBB, 0x88, 0x88, 0x84, 0x30, 0xB1, 0xB2, 0xEB, 0x4A, 0x85, 0x2E, 0xA5, 0x2A, 0x90, +0x03, 0x09, 0x00, 0x80, 0x9B, 0xEB, 0x11, 0xB2, 0x91, 0xB2, 0xA4, 0x30, 0xF0, 0x06, 0xA5, 0x2E, +0x85, 0x2A, 0x80, 0xDE, 0xA5, 0x2E, 0xEB, 0x12, 0xB2, 0x92, 0xB2, 0xC6, 0xC8, 0xF0, 0x2F, 0xA5, +0xB2, 0x18, 0x65, 0xC4, 0x85, 0xB2, 0x90, 0x06, 0xE6, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0x80, 0xBA, +0xB2, 0xB2, 0xEB, 0x4A, 0xEB, 0x12, 0xB2, 0x92, 0xB2, 0xC6, 0xC8, 0xF0, 0x11, 0xA5, 0xB2, 0x18, +0x65, 0xC4, 0x85, 0xB2, 0x90, 0x06, 0xE6, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0x80, 0xE2, 0xAB, 0x6B, +0xA5, 0xE2, 0xC9, 0x02, 0x00, 0xF0, 0x03, 0x10, 0x06, 0x6B, 0xA9, 0x00, 0x00, 0x80, 0x03, 0xA9, +0xFF, 0xFF, 0x85, 0x2C, 0xA5, 0xD0, 0xC5, 0xCE, 0x10, 0x10, 0xA5, 0x90, 0xC5, 0x92, 0xD0, 0x01, +0x6B, 0x3A, 0x85, 0xD0, 0xA5, 0x92, 0x85, 0xCE, 0x80, 0x11, 0xA5, 0x90, 0x3A, 0xC5, 0xD0, 0x30, +0x02, 0x85, 0xD0, 0xA5, 0x92, 0xC5, 0xCE, 0x10, 0x02, 0x85, 0xCE, 0xA5, 0xE8, 0xF0, 0x01, 0x6B, +0xA5, 0xCE, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0x2A, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xD4, 0xC4, 0xD4, 0x84, 0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x18, 0x65, 0xAE, 0x85, +0xB6, 0x68, 0x65, 0xB0, 0x85, 0xB8, 0xA5, 0xB6, 0x18, 0x65, 0x2A, 0x85, 0xB6, 0x90, 0x02, 0xE6, +0xB8, 0xA5, 0xB6, 0x18, 0x65, 0xC4, 0x85, 0xB2, 0xA5, 0xB8, 0x69, 0x00, 0x00, 0x85, 0xB4, 0x85, +0xD4, 0xA5, 0xB2, 0x18, 0x65, 0xC4, 0x85, 0xD2, 0x90, 0x02, 0xE6, 0xD4, 0x8B, 0xD4, 0xB3, 0xAB, +0xAB, 0xA5, 0xD0, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x38, 0xE5, 0x2A, 0xD0, 0x03, 0x82, 0x69, +0x00, 0x85, 0xEA, 0xA8, 0xB1, 0xB2, 0xEB, 0x4A, 0xEB, 0x85, 0x2A, 0x64, 0x2E, 0xB1, 0xB2, 0xEB, +0x0A, 0xEB, 0x05, 0x2A, 0x85, 0x2A, 0x90, 0x05, 0xA9, 0x00, 0x01, 0x85, 0x2E, 0xB7, 0xD2, 0x25, +0x2C, 0x17, 0xB6, 0x05, 0x2A, 0x85, 0x2A, 0x88, 0x88, 0xB1, 0xB2, 0xEB, 0x4A, 0xEB, 0x05, 0x2E, +0x85, 0x2E, 0x90, 0x07, 0xA9, 0x80, 0x00, 0x05, 0x2A, 0x85, 0x2A, 0xA5, 0x2A, 0x49, 0xFF, 0xFF, +0xC8, 0xC8, 0x11, 0xB2, 0x91, 0xB2, 0x88, 0x88, 0xF0, 0x06, 0xA5, 0x2E, 0x85, 0x2A, 0x80, 0xBB, +0xA7, 0xD2, 0x25, 0x2C, 0x07, 0xB6, 0x05, 0x2E, 0x85, 0x2E, 0xB2, 0xB2, 0xEB, 0x0A, 0xEB, 0x05, +0x2E, 0x49, 0xFF, 0xFF, 0x12, 0xB2, 0x92, 0xB2, 0x80, 0x20, 0x85, 0xEA, 0xA7, 0xD2, 0x25, 0x2C, +0x07, 0xB6, 0x85, 0x2A, 0xB2, 0xB2, 0xEB, 0xAA, 0x4A, 0xEB, 0x05, 0x2A, 0x85, 0x2A, 0x8A, 0x0A, +0xEB, 0x05, 0x2A, 0x49, 0xFF, 0xFF, 0x12, 0xB2, 0x92, 0xB2, 0xA5, 0xCE, 0x29, 0x0F, 0x00, 0x0A, +0xAA, 0xBF, 0x87, 0x49, 0xFE, 0x32, 0xB2, 0x92, 0xB2, 0xA5, 0xD0, 0x29, 0x0F, 0x00, 0x0A, 0xAA, +0xBF, 0xA7, 0x49, 0xFE, 0xA4, 0xEA, 0x31, 0xB2, 0x91, 0xB2, 0xAB, 0x6B, 0x8B, 0xA5, 0x90, 0x85, +0x98, 0x22, 0x50, 0x1F, 0xE0, 0xAA, 0x29, 0xFF, 0x00, 0x18, 0x65, 0x90, 0x85, 0x90, 0xB7, 0x7C, +0x85, 0x2C, 0xC8, 0xC8, 0xB7, 0x7C, 0x3A, 0xA8, 0x38, 0xE5, 0x2C, 0x10, 0x03, 0x82, 0x3B, 0x01, +0x85, 0x2A, 0x8A, 0xEB, 0x29, 0xFF, 0x00, 0x18, 0x65, 0x8C, 0x18, 0x65, 0x98, 0x85, 0x98, 0xC5, +0xCE, 0x10, 0x02, 0x85, 0xCE, 0x18, 0x65, 0x2A, 0xC5, 0xD0, 0x30, 0x02, 0x85, 0xD0, 0xA5, 0x2C, +0x29, 0x0F, 0x00, 0x85, 0x2E, 0x0A, 0xAA, 0xBF, 0x87, 0x49, 0xFE, 0x85, 0xA4, 0xA5, 0x2C, 0x4A, +0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x85, 0x9C, 0x18, 0x65, 0x78, 0x85, 0xB6, 0xA5, 0x7A, 0x69, 0x00, +0x00, 0x85, 0xB8, 0x98, 0x29, 0x0F, 0x00, 0x0A, 0xAA, 0xBF, 0xA7, 0x49, 0xFE, 0x85, 0xA6, 0xA5, +0x98, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0xAA, 0xA5, 0x98, 0x29, 0x0F, 0x00, 0x38, 0xE5, 0x2E, +0x10, 0x06, 0x18, 0x69, 0x10, 0x00, 0xCA, 0xCA, 0x0A, 0x85, 0x42, 0x8A, 0x18, 0x65, 0xAE, 0x85, +0xB2, 0xA5, 0xB0, 0x69, 0x00, 0x00, 0x85, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0xA5, 0xCA, 0x85, 0xC8, +0x98, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, 0xFF, 0x38, 0xE5, 0x9C, 0xD0, 0x03, 0x82, 0x69, 0x00, 0x85, +0xEA, 0xA0, 0x00, 0x00, 0xA7, 0xB6, 0x25, 0xA4, 0xF0, 0x1E, 0x85, 0x9A, 0x22, 0xDE, 0x38, 0xFE, +0x11, 0xB2, 0x91, 0xB2, 0xA5, 0x9A, 0x22, 0x69, 0x39, 0xFE, 0xC8, 0xC8, 0x11, 0xB2, 0x91, 0xB2, +0xC4, 0xEA, 0xF0, 0x08, 0xB7, 0xB6, 0xD0, 0xE2, 0xC8, 0xC8, 0x80, 0xF4, 0xB7, 0xB6, 0x25, 0xA6, +0xF0, 0x16, 0x85, 0x9A, 0x22, 0xDE, 0x38, 0xFE, 0x11, 0xB2, 0x91, 0xB2, 0xA5, 0x9A, 0x22, 0x69, +0x39, 0xFE, 0xC8, 0xC8, 0x11, 0xB2, 0x91, 0xB2, 0xC6, 0xC8, 0xF0, 0x5F, 0xA5, 0xB2, 0x18, 0x65, +0xC4, 0x85, 0xB2, 0x90, 0x06, 0xE6, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0xA5, 0xB6, 0x18, 0x65, 0x86, +0x85, 0xB6, 0x90, 0x02, 0xE6, 0xB8, 0x80, 0x99, 0xA5, 0xA6, 0x25, 0xA4, 0x85, 0xA4, 0xA0, 0x02, +0x00, 0xA7, 0xB6, 0x25, 0xA4, 0xF0, 0x14, 0x85, 0x9A, 0x22, 0xDE, 0x38, 0xFE, 0x12, 0xB2, 0x92, +0xB2, 0xA5, 0x9A, 0x22, 0x69, 0x39, 0xFE, 0x11, 0xB2, 0x91, 0xB2, 0xC6, 0xC8, 0xF0, 0x1C, 0xA5, +0xB2, 0x18, 0x65, 0xC4, 0x85, 0xB2, 0x90, 0x06, 0xE6, 0xB4, 0xD4, 0xB3, 0xAB, 0xAB, 0xA5, 0xB6, +0x18, 0x65, 0x86, 0x85, 0xB6, 0x90, 0x02, 0xE6, 0xB8, 0x80, 0xC6, 0xAB, 0x6B, 0xA5, 0x56, 0xD0, +0x0E, 0xA5, 0x52, 0x18, 0x65, 0x52, 0x65, 0x52, 0x69, 0x24, 0x00, 0x85, 0xD2, 0x80, 0x04, 0xA5, +0x52, 0x85, 0xD2, 0xA5, 0xD2, 0x1A, 0x18, 0x65, 0x28, 0x0A, 0x0A, 0x4A, 0x4A, 0x4A, 0x29, 0xFE, +0xFF, 0x85, 0xC4, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xD4, 0xC4, 0xD4, 0x50, 0xA2, 0x0B, 0x09, +0x22, 0x00, 0x00, 0xE1, 0xD4, 0x46, 0xD4, 0x44, 0xA2, 0x02, 0x19, 0x22, 0x00, 0x00, 0xE1, 0x90, +0x01, 0x6B, 0xA5, 0x50, 0x85, 0x4A, 0xA5, 0xC4, 0x4A, 0x85, 0x48, 0xA5, 0x56, 0xD0, 0x0A, 0xA9, +0x00, 0x00, 0xA2, 0x00, 0x01, 0x95, 0x04, 0x80, 0x07, 0xA5, 0x52, 0xA2, 0x00, 0x01, 0x95, 0x04, +0xA6, 0x46, 0xA5, 0x44, 0x20, 0x49, 0x69, 0x86, 0xB0, 0x85, 0xAE, 0xA9, 0x00, 0x00, 0x85, 0xCE, +0xA5, 0x48, 0x3A, 0x85, 0xD0, 0xA5, 0x4A, 0x85, 0xCA, 0x22, 0x70, 0x1F, 0xE0, 0x18, 0xA9, 0x00, +0x00, 0x6B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA5, 0x54, 0x0A, 0x85, 0xC4, 0x48, 0xD4, 0x50, +0xA2, 0x0B, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xD4, 0x46, 0xD4, 0x44, 0xA2, 0x02, 0x19, 0x22, 0x00, +0x00, 0xE1, 0x90, 0x01, 0x6B, 0xA5, 0x50, 0x85, 0x4A, 0xA5, 0x54, 0x85, 0x48, 0xA5, 0x56, 0xA2, +0x00, 0x01, 0x95, 0x04, 0xA6, 0x46, 0xA5, 0x44, 0x20, 0x49, 0x69, 0x86, 0xB0, 0x85, 0xAE, 0xA9, +0x00, 0x00, 0x85, 0xCE, 0xA5, 0x48, 0x3A, 0x85, 0xD0, 0xA5, 0x4A, 0x85, 0xCA, 0x22, 0x70, 0x1F, +0xE0, 0x18, 0xA9, 0x00, 0x00, 0x6B, 0xA0, 0x82, 0x00, 0xB7, 0x24, 0x85, 0x30, 0x22, 0xF0, 0x1E, +0xE0, 0x64, 0x2A, 0xA0, 0x7C, 0x00, 0xB7, 0x24, 0x29, 0x04, 0x00, 0xF0, 0x02, 0xC6, 0x2A, 0xA0, +0x8C, 0x00, 0xB7, 0x24, 0x24, 0x2A, 0x30, 0x06, 0xAA, 0xA5, 0x0C, 0x20, 0xD9, 0x16, 0x85, 0x2E, +0xA0, 0x8E, 0x00, 0xB7, 0x24, 0x24, 0x2A, 0x30, 0x06, 0xAA, 0xA5, 0x0C, 0x20, 0xD9, 0x16, 0x85, +0xBE, 0x22, 0xC0, 0x1E, 0xE0, 0xA5, 0x00, 0x85, 0x40, 0x22, 0x98, 0x1E, 0xE0, 0xA5, 0x30, 0x29, +0xFF, 0x7F, 0xC9, 0x04, 0x00, 0xB0, 0x03, 0x4C, 0x0C, 0x74, 0xA5, 0xA4, 0xD0, 0x04, 0x22, 0xCC, +0x1E, 0xE0, 0xA5, 0xC6, 0x85, 0xCC, 0xA5, 0xBA, 0x85, 0x2C, 0xA5, 0xBC, 0x85, 0x2A, 0xA5, 0xA4, +0xF0, 0x04, 0x22, 0xCC, 0x1E, 0xE0, 0x24, 0x30, 0x30, 0x60, 0x24, 0x0B, 0x30, 0x2E, 0xA4, 0x2C, +0xB7, 0xB2, 0xF0, 0x16, 0x22, 0x00, 0x1E, 0xE0, 0xA4, 0x2C, 0xC8, 0xB7, 0xB2, 0xC8, 0x84, 0x2C, +0x22, 0x00, 0x1E, 0xE0, 0xC6, 0xCC, 0x10, 0xE6, 0x80, 0x5E, 0xC8, 0xC8, 0x84, 0x2C, 0xA5, 0x2A, +0x18, 0x69, 0x08, 0x00, 0x85, 0x2A, 0xC6, 0xCC, 0x10, 0xD4, 0x80, 0x4C, 0xA4, 0x2C, 0xB7, 0xB2, +0xF0, 0x16, 0x22, 0x00, 0x1E, 0xE0, 0xA4, 0x2C, 0xC8, 0xB7, 0xB2, 0xC8, 0x84, 0x2C, 0x22, 0x00, +0x1E, 0xE0, 0xC6, 0xCC, 0x10, 0xE6, 0x80, 0x30, 0xC8, 0xC8, 0x84, 0x2C, 0xA5, 0x2A, 0x1A, 0x1A, +0x1A, 0x1A, 0x85, 0x2A, 0xC6, 0xCC, 0x10, 0xD4, 0x80, 0x1E, 0xA4, 0x2C, 0xB7, 0xB2, 0x49, 0xFF, +0xFF, 0x22, 0x00, 0x1E, 0xE0, 0xA4, 0x2C, 0xC8, 0xB7, 0xB2, 0x49, 0xFF, 0xFF, 0xC8, 0x84, 0x2C, +0x22, 0x00, 0x1E, 0xE0, 0xC6, 0xCC, 0x10, 0xE2, 0xA5, 0xB2, 0x18, 0x65, 0xC4, 0x85, 0xB2, 0x90, +0x02, 0xE6, 0xB4, 0xA5, 0xB6, 0x18, 0x65, 0x12, 0x85, 0xB6, 0x90, 0x02, 0xE6, 0xB8, 0xE6, 0x40, +0xC6, 0xC8, 0x30, 0x03, 0x4C, 0x52, 0x73, 0x22, 0x9C, 0x1E, 0xE0, 0x6B, 0xA5, 0xC6, 0x85, 0xCC, +0xA5, 0xBA, 0x85, 0x2C, 0xA5, 0xBC, 0x85, 0x2A, 0x22, 0xCC, 0x1E, 0xE0, 0x24, 0x30, 0x30, 0x1A, +0xA4, 0x2C, 0xB7, 0xB2, 0x22, 0x00, 0x1E, 0xE0, 0xA4, 0x2C, 0xC8, 0xB7, 0xB2, 0xC8, 0x84, 0x2C, +0x22, 0x00, 0x1E, 0xE0, 0xC6, 0xCC, 0x10, 0xE8, 0x80, 0x1E, 0xA4, 0x2C, 0xB7, 0xB2, 0x49, 0xFF, +0xFF, 0x22, 0x00, 0x1E, 0xE0, 0xA4, 0x2C, 0xC8, 0xB7, 0xB2, 0x49, 0xFF, 0xFF, 0xC8, 0x84, 0x2C, +0x22, 0x00, 0x1E, 0xE0, 0xC6, 0xCC, 0x10, 0xE2, 0xA5, 0xB2, 0x18, 0x65, 0xC4, 0x85, 0xB2, 0x90, +0x02, 0xE6, 0xB4, 0xA5, 0xB6, 0x18, 0x65, 0x12, 0x85, 0xB6, 0x90, 0x02, 0xE6, 0xB8, 0xE6, 0x40, +0xC6, 0xC8, 0x10, 0x98, 0x22, 0x9C, 0x1E, 0xE0, 0x6B, 0x5C, 0x44, 0x75, 0xFE, 0x5C, 0xB3, 0x75, +0xFE, 0x5C, 0x15, 0x76, 0xFE, 0x5C, 0x7D, 0x76, 0xFE, 0x5C, 0xEA, 0x76, 0xFE, 0x5C, 0x3B, 0x77, +0xFE, 0x5C, 0x7D, 0x77, 0xFE, 0x5C, 0xC5, 0x77, 0xFE, 0x5C, 0xEB, 0x74, 0xFE, 0x5C, 0x74, 0x75, +0xFE, 0x5C, 0xD6, 0x75, 0xFE, 0x5C, 0x38, 0x76, 0xFE, 0x5C, 0xA3, 0x76, 0xFE, 0x5C, 0x11, 0x77, +0xFE, 0x5C, 0x53, 0x77, 0xFE, 0x5C, 0x95, 0x77, 0xFE, 0x24, 0x0B, 0x10, 0x17, 0x29, 0x7F, 0x00, +0x0A, 0x0A, 0xAA, 0xBF, 0x79, 0x74, 0xFE, 0x8F, 0x00, 0x1E, 0xE0, 0xBF, 0x7B, 0x74, 0xFE, 0x8F, +0x02, 0x1E, 0xE0, 0x6B, 0x29, 0x7F, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x99, 0x74, 0xFE, 0x8F, 0x00, +0x1E, 0xE0, 0xBF, 0x9B, 0x74, 0xFE, 0x8F, 0x02, 0x1E, 0xE0, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, +0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0xA8, 0xBF, 0x3B, 0x4C, 0xFE, 0xBB, 0xA8, 0x25, 0x2E, 0x85, 0xC0, +0x98, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0x85, 0xC0, 0xA4, 0x2A, 0xB7, 0x4C, 0x49, 0xFF, +0xFF, 0x37, 0xB6, 0x85, 0xC2, 0xB7, 0x4C, 0x25, 0xC0, 0x05, 0xC2, 0x97, 0xB6, 0xC8, 0xC8, 0x8A, +0x25, 0x2E, 0x85, 0xC0, 0x8A, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0x85, 0xC0, 0xB7, 0x4C, +0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x85, 0xC2, 0xB7, 0x4C, 0x25, 0xC0, 0x05, 0xC2, 0x97, 0xB6, 0xC8, +0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0xA8, 0x25, 0x2E, +0x85, 0xC0, 0x98, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0x85, 0xC0, 0xA4, 0x2A, 0xB7, 0x4C, +0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x85, 0xC2, 0xB7, 0x4C, 0x25, 0xC0, 0x05, 0xC2, 0x97, 0xB6, 0xC8, +0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0xA8, 0xBF, +0x3B, 0x4C, 0xFE, 0xBB, 0xA8, 0x25, 0x2E, 0x85, 0xC0, 0x98, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, +0xC0, 0xA4, 0x2A, 0x37, 0x4C, 0x17, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x8A, 0x25, 0x2E, 0x85, 0xC0, +0x8A, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0x37, 0x4C, 0x17, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, +0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0xA8, 0x25, 0x2E, 0x85, +0xC0, 0x98, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0xA4, 0x2A, 0x37, 0x4C, 0x17, 0xB6, 0x97, +0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, +0xA8, 0xBF, 0x3B, 0x4C, 0xFE, 0xBB, 0xA8, 0x25, 0x2E, 0x85, 0xC0, 0x98, 0x49, 0xFF, 0xFF, 0x25, +0xBE, 0x05, 0xC0, 0xA4, 0x2A, 0x37, 0x4C, 0x57, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x8A, 0x25, 0x2E, +0x85, 0xC0, 0x8A, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0x37, 0x4C, 0x57, 0xB6, 0x97, 0xB6, +0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0xA8, 0x25, +0x2E, 0x85, 0xC0, 0x98, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0xA4, 0x2A, 0x37, 0x4C, 0x57, +0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, +0x4C, 0xFE, 0xA8, 0xBF, 0x3B, 0x4C, 0xFE, 0xBB, 0xA8, 0x25, 0x2E, 0x85, 0xC0, 0x98, 0x49, 0xFF, +0xFF, 0x25, 0xBE, 0x05, 0xC0, 0xA4, 0x2A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x97, 0xB6, +0xC8, 0xC8, 0x8A, 0x25, 0x2E, 0x85, 0xC0, 0x8A, 0x49, 0xFF, 0xFF, 0x25, 0xBE, 0x05, 0xC0, 0x37, +0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, +0x0A, 0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0xA8, 0x25, 0x2E, 0x85, 0xC0, 0x98, 0x49, 0xFF, 0xFF, 0x25, +0xBE, 0x05, 0xC0, 0xA4, 0x2A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, +0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0xA8, 0xBF, 0x3B, +0x4C, 0xFE, 0xBB, 0xA8, 0x25, 0x2E, 0x85, 0xC0, 0x98, 0xA4, 0x2A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, +0x37, 0xB6, 0x85, 0xC2, 0xB7, 0x4C, 0x25, 0xC0, 0x05, 0xC2, 0x97, 0xB6, 0xC8, 0xC8, 0x8A, 0x25, +0x2E, 0x85, 0xC0, 0x8A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x85, 0xC2, 0xB7, 0x4C, 0x25, +0xC0, 0x05, 0xC2, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0xAA, 0xBF, +0x3B, 0x50, 0xFE, 0xAA, 0x25, 0x2E, 0x85, 0xC0, 0x8A, 0xA4, 0x2A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, +0x37, 0xB6, 0x85, 0xC2, 0xB7, 0x4C, 0x25, 0xC0, 0x05, 0xC2, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, +0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0xA8, 0xBF, 0x3B, 0x4C, 0xFE, +0xBB, 0x25, 0x2E, 0xA4, 0x2A, 0x37, 0x4C, 0x17, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x8A, 0x25, 0x2E, +0x37, 0x4C, 0x17, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0xAA, +0xBF, 0x3B, 0x50, 0xFE, 0x25, 0x2E, 0xA4, 0x2A, 0x37, 0x4C, 0x17, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, +0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0xA8, 0xBF, 0x3B, +0x4C, 0xFE, 0xBB, 0x25, 0x2E, 0xA4, 0x2A, 0x37, 0x4C, 0x57, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x8A, +0x25, 0x2E, 0x37, 0x4C, 0x57, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, +0x0A, 0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0x25, 0x2E, 0xA4, 0x2A, 0x37, 0x4C, 0x57, 0xB6, 0x97, 0xB6, +0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xBF, 0x3D, 0x4C, 0xFE, 0xA8, +0xBF, 0x3B, 0x4C, 0xFE, 0xBB, 0x25, 0x2E, 0xA4, 0x2A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, +0x97, 0xB6, 0xC8, 0xC8, 0x8A, 0x25, 0x2E, 0x37, 0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x97, 0xB6, +0xC8, 0xC8, 0x84, 0x2A, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0xAA, 0xBF, 0x3B, 0x50, 0xFE, 0x25, 0x2E, +0xA4, 0x2A, 0x37, 0x4C, 0x49, 0xFF, 0xFF, 0x37, 0xB6, 0x97, 0xB6, 0xC8, 0xC8, 0x84, 0x2A, 0x6B, +0xE6, 0x77, 0xFE, 0x00, 0x00, 0x00, 0x06, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x08, 0x00, 0x01, 0x01, +0x0C, 0x00, 0x01, 0x90, 0x00, 0x00, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0A, 0x00, +0x08, 0x00, 0x2F, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x00, 0x18, 0x00, 0x40, 0xCF, +0x36, 0xC2, 0x18, 0x18, 0xC7, 0x80, 0x00, 0x00, 0x00, 0xCF, 0x31, 0xE7, 0xB0, 0xF9, 0xEF, 0xDE, +0x78, 0x03, 0x03, 0x0F, 0x3E, 0x7B, 0xE7, 0xBE, 0xFF, 0xDE, 0xCF, 0xC3, 0xC7, 0x84, 0x18, 0xDE, +0xF9, 0xEF, 0x9E, 0xFF, 0x3C, 0x78, 0x79, 0xE7, 0xFF, 0xE0, 0xF3, 0x00, 0x30, 0x18, 0x00, 0x18, +0x07, 0x03, 0x06, 0x1E, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x3F, 0xC3, 0x9A, 0x4F, 0x3C, 0x27, 0x29, 0x24, 0x31, 0x87, 0x24, 0xC9, 0x80, 0x08, 0x81, 0x89, +0x1E, 0x34, 0xB2, 0x33, 0x06, 0x24, 0xC8, 0xCC, 0x18, 0x91, 0x8E, 0x11, 0xE7, 0x03, 0xDC, 0xF8, +0x1D, 0x17, 0x20, 0x3F, 0xBE, 0x00, 0x01, 0x99, 0x88, 0x0E, 0x7D, 0xFC, 0x00, 0xCF, 0xBC, 0xF0, +0x00, 0x00, 0x6C, 0x00, 0xF0, 0xC0, 0x20, 0x00, 0x00, 0x01, 0x0C, 0xB9, 0x7F, 0x00, 0x00, 0x06, +0xDB, 0x6C, 0x02, 0x12, 0xFF, 0xFC, 0x10, 0x00, 0xE0, 0x8F, 0x3F, 0xEF, 0xAD, 0x20, 0xD8, 0x64, +0x8C, 0x00, 0x01, 0x93, 0xF3, 0x3C, 0xF3, 0xC3, 0x00, 0xF3, 0xCC, 0x06, 0x01, 0x99, 0xC1, 0xCF, +0x3C, 0xF3, 0xC6, 0x33, 0xCD, 0x83, 0xCD, 0x86, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0x33, 0x3C, 0x78, +0x79, 0xE6, 0x1E, 0x30, 0x35, 0x80, 0x18, 0x18, 0x00, 0x18, 0x0C, 0x03, 0x00, 0x06, 0x0C, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x70, 0x19, 0xE6, 0x49, +0xC0, 0x00, 0x60, 0xC9, 0x81, 0x32, 0x40, 0x10, 0x42, 0xC0, 0x33, 0x58, 0x4C, 0x61, 0x8B, 0x01, +0x31, 0x86, 0x2C, 0x07, 0xFB, 0x13, 0x1C, 0x07, 0xF2, 0xCD, 0xE9, 0xBC, 0x03, 0x66, 0x63, 0x00, +0x63, 0x0D, 0x88, 0x13, 0x32, 0xD8, 0x09, 0xB9, 0xE7, 0x98, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x01, +0x20, 0x00, 0x00, 0x00, 0x93, 0x4E, 0xCC, 0x00, 0x00, 0x0D, 0x9B, 0xCC, 0x85, 0x00, 0xC7, 0x8C, +0x6C, 0x0D, 0xF3, 0x6F, 0x36, 0xDA, 0x1A, 0x30, 0xF0, 0x33, 0x0C, 0x00, 0x03, 0x33, 0x30, 0x30, +0xF3, 0xFB, 0xE1, 0xB3, 0xCF, 0x6C, 0xFC, 0xC1, 0xCD, 0xCF, 0x3C, 0x33, 0xC6, 0x30, 0xCD, 0x83, +0xD9, 0x87, 0x7E, 0xF3, 0xCF, 0x3C, 0xF0, 0x33, 0x3C, 0x7B, 0x6F, 0x66, 0x36, 0x18, 0x38, 0xC0, +0x0B, 0xFF, 0x3C, 0xFB, 0xDF, 0x7F, 0xEE, 0x3E, 0x6D, 0xFD, 0xF3, 0xDF, 0x3F, 0xB7, 0xBE, 0xCF, +0x1E, 0x1E, 0x79, 0xFE, 0x46, 0x20, 0x03, 0xCF, 0x61, 0xF0, 0x0F, 0x66, 0x00, 0x00, 0x3E, 0x01, +0x8F, 0x3C, 0xF0, 0x0F, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x01, 0x99, 0x9B, 0x7B, +0x07, 0x87, 0xF4, 0xFB, 0x09, 0x50, 0x1F, 0xE6, 0x67, 0x00, 0x66, 0x06, 0xD6, 0x61, 0x98, 0xDB, +0xF1, 0x99, 0xE7, 0x9B, 0xDC, 0x78, 0x6C, 0x00, 0xC3, 0x1E, 0x51, 0x9E, 0x60, 0x03, 0xC0, 0x00, +0xCC, 0x7B, 0x80, 0x0D, 0xB6, 0xD8, 0x08, 0xB3, 0xB3, 0x64, 0x86, 0x1B, 0xFF, 0xFC, 0x06, 0xCF, +0x84, 0x1A, 0x30, 0x3F, 0xFF, 0x1F, 0x86, 0x33, 0x30, 0x63, 0xB3, 0x0F, 0x33, 0x1E, 0xCC, 0x18, +0x00, 0x63, 0x55, 0xCF, 0xEC, 0x33, 0xF7, 0xB7, 0xFD, 0x83, 0xF1, 0x87, 0xFF, 0xF3, 0xFB, 0x3F, +0x9E, 0x33, 0x36, 0xDB, 0x66, 0x3C, 0x66, 0x0C, 0x30, 0x00, 0x06, 0x79, 0xE7, 0x9E, 0x6C, 0xCF, +0x36, 0x1E, 0xCD, 0xB7, 0x9E, 0x79, 0xE7, 0xCC, 0x18, 0xCF, 0x1E, 0xDB, 0xD9, 0x8D, 0x86, 0x18, +0x06, 0x79, 0xE1, 0x8C, 0x39, 0xE6, 0xFB, 0xEF, 0xE6, 0xFB, 0xF9, 0xE7, 0x9B, 0xF9, 0xF7, 0x73, +0x7C, 0xF3, 0xCF, 0x66, 0xF6, 0x79, 0xE7, 0x9F, 0xEE, 0xC7, 0xCC, 0xFF, 0xF2, 0xCF, 0x00, 0x00, +0x06, 0x67, 0xEB, 0x6D, 0xFB, 0x0D, 0xFE, 0x6F, 0x8C, 0xD9, 0xB1, 0x99, 0xE7, 0x98, 0x67, 0x9D, +0xEF, 0xF1, 0x8F, 0xE1, 0x53, 0x33, 0x30, 0x06, 0x6F, 0x3E, 0xCF, 0xCC, 0xFF, 0xF0, 0x00, 0x03, +0xF0, 0x73, 0xF3, 0xE4, 0x85, 0x31, 0xF7, 0xEC, 0x0F, 0xE2, 0xCB, 0x2C, 0x30, 0x33, 0x0C, 0x00, +0x0C, 0x33, 0x30, 0xC0, 0xFF, 0x0F, 0x33, 0x33, 0x7C, 0x0C, 0xFC, 0xC6, 0x55, 0xFF, 0x3C, 0x33, +0xC6, 0x33, 0xCD, 0x83, 0xD9, 0x86, 0xBD, 0xF3, 0xC3, 0x3D, 0x83, 0x33, 0x36, 0xDB, 0x6F, 0x18, +0xC6, 0x06, 0x30, 0x00, 0x06, 0x79, 0xE1, 0x9F, 0xEC, 0xCF, 0x36, 0x1F, 0x8D, 0xB7, 0x9E, 0x79, +0xE7, 0x87, 0x98, 0xCD, 0xB6, 0xD9, 0x9B, 0x98, 0x46, 0x20, 0x06, 0x79, 0xE1, 0xEF, 0x39, 0xE7, +0x9E, 0x79, 0xE7, 0x9E, 0x78, 0x7F, 0xFE, 0x5F, 0xB3, 0x33, 0x67, 0x9E, 0x79, 0xE7, 0x9E, 0x79, +0xE7, 0x99, 0x80, 0xC3, 0x0C, 0xFB, 0xF3, 0x01, 0xE0, 0x00, 0x1F, 0xFE, 0x73, 0x9A, 0x61, 0x98, +0x66, 0x79, 0x88, 0xD9, 0xB1, 0x8F, 0xBD, 0x9B, 0xFF, 0xAF, 0x0C, 0x31, 0x83, 0x1E, 0x8E, 0x61, +0x98, 0x06, 0x79, 0xE3, 0xCC, 0xCF, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xB7, 0xC7, 0xCC, 0x96, 0xE0, +0xE7, 0xF0, 0x06, 0xDA, 0xD5, 0xE6, 0x30, 0x34, 0x8C, 0x00, 0x18, 0x32, 0x31, 0x8C, 0xC3, 0xCF, +0x36, 0x33, 0x0C, 0x06, 0x01, 0x80, 0x5B, 0xCF, 0x3C, 0xF3, 0xC6, 0x33, 0xCD, 0xB3, 0xCD, 0x86, +0x3C, 0xF3, 0xC3, 0x3C, 0xF3, 0x33, 0x33, 0x8C, 0xD9, 0x99, 0x86, 0x03, 0x30, 0x00, 0x06, 0x79, +0xE7, 0x9E, 0x0C, 0x7F, 0x36, 0x1E, 0xCD, 0xB7, 0x9E, 0x79, 0xE7, 0x80, 0xDB, 0xCD, 0xB3, 0x33, +0xCD, 0xB0, 0x66, 0x60, 0x07, 0xFF, 0xE7, 0x89, 0xF9, 0xE7, 0x9E, 0x79, 0xE7, 0x9E, 0x79, 0xE1, +0x86, 0x98, 0x33, 0x33, 0x67, 0x9E, 0x79, 0xE7, 0x9E, 0x79, 0xE7, 0x99, 0x80, 0x7B, 0x17, 0xB9, +0x7B, 0x00, 0x00, 0x00, 0x0C, 0x66, 0x63, 0xB2, 0x60, 0x01, 0xFE, 0xF9, 0x90, 0xD9, 0xB1, 0x80, +0x00, 0x96, 0x61, 0xCF, 0x3C, 0x31, 0x83, 0x20, 0x8B, 0x33, 0x30, 0x07, 0xFF, 0xE3, 0xCC, 0xCC, +0x00, 0x00, 0x00, 0x00, 0x85, 0x1B, 0xFF, 0xFC, 0x6C, 0x40, 0x43, 0x6C, 0x00, 0x0F, 0x83, 0x3B, +0x18, 0x60, 0x00, 0x60, 0x70, 0x3C, 0xFF, 0xF7, 0x83, 0x79, 0xE6, 0x1E, 0x7B, 0x63, 0x03, 0x06, +0x40, 0xCF, 0xE7, 0xBE, 0xFE, 0x1E, 0xCF, 0xDE, 0xC7, 0xFE, 0x3C, 0x5E, 0xC1, 0xEC, 0xDE, 0x31, +0xE3, 0x8C, 0xD9, 0x99, 0xFE, 0x01, 0x30, 0x00, 0x03, 0xFF, 0x3C, 0xFB, 0xCC, 0x8F, 0x3F, 0xDE, +0x7F, 0xB7, 0x9B, 0xDF, 0x3F, 0x87, 0x8E, 0x7C, 0xE3, 0x36, 0x71, 0xFE, 0x66, 0x60, 0x06, 0x79, +0xBD, 0xF8, 0x6F, 0x3C, 0xFB, 0xEF, 0xBE, 0xFB, 0xEF, 0x3C, 0xF3, 0xEF, 0x7F, 0xFF, 0xE6, 0xF3, +0xCF, 0x3C, 0xF3, 0xEF, 0xBE, 0xF9, 0x80, 0x17, 0xE0, 0xC1, 0x76, 0x00, 0x00, 0x00, 0x00, 0x67, +0xBE, 0x6D, 0xFF, 0xFE, 0x67, 0x2F, 0x22, 0xDB, 0x65, 0x9F, 0xBD, 0x9B, 0xDC, 0xF1, 0xEC, 0x0F, +0x02, 0x00, 0xF9, 0x9E, 0x66, 0xDE, 0x79, 0xBE, 0x7F, 0x7B, 0x80, 0x00, 0x00, 0x00, 0x02, 0x23, +0xCF, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x07, 0x80, 0x00, 0xC0, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, +0xF0, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x06, 0x00, +0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +0x80, 0x10, 0x03, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +0x7C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x07, 0x00, 0x0E, 0x00, 0x15, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, +0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, +0x1E, 0x00, 0x24, 0x00, 0x2B, 0x00, 0x32, 0x00, 0x39, 0x00, 0x40, 0x00, 0x42, 0x00, 0x47, 0x00, +0x4C, 0x00, 0x52, 0x00, 0x58, 0x00, 0x5B, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6A, 0x00, 0x70, 0x00, +0x76, 0x00, 0x7C, 0x00, 0x82, 0x00, 0x88, 0x00, 0x8E, 0x00, 0x94, 0x00, 0x9A, 0x00, 0xA0, 0x00, +0xA6, 0x00, 0xA8, 0x00, 0xAB, 0x00, 0xB0, 0x00, 0xB6, 0x00, 0xBB, 0x00, 0xC1, 0x00, 0xC8, 0x00, +0xCE, 0x00, 0xD4, 0x00, 0xDA, 0x00, 0xE0, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0xF0, 0x00, 0xF6, 0x00, +0xFA, 0x00, 0x00, 0x01, 0x07, 0x01, 0x0D, 0x01, 0x14, 0x01, 0x1A, 0x01, 0x20, 0x01, 0x26, 0x01, +0x2C, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3E, 0x01, 0x44, 0x01, 0x4B, 0x01, 0x53, 0x01, 0x59, 0x01, +0x5F, 0x01, 0x65, 0x01, 0x69, 0x01, 0x70, 0x01, 0x74, 0x01, 0x7A, 0x01, 0x82, 0x01, 0x85, 0x01, +0x8B, 0x01, 0x91, 0x01, 0x97, 0x01, 0x9D, 0x01, 0xA3, 0x01, 0xA8, 0x01, 0xAE, 0x01, 0xB4, 0x01, +0xB8, 0x01, 0xBD, 0x01, 0xC3, 0x01, 0xC7, 0x01, 0xCF, 0x01, 0xD5, 0x01, 0xDB, 0x01, 0xE1, 0x01, +0xE7, 0x01, 0xEC, 0x01, 0xF2, 0x01, 0xF8, 0x01, 0xFE, 0x01, 0x05, 0x02, 0x0D, 0x02, 0x13, 0x02, +0x19, 0x02, 0x1F, 0x02, 0x25, 0x02, 0x27, 0x02, 0x2D, 0x02, 0x35, 0x02, 0x35, 0x02, 0x3B, 0x02, +0x41, 0x02, 0x47, 0x02, 0x4C, 0x02, 0x53, 0x02, 0x59, 0x02, 0x5F, 0x02, 0x65, 0x02, 0x6B, 0x02, +0x71, 0x02, 0x77, 0x02, 0x7D, 0x02, 0x83, 0x02, 0x89, 0x02, 0x8F, 0x02, 0x95, 0x02, 0x9B, 0x02, +0xA1, 0x02, 0xA5, 0x02, 0xA9, 0x02, 0xAD, 0x02, 0xB1, 0x02, 0xB7, 0x02, 0xBD, 0x02, 0xC3, 0x02, +0xC9, 0x02, 0xCF, 0x02, 0xD5, 0x02, 0xDB, 0x02, 0xE1, 0x02, 0xE7, 0x02, 0xED, 0x02, 0xF3, 0x02, +0xF8, 0x02, 0xFD, 0x02, 0x04, 0x03, 0x0A, 0x03, 0x0D, 0x03, 0x12, 0x03, 0x18, 0x03, 0x1E, 0x03, +0x23, 0x03, 0x2C, 0x03, 0x2F, 0x03, 0x33, 0x03, 0x39, 0x03, 0x41, 0x03, 0x48, 0x03, 0x4F, 0x03, +0x55, 0x03, 0x5A, 0x03, 0x5F, 0x03, 0x65, 0x03, 0x6B, 0x03, 0x71, 0x03, 0x77, 0x03, 0x7E, 0x03, +0x85, 0x03, 0x8B, 0x03, 0x91, 0x03, 0x97, 0x03, 0x9D, 0x03, 0xA7, 0x03, 0xAE, 0x03, 0xB4, 0x03, +0xB6, 0x03, 0xBC, 0x03, 0xC4, 0x03, 0xCA, 0x03, 0xD0, 0x03, 0xD5, 0x03, 0xDD, 0x03, 0xE5, 0x03, +0xED, 0x03, 0xED, 0x03, 0xF3, 0x03, 0xF9, 0x03, 0x00, 0x04, 0x08, 0x04, 0x12, 0x04, 0x15, 0x04, +0x1C, 0x04, 0x22, 0x04, 0x28, 0x04, 0x2B, 0x04, 0x2E, 0x04, 0x33, 0x04, 0x3A, 0x04, 0x40, 0x04, +0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, +0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, +0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, +0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, +0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x47, 0x04, 0x4E, 0x04, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0x04, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x04, 0x00, 0x06, 0x02, 0x08, 0x01, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x01, 0x06, 0x02, +0x07, 0x01, 0x07, 0x01, 0x07, 0x00, 0x08, 0x01, 0x05, 0x01, 0x08, 0x01, 0x04, 0x01, 0x08, 0x00, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x01, 0x04, 0x01, 0x05, 0x01, 0x07, 0x01, 0x08, 0x01, 0x07, 0x01, 0x08, 0x01, +0x08, 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x07, 0x01, 0x07, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x02, 0x08, 0x01, 0x09, 0x01, 0x08, 0x01, 0x09, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x09, 0x01, 0x09, 0x00, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x06, 0x01, 0x08, 0x00, 0x06, 0x01, 0x08, 0x01, 0x08, 0x00, +0x05, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x07, 0x01, 0x08, 0x01, +0x08, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x08, 0x02, 0x09, 0x00, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x01, 0x07, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x09, 0x01, 0x09, 0x00, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x06, 0x02, 0x08, 0x01, 0x09, 0x00, 0x01, 0x00, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x07, 0x01, 0x09, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x01, 0x06, 0x01, 0x06, 0x01, 0x06, 0x01, 0x06, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x01, 0x07, 0x01, 0x07, 0x01, 0x08, 0x00, 0x08, 0x01, 0x07, 0x02, 0x07, 0x01, 0x08, 0x01, +0x08, 0x01, 0x07, 0x01, 0x0B, 0x01, 0x07, 0x02, 0x06, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x09, 0x01, +0x08, 0x00, 0x08, 0x01, 0x07, 0x01, 0x07, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, +0x08, 0x00, 0x08, 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x0C, 0x01, 0x09, 0x01, +0x08, 0x01, 0x06, 0x02, 0x08, 0x01, 0x08, 0x00, 0x08, 0x01, 0x08, 0x01, 0x07, 0x01, 0x08, 0x00, +0x08, 0x00, 0x08, 0x00, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x09, 0x01, 0x0A, 0x01, 0x0C, 0x01, +0x05, 0x01, 0x08, 0x00, 0x08, 0x01, 0x08, 0x01, 0x05, 0x01, 0x05, 0x01, 0x07, 0x01, 0x08, 0x00, +0x08, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +0x01, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, +0x08, 0x00, 0xFF, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0xF0, 0x82, 0x38, 0xA5, 0xAA, 0xE5, 0xA6, 0x85, +0xB0, 0x38, 0xA5, 0xAC, 0xE5, 0xA8, 0x85, 0xAE, 0xA2, 0x00, 0x00, 0x22, 0xE2, 0x80, 0xFE, 0xAA, +0xA0, 0x04, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0xF0, 0x82, 0xA2, 0x01, 0x00, 0x22, +0xE2, 0x80, 0xFE, 0xAA, 0xA0, 0x04, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0xF0, 0x82, +0xA2, 0x02, 0x00, 0x22, 0xE2, 0x80, 0xFE, 0xAA, 0xA0, 0x04, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, +0x0D, 0x20, 0xF0, 0x82, 0xA2, 0x03, 0x00, 0x22, 0xE2, 0x80, 0xFE, 0xAA, 0xA0, 0x04, 0x00, 0x4C, +0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, 0x83, +0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x04, 0x00, 0x22, 0xE2, 0x80, 0xFE, 0xAA, 0xA0, 0x08, 0x00, 0x4C, +0x22, 0xFF, 0x86, 0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x1F, 0xA9, 0x68, 0x01, 0x85, 0xD2, 0x64, 0xD4, +0xA2, 0x00, 0x02, 0x38, 0xA5, 0xAA, 0xE5, 0xA6, 0x95, 0x08, 0x38, 0xA5, 0xAC, 0xE5, 0xA8, 0x95, +0x0A, 0xA9, 0x50, 0x00, 0x5C, 0xC0, 0x1F, 0xE0, 0x8B, 0xA0, 0x10, 0x00, 0xB7, 0x2A, 0x48, 0xC8, +0xB7, 0x2A, 0x83, 0x02, 0x6B, 0xA9, 0x60, 0x00, 0x80, 0x08, 0xA9, 0x50, 0x00, 0x80, 0x03, 0xA9, +0x40, 0x00, 0x85, 0x3A, 0x22, 0xF8, 0x1E, 0xE0, 0x90, 0x01, 0x6B, 0x64, 0xEE, 0xA5, 0x38, 0xD0, +0x18, 0xA5, 0x3A, 0xC9, 0x60, 0x00, 0xF0, 0x0C, 0x20, 0x21, 0x54, 0x90, 0x07, 0x22, 0x9C, 0x1F, +0xE0, 0x90, 0x01, 0x6B, 0xE6, 0xEE, 0x82, 0x24, 0x05, 0x4C, 0xAB, 0x21, 0x20, 0xB3, 0x0D, 0x20, +0x0E, 0x83, 0xA2, 0x00, 0x02, 0xB5, 0x08, 0x85, 0xB0, 0xB5, 0x0A, 0x85, 0xAE, 0xA3, 0x0D, 0x83, +0x09, 0xA3, 0x0F, 0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x00, 0x00, 0x22, 0xFE, 0x81, 0xFE, 0xAA, +0xA0, 0x08, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x0E, 0x83, 0xA3, 0x0D, 0x83, 0x09, +0xA3, 0x0F, 0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x01, 0x00, 0x22, 0xFE, 0x81, 0xFE, 0xAA, 0xA0, +0x08, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x0E, 0x83, 0xA3, 0x0D, 0x83, 0x09, 0xA3, +0x0F, 0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x02, 0x00, 0x22, 0xFE, 0x81, 0xFE, 0xAA, 0xA0, 0x08, +0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x0E, 0x83, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, +0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x03, 0x00, 0x22, 0xFE, 0x81, 0xFE, 0xAA, 0xA0, 0x08, 0x00, +0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, 0xA2, 0x00, 0x02, 0xA3, 0x0D, 0x95, +0x08, 0xA3, 0x0F, 0x95, 0x0A, 0xA3, 0x11, 0x83, 0x09, 0xA3, 0x13, 0x83, 0x0B, 0x20, 0xF0, 0x82, +0xA2, 0x04, 0x00, 0x22, 0xFE, 0x81, 0xFE, 0xAA, 0xA0, 0x0C, 0x00, 0x4C, 0x22, 0xFF, 0x86, 0x38, +0x20, 0xC5, 0x0D, 0xB0, 0x0E, 0xA9, 0x68, 0x01, 0x85, 0xD2, 0x64, 0xD4, 0xA9, 0x40, 0x00, 0x5C, +0xC0, 0x1F, 0xE0, 0x8B, 0xA0, 0x0C, 0x00, 0xB7, 0x2A, 0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, +0x20, 0xB3, 0x0D, 0x20, 0x1A, 0x83, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, 0x83, 0x0B, 0x20, 0xF0, +0x82, 0xA2, 0x00, 0x00, 0x22, 0xC4, 0x82, 0xFE, 0xAA, 0xA0, 0x08, 0x00, 0x4C, 0x22, 0xFF, 0x20, +0xB3, 0x0D, 0x20, 0x1A, 0x83, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, 0x83, 0x0B, 0x20, 0xF0, 0x82, +0xA2, 0x01, 0x00, 0x22, 0xC4, 0x82, 0xFE, 0xAA, 0xA0, 0x08, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, +0x0D, 0x20, 0x1A, 0x83, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, 0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, +0x02, 0x00, 0x22, 0xC4, 0x82, 0xFE, 0xAA, 0xA0, 0x08, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, +0x20, 0x1A, 0x83, 0xA3, 0x0D, 0x83, 0x09, 0xA3, 0x0F, 0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x03, +0x00, 0x22, 0xC4, 0x82, 0xFE, 0xAA, 0xA0, 0x08, 0x00, 0x4C, 0x22, 0xFF, 0x20, 0xB3, 0x0D, 0x22, +0x40, 0x1E, 0xE0, 0xA3, 0x0F, 0x85, 0xD4, 0xA3, 0x0D, 0x85, 0xD2, 0xA3, 0x11, 0x83, 0x09, 0xA3, +0x13, 0x83, 0x0B, 0x20, 0xF0, 0x82, 0xA2, 0x04, 0x00, 0x22, 0xC4, 0x82, 0xFE, 0xAA, 0xA0, 0x0C, +0x00, 0x4C, 0x22, 0xFF, 0x86, 0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x18, 0xA2, 0x00, 0x02, 0x38, 0xA5, +0xAA, 0xE5, 0xA6, 0x95, 0x08, 0x38, 0xA5, 0xAC, 0xE5, 0xA8, 0x95, 0x0A, 0xA9, 0x60, 0x00, 0x5C, +0xC0, 0x1F, 0xE0, 0x8B, 0xA0, 0x14, 0x00, 0xB7, 0x2A, 0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, +0xA3, 0x0B, 0x85, 0x2A, 0xA3, 0x0D, 0x85, 0x2C, 0xA2, 0x06, 0x02, 0xA0, 0x06, 0x00, 0xDA, 0xBB, +0xB7, 0x2A, 0x95, 0xA6, 0xFA, 0x95, 0x00, 0xCA, 0xCA, 0x88, 0x88, 0x10, 0xF1, 0x60, 0xA2, 0x00, +0x02, 0xA3, 0x0B, 0x95, 0x08, 0xA3, 0x0D, 0x95, 0x0A, 0x60, 0xA3, 0x0D, 0x85, 0xD4, 0xA3, 0x0B, +0x85, 0xD2, 0x60, 0x64, 0x2C, 0x06, 0x30, 0x26, 0x2C, 0xF0, 0x13, 0xA5, 0x2E, 0x49, 0xFF, 0xFF, +0x1A, 0x85, 0x2E, 0xF0, 0x02, 0xC6, 0x30, 0xA5, 0x30, 0x49, 0xFF, 0xFF, 0x85, 0x30, 0x38, 0xA5, +0x2E, 0xE9, 0xF4, 0x01, 0xB0, 0x02, 0xC6, 0x30, 0x64, 0x2A, 0x80, 0x02, 0xE6, 0x2A, 0x20, 0xB2, +0x83, 0xA5, 0xE4, 0xC5, 0x30, 0x30, 0xF5, 0xD0, 0x06, 0xA5, 0xE2, 0xC5, 0x2E, 0x30, 0xED, 0xA5, +0x2C, 0xF0, 0x08, 0x38, 0xA9, 0xB4, 0x00, 0xE5, 0x2A, 0x85, 0x2A, 0x6B, 0xA5, 0x2A, 0x80, 0x04, +0x38, 0xE9, 0xB4, 0x00, 0xC9, 0xB4, 0x00, 0x10, 0xF7, 0xAA, 0x10, 0x06, 0x18, 0x69, 0xB4, 0x00, +0x30, 0xFA, 0x85, 0x2A, 0x64, 0x2C, 0xC9, 0x5B, 0x00, 0x30, 0x0C, 0xE6, 0x2C, 0x38, 0xE9, 0xB4, +0x00, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x2A, 0x20, 0xB2, 0x83, 0xA5, 0x2C, 0xD0, 0x13, 0xA5, 0xE2, +0x49, 0xFF, 0xFF, 0x1A, 0x85, 0xE2, 0xD0, 0x02, 0xC6, 0xE4, 0xA5, 0xE4, 0x49, 0xFF, 0xFF, 0x85, +0xE4, 0x6B, 0xA9, 0x5A, 0x00, 0xC5, 0x2A, 0xD0, 0x0B, 0xA9, 0xFF, 0x3F, 0x85, 0xE4, 0xA9, 0xFF, +0xFF, 0x85, 0xE2, 0x60, 0x64, 0xE4, 0xA5, 0x2A, 0xC9, 0x2D, 0x00, 0x30, 0x13, 0xE6, 0xE4, 0xC9, +0x40, 0x00, 0x30, 0x0C, 0xAA, 0xBF, 0xAD, 0x83, 0xFE, 0x29, 0xFF, 0x00, 0x85, 0xE4, 0xA5, 0x2A, +0x0A, 0xAA, 0xBF, 0x07, 0x84, 0xFE, 0x85, 0xE2, 0x60, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, +0x08, 0x09, 0x0B, 0x0E, 0x13, 0x1C, 0x39, 0x00, 0x00, 0x78, 0x04, 0xF1, 0x08, 0x6B, 0x0D, 0xE7, +0x11, 0x66, 0x16, 0xE8, 0x1A, 0x6F, 0x1F, 0xFA, 0x23, 0x8C, 0x28, 0x24, 0x2D, 0xC3, 0x31, 0x6A, +0x36, 0x1A, 0x3B, 0xD4, 0x3F, 0x98, 0x44, 0x68, 0x49, 0x44, 0x4E, 0x2E, 0x53, 0x26, 0x58, 0x2D, +0x5D, 0x45, 0x62, 0x6E, 0x67, 0xAA, 0x6C, 0xFB, 0x71, 0x60, 0x77, 0xDC, 0x7C, 0x70, 0x82, 0x1E, +0x88, 0xE7, 0x8D, 0xCD, 0x93, 0xD2, 0x99, 0xF7, 0x9F, 0x40, 0xA6, 0xAD, 0xAC, 0x41, 0xB3, 0xFF, +0xB9, 0xE9, 0xC0, 0x02, 0xC8, 0x4E, 0xCF, 0xCF, 0xD6, 0x8A, 0xDE, 0x81, 0xE6, 0xB9, 0xEE, 0x37, +0xF7, 0x00, 0x00, 0x19, 0x09, 0x87, 0x12, 0x51, 0x1C, 0x7F, 0x26, 0x17, 0x31, 0x22, 0x3C, 0xAA, +0x47, 0xB9, 0x53, 0x5B, 0x60, 0x98, 0x6D, 0x89, 0x7B, 0x35, 0x8A, 0xAF, 0x99, 0x0E, 0xAA, 0x68, +0xBB, 0xD6, 0xCD, 0x77, 0xE1, 0x6E, 0xF6, 0xE1, 0x0C, 0xFE, 0x24, 0xFC, 0x3E, 0x19, 0x5B, 0x9F, +0x79, 0xE7, 0x9A, 0x5B, 0xBF, 0x7A, 0xE7, 0xE3, 0x13, 0x56, 0x45, 0xC7, 0x7C, 0x68, 0xBB, 0xC2, +0x02, 0xDB, 0x54, 0x62, 0xB4, 0x01, 0x25, 0xD9, 0xAB, 0x51, 0x50, 0x88, 0x1D, 0xF3, 0x24, 0xAD, +0x83, 0x17, 0x6E, 0xF5, 0x4C, 0xBD, 0x14, 0xD7, 0xA2, 0x30, 0x4A, 0xFF, 0xFF, 0xB5, 0x08, 0x10, +0x05, 0xA9, 0x00, 0x00, 0x95, 0x08, 0xB5, 0x0A, 0x10, 0x05, 0xA9, 0x00, 0x00, 0x95, 0x0A, 0x38, +0xB5, 0x06, 0xF5, 0x02, 0xD5, 0x0A, 0x10, 0x02, 0x95, 0x0A, 0x38, 0xB5, 0x04, 0xF5, 0x00, 0xD5, +0x08, 0x10, 0x02, 0x95, 0x08, 0xA9, 0x00, 0x00, 0x95, 0x0C, 0x95, 0x10, 0x95, 0x18, 0x95, 0x1A, +0x95, 0x1C, 0x95, 0x1E, 0x95, 0x16, 0xB5, 0x06, 0x95, 0x0E, 0xB5, 0x02, 0x95, 0x12, 0x64, 0x2A, +0xB5, 0x0A, 0x85, 0x2C, 0x46, 0x2C, 0x66, 0x2A, 0x18, 0xB5, 0x10, 0x65, 0x2A, 0x95, 0x10, 0xB5, +0x12, 0x65, 0x2C, 0x95, 0x12, 0x38, 0xB5, 0x0C, 0xE5, 0x2A, 0x95, 0x0C, 0xB5, 0x0E, 0xE5, 0x2C, +0x95, 0x0E, 0x18, 0xA9, 0x00, 0x80, 0x75, 0x0C, 0x95, 0x0C, 0x90, 0x02, 0xF6, 0x0E, 0xB5, 0x08, +0x49, 0xFF, 0xFF, 0x1A, 0x1A, 0x95, 0x30, 0xB5, 0x08, 0x0A, 0x3A, 0x95, 0x14, 0xDA, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xB5, 0x08, 0x48, 0xB5, 0x0A, 0x48, 0xA2, 0x0B, 0x0E, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x03, 0x48, +0xA3, 0x03, 0x48, 0xA2, 0x0B, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x09, 0xAA, 0x68, 0x95, 0x20, +0x0A, 0x95, 0x28, 0x68, 0x95, 0x22, 0x2A, 0x95, 0x2A, 0x68, 0x95, 0x24, 0x2A, 0x95, 0x2C, 0x68, +0x95, 0x26, 0x2A, 0x95, 0x2E, 0xFA, 0x6B, 0xA5, 0x40, 0xD5, 0x00, 0x30, 0x04, 0xD5, 0x04, 0x30, +0x4B, 0x6B, 0xB5, 0x0C, 0x18, 0x69, 0x00, 0x80, 0x95, 0x0C, 0x90, 0x02, 0xF6, 0x0E, 0xB5, 0x10, +0x38, 0xE9, 0x00, 0x80, 0x95, 0x10, 0xB0, 0x02, 0xD6, 0x12, 0x18, 0xB5, 0x18, 0x75, 0x20, 0x95, +0x18, 0xB5, 0x1A, 0x75, 0x22, 0x95, 0x1A, 0xB5, 0x1C, 0x75, 0x24, 0x95, 0x1C, 0xB5, 0x1E, 0x75, +0x26, 0x95, 0x1E, 0x18, 0xB5, 0x20, 0x75, 0x28, 0x95, 0x20, 0xB5, 0x22, 0x75, 0x2A, 0x95, 0x22, +0xB5, 0x24, 0x75, 0x2C, 0x95, 0x24, 0xB5, 0x26, 0x75, 0x2E, 0x95, 0x26, 0xB5, 0x1E, 0xD5, 0x16, +0x90, 0xB0, 0xD0, 0x06, 0xB5, 0x1C, 0xD5, 0x14, 0x90, 0xA8, 0x80, 0x4A, 0x38, 0xB5, 0x0C, 0xE9, +0x00, 0x80, 0x95, 0x0C, 0xB0, 0x02, 0xD6, 0x0E, 0x18, 0xB5, 0x10, 0x69, 0x00, 0x80, 0x95, 0x10, +0x90, 0x02, 0xF6, 0x12, 0x38, 0xB5, 0x20, 0xF5, 0x28, 0x95, 0x20, 0xB5, 0x22, 0xF5, 0x2A, 0x95, +0x22, 0xB5, 0x24, 0xF5, 0x2C, 0x95, 0x24, 0xB5, 0x26, 0xF5, 0x2E, 0x95, 0x26, 0x38, 0xB5, 0x18, +0xF5, 0x20, 0x95, 0x18, 0xB5, 0x1A, 0xF5, 0x22, 0x95, 0x1A, 0xB5, 0x1C, 0xF5, 0x24, 0x95, 0x1C, +0xB5, 0x1E, 0xF5, 0x26, 0x95, 0x1E, 0xB5, 0x16, 0xD5, 0x1E, 0x90, 0xB0, 0xD0, 0x06, 0xB5, 0x14, +0xD5, 0x1C, 0x90, 0xA8, 0xB5, 0x30, 0x1A, 0x85, 0x2A, 0x1A, 0x95, 0x30, 0x64, 0x2C, 0xA5, 0x2A, +0x10, 0x05, 0xA9, 0xFF, 0xFF, 0x85, 0x2C, 0x06, 0x2A, 0x26, 0x2C, 0x06, 0x2A, 0x26, 0x2C, 0x38, +0xB5, 0x14, 0xE5, 0x2A, 0x95, 0x14, 0xB5, 0x16, 0xE5, 0x2C, 0x95, 0x16, 0x6B, 0x20, 0x73, 0x86, +0x4C, 0xAB, 0x21, 0xA0, 0x44, 0x00, 0xB7, 0x24, 0xF0, 0x0B, 0x85, 0x2E, 0xC8, 0xC8, 0xB7, 0x24, +0xF0, 0x03, 0x85, 0x30, 0x60, 0x68, 0x18, 0xA9, 0x00, 0x00, 0x6B, 0xA5, 0xD2, 0xD0, 0x01, 0x6B, +0x8B, 0x22, 0xC0, 0x1E, 0xE0, 0x22, 0xE8, 0x1E, 0xE0, 0xA5, 0xD2, 0x10, 0x0B, 0x18, 0x65, 0xD4, +0x85, 0xD4, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0xD2, 0x64, 0xAE, 0xC9, 0x68, 0x01, 0x30, 0x03, 0x82, +0x1C, 0x01, 0xA5, 0xD4, 0x20, 0x59, 0x8A, 0x85, 0xD4, 0x18, 0x65, 0xD2, 0x20, 0x59, 0x8A, 0x85, +0xF0, 0xA2, 0x00, 0x02, 0x18, 0xB5, 0x00, 0x75, 0x04, 0x4A, 0x85, 0xB4, 0x18, 0xB5, 0x02, 0x75, +0x06, 0x4A, 0x85, 0xF2, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x38, 0xB5, 0x06, 0xF5, 0x02, 0x48, +0x38, 0xB5, 0x04, 0xF5, 0x00, 0x85, 0xAE, 0x48, 0xA2, 0x0B, 0x0E, 0x22, 0x00, 0x00, 0xE1, 0x68, +0x85, 0xE6, 0x68, 0x85, 0xE8, 0xA5, 0xD4, 0x85, 0x2A, 0x22, 0xD8, 0x1F, 0xE0, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xD4, 0xE4, 0xD4, 0xE2, 0xD4, 0xE8, 0xD4, 0xE6, 0xA2, 0x0B, 0x0F, 0x22, 0x00, +0x00, 0xE1, 0x68, 0x85, 0xDE, 0x68, 0x85, 0xE0, 0xA5, 0xF0, 0x85, 0x2A, 0x22, 0xD8, 0x1F, 0xE0, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xD4, 0xE4, 0xD4, 0xE2, 0xD4, 0xE8, 0xD4, 0xE6, 0xA2, 0x0B, +0x0F, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0xE2, 0x68, 0x85, 0xE4, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0xA5, 0xAE, 0x4A, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0xAE, 0x48, 0xF4, 0x00, 0x00, 0xD4, 0xE0, +0xD4, 0xDE, 0xA2, 0x0B, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0xE6, 0x68, 0x18, 0x65, 0xF2, +0x85, 0xE8, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xD4, 0xAE, 0xF4, 0x00, 0x00, 0xD4, 0xE4, 0xD4, +0xE2, 0xA2, 0x0B, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0xEA, 0x68, 0x18, 0x65, 0xF2, 0x85, +0xEC, 0xA5, 0xD4, 0xC9, 0xB4, 0x00, 0x10, 0x06, 0x38, 0xE9, 0x5A, 0x00, 0x80, 0x06, 0x38, 0xA9, +0x0E, 0x01, 0xE5, 0xD4, 0x85, 0xDA, 0xA5, 0xF0, 0xC9, 0xB4, 0x00, 0x10, 0x06, 0x38, 0xE9, 0x5A, +0x00, 0x80, 0x06, 0x38, 0xA9, 0x0E, 0x01, 0xE5, 0xF0, 0x85, 0xDC, 0x64, 0xB2, 0xA9, 0xB4, 0x00, +0xC5, 0xD2, 0x30, 0x15, 0xD0, 0x0B, 0xA5, 0xD4, 0xC9, 0x5A, 0x00, 0xD0, 0x0C, 0xE6, 0xB2, 0x80, +0x08, 0xA5, 0xDA, 0x05, 0xDC, 0x30, 0x02, 0xE6, 0xB2, 0xA9, 0x01, 0x00, 0x85, 0xAE, 0xA2, 0x00, +0x02, 0x22, 0xBD, 0x84, 0xFE, 0xB5, 0x08, 0x4A, 0x85, 0x2A, 0x75, 0x00, 0x85, 0xD6, 0x38, 0xB5, +0x04, 0xE5, 0x2A, 0x85, 0xD8, 0x64, 0xB0, 0xA2, 0x00, 0x02, 0xA5, 0xEE, 0xF0, 0x65, 0xA2, 0x00, +0x02, 0x20, 0x73, 0x86, 0x38, 0xB5, 0x06, 0xE5, 0x30, 0x85, 0xF4, 0x18, 0xB5, 0x02, 0x65, 0x30, +0x85, 0xF2, 0xC5, 0xF4, 0x10, 0x4D, 0x38, 0xB5, 0x04, 0xE5, 0x2E, 0x85, 0xF0, 0x18, 0xB5, 0x00, +0x65, 0x2E, 0x85, 0xEE, 0xC5, 0xF0, 0x10, 0x3B, 0xE6, 0xB0, 0xA2, 0x32, 0x02, 0xA5, 0xF4, 0x95, +0x06, 0xA5, 0xF2, 0x95, 0x02, 0xA5, 0xF0, 0x95, 0x04, 0xA5, 0xEE, 0x95, 0x00, 0xA2, 0x00, 0x02, +0xA5, 0x30, 0x0A, 0x49, 0xFF, 0xFF, 0x1A, 0x18, 0x75, 0x0A, 0x85, 0xF4, 0xA5, 0x2E, 0x0A, 0x49, +0xFF, 0xFF, 0x1A, 0x18, 0x75, 0x08, 0xA2, 0x32, 0x02, 0x95, 0x08, 0xA5, 0xF4, 0x95, 0x0A, 0x22, +0xBD, 0x84, 0xFE, 0xA2, 0x00, 0x02, 0xB5, 0x00, 0x85, 0x40, 0x38, 0xE5, 0x14, 0x20, 0xE6, 0x23, +0x20, 0x0E, 0x24, 0x22, 0xCC, 0x1E, 0xE0, 0xA2, 0x00, 0x02, 0xB5, 0x10, 0x85, 0xF6, 0xB5, 0x0E, +0x85, 0xF8, 0xA5, 0x40, 0xC5, 0xD6, 0x30, 0x04, 0xC5, 0xD8, 0x30, 0x12, 0xA2, 0x00, 0x02, 0x22, +0x87, 0x85, 0xFE, 0xA5, 0xB0, 0xF0, 0x07, 0xA2, 0x32, 0x02, 0x22, 0x87, 0x85, 0xFE, 0xA5, 0xAE, +0xD0, 0x03, 0x82, 0x4B, 0x01, 0xA5, 0x40, 0xC5, 0xB4, 0xD0, 0x31, 0xA5, 0xDA, 0x49, 0xFF, 0xFF, +0x1A, 0x85, 0xDA, 0xA5, 0xDC, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0xDC, 0x64, 0xB2, 0xA9, 0xB4, 0x00, +0xC5, 0xD2, 0x30, 0x15, 0xD0, 0x0A, 0xA5, 0xD4, 0xC9, 0x0E, 0x01, 0xD0, 0x0C, 0x82, 0x71, 0x01, +0xA5, 0xDA, 0x05, 0xDC, 0x30, 0x03, 0x82, 0x68, 0x01, 0x20, 0x6C, 0x8A, 0xA5, 0xB2, 0xF0, 0x03, +0x82, 0x57, 0x01, 0xA5, 0x40, 0xC5, 0x00, 0x10, 0x03, 0x82, 0x4E, 0x01, 0xA2, 0x00, 0x02, 0xB5, +0x12, 0xA4, 0xDA, 0x10, 0x06, 0xC5, 0xE8, 0x10, 0x02, 0xA5, 0xE8, 0x85, 0xEE, 0xB5, 0x0E, 0xA4, +0xDC, 0x10, 0x08, 0xC5, 0xEC, 0x30, 0x04, 0xF0, 0x02, 0xA5, 0xEC, 0x85, 0xF0, 0xA5, 0xB0, 0xF0, +0x0D, 0xA2, 0x32, 0x02, 0xA5, 0x40, 0xD5, 0x00, 0x30, 0x04, 0xD5, 0x04, 0x30, 0x3E, 0xA2, 0x00, +0x02, 0xA5, 0xEE, 0xC5, 0xF0, 0x10, 0x0C, 0x85, 0xA8, 0xA5, 0xF0, 0x85, 0xAC, 0x20, 0x95, 0x8A, +0x82, 0x07, 0x01, 0xA5, 0xDA, 0x25, 0xDC, 0x10, 0x20, 0xA9, 0xB4, 0x00, 0xC5, 0xD2, 0x10, 0x19, +0xB5, 0x12, 0x85, 0xA8, 0xA5, 0xF0, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0xA2, 0x00, 0x02, 0xA5, 0xEE, +0x85, 0xA8, 0xB5, 0x0E, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0x82, 0xDE, 0x00, 0xA2, 0x32, 0x02, 0xB5, +0x12, 0xA4, 0xDC, 0x10, 0x08, 0xC5, 0xEC, 0x30, 0x04, 0xF0, 0x02, 0xA5, 0xEC, 0x85, 0xF2, 0xB5, +0x0E, 0xA4, 0xDA, 0x10, 0x06, 0xC5, 0xE8, 0x10, 0x02, 0xA5, 0xE8, 0x85, 0xF4, 0xA5, 0xEE, 0xC5, +0xF0, 0x10, 0x17, 0x85, 0xA8, 0xA5, 0xF2, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0xA5, 0xF4, 0x85, 0xA8, +0xA5, 0xF0, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0x82, 0xA0, 0x00, 0xA5, 0xDA, 0x25, 0xDC, 0x30, 0x03, +0x82, 0x97, 0x00, 0xA9, 0xB4, 0x00, 0xC5, 0xD2, 0x30, 0x03, 0x82, 0x8D, 0x00, 0xA5, 0xF2, 0xC5, +0xF0, 0xD0, 0x0D, 0xA5, 0xEE, 0x85, 0xA8, 0xA2, 0x32, 0x02, 0xB5, 0x12, 0x85, 0xAC, 0x80, 0x0E, +0xA5, 0xEE, 0xC5, 0xF4, 0xD0, 0x0B, 0xB5, 0x0E, 0x85, 0xA8, 0xA5, 0xF0, 0x85, 0xAC, 0x20, 0x95, +0x8A, 0xA2, 0x00, 0x02, 0xB5, 0x12, 0x85, 0xA8, 0xA5, 0xF2, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0xA2, +0x00, 0x02, 0xA5, 0xF4, 0x85, 0xA8, 0xB5, 0x0E, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0x82, 0x4A, 0x00, +0xA5, 0x40, 0xC5, 0x00, 0x10, 0x03, 0x82, 0x41, 0x00, 0xA5, 0xB0, 0xF0, 0x2F, 0xA2, 0x32, 0x02, +0xA5, 0x40, 0xD5, 0x00, 0x30, 0x26, 0xD5, 0x04, 0x10, 0x22, 0xA2, 0x00, 0x02, 0xB5, 0x0E, 0x48, +0xB5, 0x12, 0x85, 0xA8, 0xA2, 0x32, 0x02, 0xB5, 0x0E, 0x48, 0xB5, 0x12, 0x85, 0xAC, 0x20, 0x95, +0x8A, 0x68, 0x85, 0xA8, 0x68, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0x80, 0x0E, 0xA2, 0x00, 0x02, 0xB5, +0x12, 0x85, 0xA8, 0xB5, 0x0E, 0x85, 0xAC, 0x20, 0x95, 0x8A, 0xA5, 0x40, 0x1A, 0xC5, 0x04, 0x30, +0x02, 0xAB, 0x6B, 0x85, 0x40, 0xA5, 0xAE, 0xF0, 0x1A, 0x18, 0xA5, 0xDE, 0x65, 0xE6, 0x85, 0xE6, +0xA5, 0xE0, 0x65, 0xE8, 0x85, 0xE8, 0x18, 0xA5, 0xE2, 0x65, 0xEA, 0x85, 0xEA, 0xA5, 0xE4, 0x65, +0xEC, 0x85, 0xEC, 0x20, 0x41, 0x24, 0x82, 0x07, 0xFE, 0x10, 0x0B, 0x18, 0x69, 0x68, 0x01, 0x30, +0xFA, 0x60, 0x38, 0xE9, 0x68, 0x01, 0xC9, 0x68, 0x01, 0x10, 0xF7, 0x60, 0xA5, 0xDA, 0xA6, 0xDC, +0x86, 0xDA, 0x85, 0xDC, 0xA5, 0xE6, 0xA6, 0xEA, 0x86, 0xE6, 0x85, 0xEA, 0xA5, 0xE8, 0xA6, 0xEC, +0x86, 0xE8, 0x85, 0xEC, 0xA5, 0xDE, 0xA6, 0xE2, 0x86, 0xDE, 0x85, 0xE2, 0xA5, 0xE0, 0xA6, 0xE4, +0x86, 0xE0, 0x85, 0xE4, 0x60, 0xA5, 0xAC, 0xC5, 0x02, 0x30, 0x24, 0xC5, 0x06, 0x30, 0x04, 0xA5, +0x06, 0x85, 0xAC, 0xA5, 0xA8, 0xC5, 0x06, 0x10, 0x16, 0xC5, 0x02, 0x10, 0x04, 0xA5, 0x02, 0x85, +0xA8, 0xA5, 0xA8, 0xC5, 0xAC, 0x10, 0x08, 0x22, 0x70, 0x1E, 0xE0, 0x22, 0x00, 0x1E, 0xE0, 0x60, +0xA2, 0x00, 0x02, 0x22, 0xA4, 0x1F, 0xE0, 0xB5, 0x12, 0x85, 0xF6, 0xB5, 0x0E, 0x85, 0xF8, 0xB5, +0x08, 0x4A, 0x18, 0x75, 0x00, 0x85, 0xD6, 0x18, 0x75, 0x04, 0x38, 0xF5, 0x00, 0x38, 0xF5, 0x08, +0x85, 0xD8, 0xA2, 0xBC, 0x00, 0x20, 0x07, 0x46, 0x85, 0xC0, 0x86, 0xC2, 0xA0, 0x02, 0x00, 0xB7, +0xC0, 0x85, 0xC6, 0xA2, 0x00, 0x02, 0xB5, 0x00, 0x85, 0x40, 0xA5, 0xF6, 0x20, 0x5B, 0x8B, 0xA5, +0xF8, 0x20, 0x5B, 0x8B, 0xA5, 0x40, 0xC5, 0xD6, 0x30, 0x04, 0xC5, 0xD8, 0x30, 0x2B, 0xA2, 0x00, +0x02, 0x22, 0xA0, 0x1F, 0xE0, 0xB5, 0x12, 0xC5, 0xF6, 0xF0, 0x0C, 0x20, 0x5B, 0x8B, 0xA5, 0xF6, +0x20, 0x5B, 0x8B, 0xB5, 0x12, 0x85, 0xF6, 0xB5, 0x0E, 0xC5, 0xF8, 0xF0, 0x0C, 0x20, 0x5B, 0x8B, +0xA5, 0xF8, 0x20, 0x5B, 0x8B, 0xB5, 0x0E, 0x85, 0xF8, 0xA5, 0x40, 0x1A, 0x85, 0x40, 0xD5, 0x04, +0x30, 0xC2, 0xA5, 0xF6, 0x20, 0x5B, 0x8B, 0xA5, 0xF8, 0x20, 0x5B, 0x8B, 0xA0, 0x02, 0x00, 0xA5, +0xC6, 0x97, 0xC0, 0xA2, 0xBC, 0x00, 0x20, 0x22, 0x46, 0x18, 0x6B, 0xAA, 0x18, 0xA5, 0xC6, 0xA8, +0x69, 0x04, 0x00, 0x85, 0xC6, 0xC7, 0xC0, 0x90, 0x18, 0xF0, 0x16, 0xDA, 0x5A, 0x18, 0x69, 0x00, +0x04, 0xB0, 0x1D, 0xA2, 0xBC, 0x00, 0x20, 0x35, 0x46, 0xB0, 0x18, 0x85, 0xC0, 0x86, 0xC2, 0x7A, +0xFA, 0xA5, 0x40, 0x97, 0xC0, 0xC8, 0xC8, 0x8A, 0x97, 0xC0, 0xC8, 0xC8, 0xA2, 0x00, 0x02, 0x60, +0xA9, 0x33, 0x04, 0x7A, 0xFA, 0xFA, 0x48, 0xA2, 0xBC, 0x00, 0x20, 0x22, 0x46, 0x38, 0x68, 0x6B, +0xA2, 0x00, 0x00, 0x80, 0x0D, 0xA2, 0x01, 0x00, 0x80, 0x08, 0xA2, 0x02, 0x00, 0x80, 0x03, 0xA2, +0x03, 0x00, 0x20, 0xB3, 0x0D, 0xA3, 0x09, 0x85, 0x50, 0xA3, 0x0B, 0x85, 0x52, 0x22, 0xDF, 0x8B, +0xFE, 0xAA, 0x4C, 0x6E, 0xFF, 0x20, 0xB3, 0x0D, 0x22, 0x40, 0x1E, 0xE0, 0xA3, 0x0D, 0x85, 0x50, +0xA3, 0x0F, 0x85, 0x52, 0xA2, 0x04, 0x00, 0x22, 0xDF, 0x8B, 0xFE, 0xAA, 0x4C, 0x84, 0xFF, 0x86, +0x38, 0x20, 0xC5, 0x0D, 0xB0, 0x04, 0x5C, 0x1C, 0x1E, 0xE0, 0x8B, 0xA0, 0x18, 0x00, 0xB7, 0x2A, +0x48, 0xC8, 0xB7, 0x2A, 0x83, 0x02, 0x6B, 0xA9, 0x70, 0x00, 0x22, 0xF8, 0x1E, 0xE0, 0x90, 0x01, +0x6B, 0xA5, 0x38, 0xF0, 0x0E, 0x3A, 0x0A, 0xAA, 0x7C, 0x0B, 0x8C, 0x22, 0x8C, 0x38, 0x8C, 0x4E, +0x8C, 0x64, 0x8C, 0x20, 0xC0, 0x23, 0xA5, 0x50, 0xA6, 0x52, 0x20, 0x16, 0x8D, 0xA9, 0x00, 0x00, +0x18, 0x6B, 0x20, 0xC0, 0x23, 0x20, 0x8E, 0x8C, 0x20, 0xB0, 0x8C, 0xB0, 0x09, 0x22, 0x1C, 0x1F, +0xE0, 0x48, 0x20, 0x0A, 0x8D, 0x68, 0x80, 0x3F, 0x20, 0xC0, 0x23, 0x20, 0x8E, 0x8C, 0x20, 0xB0, +0x8C, 0xB0, 0x09, 0x22, 0x20, 0x1F, 0xE0, 0x48, 0x20, 0x0A, 0x8D, 0x68, 0x80, 0x29, 0x20, 0xC0, +0x23, 0x20, 0x8E, 0x8C, 0x20, 0xB0, 0x8C, 0xB0, 0x09, 0x22, 0x24, 0x1F, 0xE0, 0x48, 0x20, 0x0A, +0x8D, 0x68, 0x80, 0x13, 0x20, 0x8E, 0x8C, 0x20, 0xB0, 0x8C, 0xB0, 0x09, 0x22, 0x28, 0x1F, 0xE0, +0x48, 0x20, 0x0A, 0x8D, 0x68, 0x80, 0x00, 0xAA, 0xA0, 0x72, 0x00, 0x68, 0x97, 0x24, 0xA0, 0x94, +0x00, 0x68, 0x97, 0x24, 0xC8, 0xC8, 0x68, 0x97, 0x24, 0x8A, 0xC9, 0x01, 0x00, 0x6B, 0xFA, 0xA0, +0x96, 0x00, 0xB7, 0x24, 0x48, 0x88, 0x88, 0xB7, 0x24, 0x48, 0xA9, 0x00, 0x00, 0x97, 0x24, 0xC8, +0xC8, 0x97, 0x24, 0xA0, 0x72, 0x00, 0xB7, 0x24, 0x48, 0xA9, 0x00, 0x00, 0x97, 0x24, 0xDA, 0x60, +0xD4, 0x52, 0xD4, 0x50, 0xA2, 0x04, 0x6D, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x03, 0xFA, 0xFA, 0x60, +0x68, 0xFA, 0x20, 0x16, 0x8D, 0xB0, 0x23, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x04, 0x67, +0x22, 0x00, 0x00, 0xE1, 0xB0, 0x14, 0xA3, 0x03, 0x48, 0xA3, 0x03, 0x48, 0xA2, 0x04, 0x6E, 0x22, +0x00, 0x00, 0xE1, 0xFA, 0x86, 0x70, 0xFA, 0x86, 0x72, 0x60, 0x48, 0xA0, 0x96, 0x00, 0xB7, 0x24, +0x48, 0xA9, 0x00, 0x00, 0x97, 0x24, 0x88, 0x88, 0xB7, 0x24, 0x48, 0xA9, 0x00, 0x00, 0x97, 0x24, +0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x38, 0x60, 0xD4, 0x72, 0xD4, 0x70, 0xA2, 0x04, +0x68, 0x22, 0x00, 0x00, 0xE1, 0x60, 0xDA, 0x48, 0x48, 0x48, 0x0B, 0x3B, 0x5B, 0xA0, 0x04, 0x00, +0xB7, 0x07, 0x09, 0x00, 0x80, 0x97, 0x07, 0xA7, 0x07, 0x85, 0x03, 0x88, 0x88, 0xB7, 0x07, 0x85, +0x05, 0xA9, 0x0A, 0x00, 0xC7, 0x03, 0xB0, 0x55, 0xA8, 0xB7, 0x03, 0xAA, 0xC8, 0xC8, 0xB7, 0x03, +0xC8, 0xC8, 0x5A, 0x48, 0xDA, 0xA2, 0x04, 0x3A, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xC7, 0x03, 0xB0, +0x2A, 0xA8, 0xB7, 0x03, 0xAA, 0xC8, 0xC8, 0xB7, 0x03, 0xC8, 0xC8, 0x5A, 0x48, 0xDA, 0xA2, 0x04, +0x3C, 0x22, 0x00, 0x00, 0xE1, 0x90, 0xE5, 0x7A, 0x48, 0xA0, 0x04, 0x00, 0xB7, 0x07, 0x29, 0xFF, +0x7F, 0x97, 0x07, 0x68, 0x2B, 0xFA, 0xFA, 0xFA, 0xFA, 0x38, 0x60, 0xA0, 0x0C, 0x00, 0xB7, 0x03, +0x48, 0x88, 0x88, 0xB7, 0x03, 0x48, 0xA2, 0x04, 0x3C, 0x22, 0x00, 0x00, 0xE1, 0xA0, 0x04, 0x00, +0xB7, 0x07, 0x29, 0xFF, 0x7F, 0x97, 0x07, 0x2B, 0x68, 0x68, 0x68, 0xFA, 0x60, 0x20, 0xB3, 0x0D, +0xA0, 0x98, 0x00, 0xB7, 0x24, 0xC8, 0xC8, 0x17, 0x24, 0xF0, 0x06, 0xA2, 0x40, 0x04, 0x4C, 0x42, +0xFF, 0xA9, 0x00, 0x01, 0xA6, 0x0A, 0xA0, 0x00, 0x00, 0x20, 0x24, 0x11, 0x90, 0x04, 0xAA, 0x4C, +0x42, 0xFF, 0x86, 0x50, 0x84, 0x52, 0xA0, 0x98, 0x00, 0x8A, 0x97, 0x24, 0xC8, 0xC8, 0xA5, 0x52, +0x97, 0x24, 0x20, 0xA7, 0x45, 0xA9, 0x0A, 0x00, 0x87, 0x54, 0xA0, 0x02, 0x00, 0xA9, 0x00, 0x00, +0x97, 0x54, 0xC8, 0xC8, 0xC0, 0x0A, 0x00, 0x90, 0xF7, 0xA5, 0x50, 0x83, 0x09, 0xA5, 0x52, 0x83, +0x0B, 0x20, 0xB2, 0x45, 0xA2, 0x04, 0x27, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0x3F, 0xFF, 0x20, 0xB3, +0x0D, 0xA0, 0x98, 0x00, 0xB7, 0x24, 0x85, 0x50, 0xA9, 0x00, 0x00, 0x97, 0x24, 0xC8, 0xC8, 0xB7, +0x24, 0x85, 0x52, 0xA9, 0x00, 0x00, 0x97, 0x24, 0xA5, 0x50, 0x05, 0x52, 0xD0, 0x06, 0xA2, 0x41, +0x04, 0x4C, 0x42, 0xFF, 0x20, 0xA7, 0x45, 0xA7, 0x54, 0xF4, 0x00, 0x00, 0x48, 0xD4, 0x52, 0xD4, +0x50, 0x20, 0xB2, 0x45, 0xA2, 0x02, 0x19, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x04, 0xAA, 0x4C, 0x42, +0xFF, 0x20, 0xA7, 0x45, 0xA7, 0x54, 0xC9, 0x0A, 0x00, 0xF0, 0x52, 0xA0, 0x0A, 0x00, 0xB7, 0x54, +0x85, 0xA6, 0x85, 0xAA, 0xC8, 0xC8, 0xB7, 0x54, 0x85, 0xA8, 0x85, 0xAC, 0xA0, 0x0E, 0x00, 0xB7, +0x54, 0xC5, 0xA6, 0x10, 0x02, 0x85, 0xA6, 0xC5, 0xAA, 0x30, 0x02, 0x85, 0xAA, 0xC8, 0xC8, 0xB7, +0x54, 0xC5, 0xA8, 0x10, 0x02, 0x85, 0xA8, 0xC5, 0xAC, 0x30, 0x02, 0x85, 0xAC, 0xC8, 0xC8, 0x98, +0xC7, 0x54, 0x90, 0xDB, 0xA0, 0x02, 0x00, 0xA5, 0xA6, 0x97, 0x54, 0xA5, 0xA8, 0xC8, 0xC8, 0x97, +0x54, 0xA5, 0xAA, 0xC8, 0xC8, 0x97, 0x54, 0xA5, 0xAC, 0xC8, 0xC8, 0x97, 0x54, 0x20, 0xB2, 0x45, +0xA2, 0x04, 0x28, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0x3F, 0xFF, 0xA3, 0x07, 0xAA, 0xA3, 0x09, 0x48, +0xDA, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xAA, 0x4C, 0xC7, 0xFF, 0x20, 0xB3, 0x0D, 0xA3, +0x0D, 0x85, 0x50, 0xA3, 0x0F, 0x85, 0x52, 0x20, 0xA7, 0x45, 0xA0, 0x02, 0x00, 0xB7, 0x54, 0x18, +0x63, 0x09, 0x97, 0x54, 0xC8, 0xC8, 0xB7, 0x54, 0x18, 0x63, 0x0B, 0x97, 0x54, 0xC8, 0xC8, 0x98, +0xC7, 0x54, 0x90, 0xE9, 0x20, 0xB2, 0x45, 0x4C, 0x81, 0xFF, 0x20, 0xB3, 0x0D, 0x20, 0x4C, 0x63, +0x22, 0xC8, 0x1F, 0xE0, 0xA3, 0x11, 0x85, 0x60, 0xA3, 0x13, 0x85, 0x62, 0x20, 0xB8, 0x45, 0xF4, +0x02, 0x00, 0xA3, 0x01, 0xC7, 0x64, 0xB0, 0x0E, 0xA8, 0x20, 0x77, 0x64, 0xA3, 0x01, 0x18, 0x69, +0x04, 0x00, 0x83, 0x01, 0x80, 0xEC, 0x68, 0x20, 0xC3, 0x45, 0x4C, 0x55, 0xFF, 0xA0, 0x98, 0x00, +0xB7, 0x24, 0x85, 0x50, 0xC8, 0xC8, 0xB7, 0x24, 0x85, 0x52, 0x05, 0x50, 0xD0, 0x05, 0x18, 0xA9, +0x00, 0x00, 0x6B, 0x20, 0xA7, 0x45, 0xA5, 0xAC, 0x38, 0xE5, 0xA8, 0x10, 0x04, 0x49, 0xFF, 0xFF, +0x1A, 0x85, 0x2A, 0xA5, 0xAA, 0x38, 0xE5, 0xA6, 0xF0, 0x52, 0x10, 0x04, 0x49, 0xFF, 0xFF, 0x1A, +0xC5, 0x2A, 0x90, 0x02, 0xA5, 0x2A, 0x1A, 0xA0, 0x02, 0x00, 0x18, 0x77, 0x54, 0x97, 0x54, 0xA7, +0x54, 0xC9, 0x0A, 0x00, 0xF0, 0x36, 0xA0, 0x0C, 0x00, 0xB7, 0x54, 0x38, 0xE5, 0xAC, 0x10, 0x04, +0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x2A, 0x88, 0x88, 0xB7, 0x54, 0x38, 0xE5, 0xAA, 0x10, 0x04, 0x49, +0xFF, 0xFF, 0x1A, 0xC5, 0x2A, 0x90, 0x02, 0xA5, 0x2A, 0x1A, 0xA0, 0x02, 0x00, 0x18, 0x77, 0x54, +0xC9, 0xF8, 0x1F, 0x90, 0x07, 0x20, 0xB2, 0x45, 0xA9, 0x42, 0x04, 0x6B, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0xD4, 0x52, 0xD4, 0x50, 0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x04, 0xFA, +0xFA, 0x80, 0x56, 0x68, 0xFA, 0x38, 0xE9, 0x04, 0x00, 0xC7, 0x54, 0x90, 0x2F, 0xF0, 0x2D, 0xA7, +0x54, 0xC9, 0x0A, 0x00, 0xD0, 0x0E, 0xA8, 0xA5, 0xA6, 0x97, 0x54, 0xC8, 0xC8, 0xA5, 0xA8, 0x97, +0x54, 0xC8, 0xC8, 0x98, 0xA8, 0xA5, 0xAA, 0x97, 0x54, 0xC8, 0xC8, 0xA5, 0xAC, 0x97, 0x54, 0xC8, +0xC8, 0x98, 0x87, 0x54, 0x20, 0xB2, 0x45, 0x18, 0xA9, 0x00, 0x00, 0x6B, 0x18, 0x69, 0x04, 0x01, +0xF4, 0x00, 0x00, 0x48, 0xD4, 0x52, 0xD4, 0x50, 0x20, 0xB2, 0x45, 0xA2, 0x02, 0x19, 0x22, 0x00, +0x00, 0xE1, 0xB0, 0x05, 0x20, 0xA7, 0x45, 0x80, 0xB6, 0x6B, 0x2D, 0x00, 0x00, 0x00, 0xBD, 0x90, +0xFE, 0x00, 0x14, 0x91, 0xFE, 0x00, 0x14, 0x91, 0xFE, 0x00, 0x32, 0x91, 0xFE, 0x00, 0x17, 0x91, +0xFE, 0x00, 0x3A, 0x91, 0xFE, 0x00, 0x14, 0x91, 0xFE, 0x00, 0x14, 0x91, 0xFE, 0x00, 0x5C, 0x91, +0xFE, 0x00, 0x80, 0x91, 0xFE, 0x00, 0xA2, 0x91, 0xFE, 0x00, 0xBA, 0x91, 0xFE, 0x00, 0xD6, 0x91, +0xFE, 0x00, 0x88, 0x93, 0xFE, 0x00, 0x47, 0x95, 0xFE, 0x00, 0x7B, 0x96, 0xFE, 0x00, 0xA3, 0x96, +0xFE, 0x00, 0xC8, 0x96, 0xFE, 0x00, 0xA8, 0x97, 0xFE, 0x00, 0x65, 0x98, 0xFE, 0x00, 0xF9, 0x98, +0xFE, 0x00, 0x08, 0x99, 0xFE, 0x00, 0x63, 0x99, 0xFE, 0x00, 0x57, 0x9B, 0xFE, 0x00, 0xA1, 0x99, +0xFE, 0x00, 0x46, 0x9B, 0xFE, 0x00, 0x35, 0x9B, 0xFE, 0x00, 0xB7, 0x99, 0xFE, 0x00, 0x74, 0x9A, +0xFE, 0x00, 0x22, 0x9A, 0xFE, 0x00, 0x54, 0x9A, 0xFE, 0x00, 0x51, 0x9D, 0xFE, 0x00, 0x59, 0x9E, +0xFE, 0x00, 0x08, 0x9F, 0xFE, 0x00, 0x81, 0x9F, 0xFE, 0x00, 0xC4, 0xA0, 0xFE, 0x00, 0xB2, 0xA0, +0xFE, 0x00, 0xEF, 0xA0, 0xFE, 0x00, 0x57, 0xA3, 0xFE, 0x00, 0xBB, 0xA4, 0xFE, 0x00, 0xB7, 0xA6, +0xFE, 0x00, 0xF6, 0xA6, 0xFE, 0x00, 0x12, 0xA7, 0xFE, 0x00, 0x2E, 0xA7, 0xFE, 0x00, 0x8B, 0xA9, +0x00, 0x00, 0x8F, 0xD8, 0x00, 0xE1, 0x8F, 0xDA, 0x00, 0xE1, 0x8F, 0xDC, 0x00, 0xE1, 0x8F, 0xDE, +0x00, 0xE1, 0xE2, 0x20, 0x8F, 0xD4, 0x0F, 0xE1, 0x3A, 0x8F, 0xCF, 0x00, 0xE1, 0x8F, 0xE0, 0x00, +0xE1, 0xC2, 0x20, 0xA9, 0x02, 0x00, 0xA2, 0x01, 0x41, 0xA0, 0x08, 0x00, 0x20, 0x24, 0x11, 0x90, +0x10, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x25, 0x00, 0xA2, 0x03, 0x15, 0x22, 0x00, 0x00, +0xE1, 0x8A, 0x8F, 0xD0, 0x0F, 0xE1, 0x98, 0x8F, 0xD2, 0x0F, 0xE1, 0x20, 0x43, 0x91, 0xA9, 0x01, +0x41, 0x9D, 0x00, 0x00, 0xAB, 0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x00, 0x8F, 0xD8, 0x00, 0xE1, 0x8F, +0xDA, 0x00, 0xE1, 0xE2, 0x20, 0x3A, 0x8F, 0xCF, 0x00, 0xE1, 0x8F, 0xE0, 0x00, 0xE1, 0xC2, 0x20, +0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xA9, 0xFF, 0xFF, 0x83, 0x07, +0x4C, 0x8B, 0xFF, 0xAF, 0xD0, 0x0F, 0xE1, 0xAA, 0xAF, 0xD2, 0x0F, 0xE1, 0xEB, 0x48, 0xAB, 0xAB, +0xBD, 0x00, 0x00, 0xBC, 0x02, 0x00, 0xAA, 0x98, 0xEB, 0x48, 0xAB, 0xAB, 0x60, 0x0B, 0x3B, 0x5B, +0xE2, 0x30, 0xA0, 0x00, 0xA2, 0x00, 0xB7, 0x09, 0x9F, 0xC0, 0x02, 0xE1, 0xCA, 0x88, 0xD0, 0xF6, +0xE2, 0x30, 0x22, 0x80, 0x00, 0xE1, 0xC2, 0x30, 0x4C, 0xC3, 0xFF, 0xA2, 0x07, 0x03, 0x4C, 0xC6, +0xFF, 0x0B, 0x3B, 0x5B, 0xE2, 0x30, 0x22, 0x84, 0x00, 0xE1, 0xA2, 0x00, 0xA0, 0x00, 0xC2, 0x30, +0xB0, 0xE9, 0xE2, 0x30, 0xBF, 0xC0, 0x02, 0xE1, 0x97, 0x09, 0xCA, 0x88, 0xD0, 0xF6, 0xC2, 0x30, +0x4C, 0xC3, 0xFF, 0xE2, 0x30, 0x22, 0x84, 0x00, 0xE1, 0xA3, 0x07, 0xAA, 0xA3, 0x09, 0x9F, 0xC0, +0x02, 0xE1, 0x22, 0x80, 0x00, 0xE1, 0xC2, 0x30, 0x4C, 0xC2, 0xFF, 0xE2, 0x30, 0x22, 0x84, 0x00, +0xE1, 0xA3, 0x07, 0xAA, 0xBF, 0xC0, 0x02, 0xE1, 0x83, 0x09, 0xC2, 0x30, 0xB0, 0x03, 0x4C, 0xB7, +0xFF, 0xA2, 0x33, 0x01, 0x4C, 0xBC, 0xFF, 0xE2, 0x30, 0x22, 0x8C, 0x00, 0xE1, 0xC2, 0x30, 0x90, +0x06, 0xA2, 0x07, 0x03, 0x4C, 0x90, 0xFF, 0x08, 0x78, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0x0B, +0x3B, 0x5B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAD, 0xE3, +0x03, 0x48, 0xAD, 0xE1, 0x03, 0x48, 0xF4, 0x01, 0x00, 0xF4, 0x80, 0x51, 0x22, 0x7F, 0x93, 0xFE, +0x68, 0x8D, 0xE9, 0x03, 0x8D, 0xF1, 0x03, 0x68, 0x8D, 0xEB, 0x03, 0x8D, 0xF3, 0x03, 0x68, 0x8D, +0xED, 0x03, 0x68, 0x8D, 0xEF, 0x03, 0x0E, 0xF1, 0x03, 0x2E, 0xF3, 0x03, 0x0E, 0xF1, 0x03, 0x2E, +0xF3, 0x03, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAD, 0xF3, +0x03, 0x48, 0xAD, 0xF1, 0x03, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0xB5, 0x05, 0x22, 0x7F, 0x93, 0xFE, +0x18, 0x68, 0x8D, 0xF1, 0x03, 0x69, 0x04, 0x00, 0xE2, 0x20, 0x85, 0x0E, 0xC2, 0x20, 0x18, 0xAD, +0xF1, 0x03, 0x69, 0x70, 0x07, 0x8D, 0xF1, 0x03, 0x68, 0x8D, 0xF3, 0x03, 0xA9, 0x3B, 0x00, 0x8D, +0xF5, 0x03, 0x9C, 0xF7, 0x03, 0xA9, 0x03, 0x00, 0x2D, 0xF1, 0x03, 0xD0, 0x03, 0xEE, 0xF5, 0x03, +0x68, 0x8D, 0xF1, 0x03, 0x68, 0x8D, 0xF3, 0x03, 0x4E, 0xF3, 0x03, 0x6E, 0xF1, 0x03, 0x4E, 0xF3, +0x03, 0x6E, 0xF1, 0x03, 0xA9, 0x01, 0x00, 0x8D, 0xF9, 0x03, 0xAD, 0xF1, 0x03, 0xCD, 0xF5, 0x03, +0x90, 0x19, 0xEE, 0xF9, 0x03, 0xEE, 0xF9, 0x03, 0x38, 0xAD, 0xF1, 0x03, 0xED, 0xF5, 0x03, 0x8D, +0xF1, 0x03, 0xAD, 0xF3, 0x03, 0xED, 0xF7, 0x03, 0x8D, 0xF3, 0x03, 0xA0, 0x07, 0x00, 0x0E, 0xF1, +0x03, 0x2E, 0xF3, 0x03, 0x88, 0xD0, 0xF7, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x18, 0xA9, 0x47, +0x00, 0x6D, 0xF1, 0x03, 0x8D, 0xF1, 0x03, 0x48, 0xA9, 0x00, 0x00, 0x6D, 0xF3, 0x03, 0x8D, 0xF3, +0x03, 0xF4, 0x4F, 0x0F, 0x22, 0x84, 0x93, 0xFE, 0x18, 0x68, 0x6D, 0xF9, 0x03, 0x8D, 0xF3, 0x03, +0xE2, 0x20, 0x3A, 0x85, 0x10, 0xC2, 0x20, 0x68, 0xA0, 0x07, 0x00, 0x4A, 0x88, 0xD0, 0xFC, 0xE2, +0x20, 0x85, 0x0F, 0xC2, 0x20, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0xAD, 0xEF, 0x03, 0x48, 0xAD, 0xED, 0x03, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x10, 0x0E, 0x22, +0x7F, 0x93, 0xFE, 0x68, 0xFA, 0xE2, 0x20, 0x85, 0x0D, 0xC2, 0x20, 0x68, 0xFA, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0x48, 0xF4, 0x3C, 0x00, 0x22, 0x84, 0x93, 0xFE, 0x68, 0xE2, 0x20, 0x85, 0x0C, +0x68, 0x85, 0x0B, 0x68, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0x18, 0xA9, 0x05, 0x00, 0x6F, 0xE9, 0x03, 0xE1, 0xAA, 0xA9, 0x00, 0x00, 0x6F, 0xEB, +0x03, 0xE1, 0x48, 0xDA, 0xF4, 0x00, 0x00, 0xF4, 0x07, 0x00, 0x22, 0x7F, 0x93, 0xFE, 0x68, 0x68, +0x68, 0x1A, 0xFA, 0xE2, 0x20, 0x85, 0x12, 0xC2, 0x20, 0x2B, 0xAB, 0x28, 0x4C, 0x8B, 0xFF, 0x22, +0xB1, 0xC8, 0xFE, 0x6B, 0x22, 0x07, 0xC8, 0xFE, 0x6B, 0x08, 0x78, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, +0xAB, 0x0B, 0x3B, 0x5B, 0xE2, 0x30, 0x8B, 0x4B, 0xAB, 0xA4, 0x10, 0xA5, 0x0E, 0x29, 0x03, 0xD0, +0x06, 0xC0, 0x01, 0xD0, 0x02, 0xA0, 0x0C, 0xA5, 0x0F, 0xD9, 0x3B, 0x95, 0xC2, 0x30, 0x90, 0x0A, +0xAB, 0x2B, 0xAB, 0x28, 0xA2, 0x01, 0x03, 0x4C, 0xD2, 0xFF, 0xAB, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA5, 0x0D, 0x29, 0xFF, 0x00, 0x48, 0xF4, 0x3C, 0x00, +0x22, 0x36, 0x95, 0xFE, 0x18, 0xA5, 0x0C, 0x29, 0xFF, 0x00, 0x63, 0x01, 0x83, 0x01, 0xA9, 0x00, +0x00, 0x63, 0x03, 0x83, 0x03, 0x68, 0xFA, 0x48, 0xF4, 0x3C, 0x00, 0x22, 0x36, 0x95, 0xFE, 0x18, +0xA5, 0x0B, 0x29, 0xFF, 0x00, 0x63, 0x01, 0x83, 0x01, 0xA9, 0x00, 0x00, 0x63, 0x03, 0x83, 0x03, +0x68, 0x8D, 0xE9, 0x03, 0x68, 0x8D, 0xEB, 0x03, 0xA5, 0x0F, 0x29, 0xFF, 0x00, 0x8D, 0xED, 0x03, +0x9C, 0xEF, 0x03, 0xA5, 0x10, 0x29, 0xFF, 0x00, 0x1A, 0x8D, 0xF1, 0x03, 0x9C, 0xF3, 0x03, 0xA5, +0x0E, 0x29, 0xFF, 0x00, 0x18, 0x69, 0x6C, 0x07, 0x8D, 0xF5, 0x03, 0x8D, 0xF9, 0x03, 0x9C, 0xF7, +0x03, 0x9C, 0xFB, 0x03, 0x38, 0xAD, 0xF5, 0x03, 0xE9, 0x70, 0x07, 0x8D, 0xF5, 0x03, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0x48, 0xF4, 0xB5, 0x05, 0x22, 0x36, 0x95, 0xFE, 0x18, 0xA9, 0x03, 0x00, +0x63, 0x01, 0x83, 0x01, 0xA9, 0x00, 0x00, 0x63, 0x03, 0x4A, 0x83, 0x03, 0xA3, 0x01, 0x6A, 0x83, +0x01, 0xA3, 0x03, 0x4A, 0x83, 0x03, 0x8D, 0xF7, 0x03, 0xA3, 0x01, 0x6A, 0x83, 0x01, 0x8D, 0xF5, +0x03, 0x68, 0x18, 0x6D, 0xED, 0x03, 0x8D, 0xED, 0x03, 0x68, 0x6D, 0xEF, 0x03, 0x8D, 0xEF, 0x03, +0xCE, 0xF1, 0x03, 0xAD, 0xF1, 0x03, 0xC9, 0x02, 0x00, 0x90, 0x21, 0xCE, 0xF1, 0x03, 0xCE, 0xF1, +0x03, 0xA9, 0x3B, 0x00, 0x8D, 0xF5, 0x03, 0xAD, 0xF9, 0x03, 0x29, 0x03, 0x00, 0xD0, 0x03, 0xEE, +0xF5, 0x03, 0x18, 0xAD, 0xF5, 0x03, 0x6D, 0xED, 0x03, 0x8D, 0xED, 0x03, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0xAD, 0xF1, 0x03, 0x48, 0xA9, 0x4D, 0x0F, 0x48, 0x22, 0x36, 0x95, 0xFE, 0x18, 0xA9, +0x34, 0x00, 0x63, 0x01, 0x83, 0x01, 0xA9, 0x00, 0x00, 0x63, 0x03, 0x83, 0x03, 0x68, 0x8D, 0xF1, +0x03, 0x68, 0x8D, 0xF3, 0x03, 0xA0, 0x07, 0x00, 0x4E, 0xF3, 0x03, 0x6E, 0xF1, 0x03, 0x88, 0xD0, +0xF7, 0x18, 0xAD, 0xED, 0x03, 0x6D, 0xF1, 0x03, 0x8D, 0xED, 0x03, 0xAD, 0xEF, 0x03, 0x6D, 0xF3, +0x03, 0x8D, 0xEF, 0x03, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0xC0, 0xA8, 0xAD, 0xED, 0x03, +0x48, 0x22, 0x36, 0x95, 0xFE, 0xA3, 0x01, 0x0A, 0x83, 0x01, 0xA3, 0x03, 0x2A, 0x83, 0x03, 0x18, +0x68, 0x6D, 0xE9, 0x03, 0x8D, 0xE5, 0x03, 0x68, 0x6D, 0xEB, 0x03, 0x8D, 0xE7, 0x03, 0xE2, 0x30, +0x22, 0x88, 0x00, 0xE1, 0xC2, 0x30, 0x2B, 0xAB, 0x2A, 0x28, 0x6A, 0xB0, 0x03, 0x4C, 0xCD, 0xFF, +0xA2, 0x07, 0x03, 0x4C, 0xD2, 0xFF, 0x22, 0xE9, 0xC7, 0xFE, 0x6B, 0x1F, 0x1C, 0x1F, 0x1E, 0x1F, +0x1E, 0x1F, 0x1F, 0x1E, 0x1F, 0x1E, 0x1F, 0x1D, 0x8B, 0x0B, 0x3B, 0x5B, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x22, 0x4C, 0x96, 0xFE, 0x90, 0x03, 0x4C, 0x40, +0x96, 0xA6, 0x0A, 0xE2, 0x20, 0xA5, 0x0C, 0x48, 0xAB, 0x0B, 0x3B, 0x5B, 0xA9, 0xA0, 0x9D, 0x08, +0x00, 0x9D, 0x11, 0x00, 0xAF, 0xF5, 0x02, 0xE1, 0xC2, 0x20, 0x08, 0xA0, 0xA0, 0xA0, 0xA5, 0x05, +0x28, 0xD0, 0x21, 0xA0, 0xC1, 0xCD, 0x29, 0xFF, 0x00, 0xC9, 0x0C, 0x00, 0x90, 0x03, 0xA0, 0xD0, +0xCD, 0xC9, 0x0D, 0x00, 0x90, 0x06, 0x38, 0xE9, 0x0C, 0x00, 0x80, 0x08, 0xC9, 0x00, 0x00, 0xD0, +0x03, 0xA9, 0x0C, 0x00, 0x20, 0x51, 0x96, 0x9D, 0x09, 0x00, 0x98, 0x9D, 0x12, 0x00, 0xA5, 0x04, +0x20, 0x51, 0x96, 0x9D, 0x0C, 0x00, 0xA5, 0x03, 0x20, 0x51, 0x96, 0x9D, 0x0F, 0x00, 0xA5, 0x08, +0x1A, 0x20, 0x51, 0x96, 0x9D, 0x00, 0x00, 0xA5, 0x07, 0x1A, 0x20, 0x51, 0x96, 0x9D, 0x03, 0x00, +0xA5, 0x06, 0x20, 0x51, 0x96, 0x9D, 0x06, 0x00, 0xE2, 0x20, 0xA9, 0xBA, 0x9D, 0x0B, 0x00, 0x9D, +0x0E, 0x00, 0xA9, 0xAF, 0x9D, 0x02, 0x00, 0x9D, 0x05, 0x00, 0xA0, 0xA0, 0x00, 0xBD, 0x09, 0x00, +0xC9, 0xB0, 0xD0, 0x04, 0x98, 0x9D, 0x09, 0x00, 0xBD, 0x00, 0x00, 0xC9, 0xB0, 0xD0, 0x04, 0x98, +0x9D, 0x00, 0x00, 0xBD, 0x03, 0x00, 0xC9, 0xB0, 0xD0, 0x04, 0x98, 0x9D, 0x03, 0x00, 0xAF, 0xF4, +0x02, 0xE1, 0xC2, 0x20, 0xF0, 0x20, 0x29, 0xFF, 0x00, 0x48, 0xBD, 0x03, 0x00, 0xA8, 0xBD, 0x00, +0x00, 0x9D, 0x03, 0x00, 0x98, 0x9D, 0x00, 0x00, 0x68, 0x3A, 0xF0, 0x0A, 0xBD, 0x06, 0x00, 0x9D, +0x00, 0x00, 0x98, 0x9D, 0x06, 0x00, 0x2B, 0x68, 0x68, 0x68, 0x68, 0x2B, 0xAB, 0x4C, 0xC2, 0xFF, +0x68, 0x68, 0x68, 0x68, 0x2B, 0xAB, 0xA2, 0x07, 0x03, 0x4C, 0xC7, 0xFF, 0x22, 0xD7, 0x91, 0xFE, +0x6B, 0x48, 0xDA, 0x5A, 0x0B, 0x3B, 0x5B, 0xE2, 0x30, 0xA0, 0x02, 0xA2, 0x09, 0xA9, 0x00, 0x18, +0x2A, 0xC9, 0x0A, 0x90, 0x02, 0xE9, 0x0A, 0x26, 0x07, 0xCA, 0xD0, 0xF4, 0x09, 0xB0, 0x48, 0x88, +0xD0, 0xE9, 0xC2, 0x30, 0x68, 0x85, 0x07, 0x2B, 0x7A, 0xFA, 0x68, 0x60, 0xA3, 0x0B, 0x29, 0xFF, +0x00, 0xC9, 0x2D, 0x00, 0xB0, 0x18, 0x0A, 0x0A, 0xAA, 0xA3, 0x06, 0x29, 0x00, 0xFF, 0x09, 0x5C, +0x00, 0x9F, 0x00, 0x00, 0xE1, 0xA3, 0x08, 0x9F, 0x02, 0x00, 0xE1, 0x4C, 0xCD, 0xFF, 0xA2, 0x01, +0x03, 0x4C, 0xD2, 0xFF, 0xA3, 0x07, 0x29, 0xFF, 0x00, 0xC9, 0x2D, 0x00, 0xB0, 0x15, 0x0A, 0x0A, +0xAA, 0xBF, 0x01, 0x00, 0xE1, 0x83, 0x09, 0xBF, 0x03, 0x00, 0xE1, 0x29, 0xFF, 0x00, 0x83, 0x0B, +0x4C, 0xB7, 0xFF, 0xA2, 0x01, 0x03, 0x4C, 0xBC, 0xFF, 0x0B, 0x3B, 0x5B, 0x08, 0x78, 0xA9, 0x74, +0x98, 0x48, 0xEB, 0x29, 0x00, 0xFF, 0x09, 0x5C, 0x00, 0x8F, 0x30, 0x00, 0xE1, 0x68, 0x29, 0x00, +0xFF, 0x09, 0xFE, 0x00, 0xEB, 0x8F, 0x32, 0x00, 0xE1, 0x8B, 0xE2, 0x20, 0xA5, 0x0B, 0x48, 0xAB, +0xC2, 0x30, 0xA5, 0x09, 0xAA, 0xBD, 0x06, 0x00, 0xC9, 0x5A, 0xA5, 0xF0, 0x06, 0xA2, 0x04, 0x03, +0x82, 0x75, 0x00, 0xAF, 0xD8, 0x00, 0xE1, 0xC5, 0x09, 0xD0, 0x0D, 0xAF, 0xDA, 0x00, 0xE1, 0xC5, +0x0B, 0xD0, 0x05, 0xA2, 0x03, 0x03, 0x80, 0x60, 0xAF, 0xD8, 0x00, 0xE1, 0x0F, 0xDA, 0x00, 0xE1, +0xD0, 0x29, 0xA5, 0x09, 0x8F, 0xD8, 0x00, 0xE1, 0xA5, 0x0B, 0x8F, 0xDA, 0x00, 0xE1, 0xE2, 0x20, +0xAF, 0xDA, 0x00, 0xE1, 0x48, 0xAB, 0xC2, 0x20, 0xAF, 0xD8, 0x00, 0xE1, 0xAA, 0xA9, 0x00, 0x00, +0x9D, 0x00, 0x00, 0x9D, 0x02, 0x00, 0xAB, 0x28, 0x4C, 0xC3, 0xFF, 0xE2, 0x20, 0xAF, 0xDA, 0x00, +0xE1, 0x48, 0xAB, 0xC2, 0x20, 0xAF, 0xD8, 0x00, 0xE1, 0xAA, 0xBD, 0x06, 0x00, 0xC9, 0x5A, 0xA5, +0xF0, 0x05, 0xA2, 0x05, 0x00, 0x80, 0x11, 0xBD, 0x00, 0x00, 0xC5, 0x09, 0xD0, 0x0F, 0xBD, 0x02, +0x00, 0xC5, 0x0B, 0xD0, 0x08, 0xA2, 0x03, 0x03, 0xAB, 0x28, 0x4C, 0xC6, 0xFF, 0xBD, 0x00, 0x00, +0x1D, 0x02, 0x00, 0xF0, 0x0F, 0xE2, 0x20, 0xBD, 0x02, 0x00, 0x48, 0xC2, 0x20, 0xBD, 0x00, 0x00, +0xAA, 0xAB, 0x80, 0xC6, 0xA5, 0x0B, 0x9D, 0x02, 0x00, 0xA5, 0x09, 0x9D, 0x00, 0x00, 0xAA, 0xE2, +0x20, 0xA5, 0x0B, 0x48, 0xAB, 0xC2, 0x20, 0x80, 0x94, 0x0B, 0x3B, 0x5B, 0x08, 0x78, 0x8B, 0xE2, +0x20, 0xA9, 0xE1, 0x48, 0xAB, 0xC2, 0x20, 0xA2, 0xD8, 0x00, 0xBD, 0x00, 0x00, 0x1D, 0x02, 0x00, +0xF0, 0x2E, 0xC2, 0x20, 0xBD, 0x00, 0x00, 0xC5, 0x09, 0xD0, 0x27, 0xE2, 0x20, 0xBD, 0x02, 0x00, +0xC5, 0x0B, 0xD0, 0x1E, 0x8B, 0xDA, 0x48, 0xC2, 0x20, 0xBD, 0x00, 0x00, 0xAA, 0xAB, 0xBD, 0x02, +0x00, 0xA8, 0xBD, 0x00, 0x00, 0xFA, 0xAB, 0x9D, 0x00, 0x00, 0x98, 0x9D, 0x02, 0x00, 0x80, 0x5A, +0x80, 0x6C, 0xE2, 0x20, 0xBD, 0x02, 0x00, 0x48, 0xC2, 0x20, 0xBD, 0x00, 0x00, 0xAA, 0xAB, 0xBD, +0x06, 0x00, 0xC9, 0x5A, 0xA5, 0xF0, 0x08, 0xA2, 0x05, 0x03, 0xAB, 0x28, 0x4C, 0xC6, 0xFF, 0xBD, +0x00, 0x00, 0x1D, 0x02, 0x00, 0xF0, 0x47, 0xBD, 0x00, 0x00, 0xC5, 0x09, 0xD0, 0x31, 0xBD, 0x02, +0x00, 0xC5, 0x0B, 0xD0, 0x2A, 0x8B, 0xDA, 0xE2, 0x20, 0xBD, 0x02, 0x00, 0x48, 0xC2, 0x20, 0xBD, +0x00, 0x00, 0xAA, 0xAB, 0xBD, 0x00, 0x00, 0x85, 0x09, 0xBD, 0x02, 0x00, 0x85, 0x0B, 0xFA, 0xAB, +0xA5, 0x09, 0x9D, 0x00, 0x00, 0xA5, 0x0B, 0x9D, 0x02, 0x00, 0xAB, 0x28, 0x4C, 0xC3, 0xFF, 0xE2, +0x20, 0xBD, 0x02, 0x00, 0x48, 0xC2, 0x20, 0xBD, 0x00, 0x00, 0xAA, 0xAB, 0x80, 0xA1, 0xAB, 0x28, +0xA2, 0x06, 0x03, 0x4C, 0xC6, 0xFF, 0xA9, 0x00, 0x00, 0x8F, 0xD8, 0x00, 0xE1, 0x8F, 0xDA, 0x00, +0xE1, 0x4C, 0x8B, 0xFF, 0xC2, 0x30, 0xAF, 0xDC, 0x00, 0xE1, 0x1A, 0x8F, 0xDC, 0x00, 0xE1, 0xD0, +0x09, 0xAF, 0xDE, 0x00, 0xE1, 0x1A, 0x8F, 0xDE, 0x00, 0xE1, 0xC2, 0x30, 0xAF, 0xD8, 0x00, 0xE1, +0xAA, 0x0F, 0xDA, 0x00, 0xE1, 0xF0, 0x5B, 0x8B, 0xE2, 0x20, 0xAF, 0xDA, 0x00, 0xE1, 0x48, 0xAB, +0xC2, 0x20, 0xBD, 0x06, 0x00, 0xC9, 0x5A, 0xA5, 0xF0, 0x10, 0xF4, 0x08, 0x03, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xA2, 0x03, 0x15, 0x22, 0x00, 0x00, 0xE1, 0xBD, 0x04, 0x00, 0xF0, 0x1B, 0xDE, +0x04, 0x00, 0xD0, 0x16, 0x8B, 0xDA, 0x4B, 0xF4, 0xD3, 0x98, 0x8B, 0x18, 0x8A, 0x69, 0x07, 0x00, +0x48, 0xE2, 0x30, 0x6B, 0x18, 0xFB, 0xC2, 0x30, 0xFA, 0xAB, 0xBD, 0x00, 0x00, 0x1D, 0x02, 0x00, +0xF0, 0x0F, 0xE2, 0x20, 0xBD, 0x02, 0x00, 0x48, 0xC2, 0x20, 0xBD, 0x00, 0x00, 0xAA, 0xAB, 0x80, +0xB1, 0xAB, 0xE2, 0x30, 0x8F, 0x47, 0xC0, 0x00, 0x18, 0x6B, 0x18, 0xA3, 0x07, 0x03, 0x07, 0xD0, +0x01, 0x38, 0x8B, 0x68, 0x68, 0x5C, 0x1C, 0x00, 0xE1, 0xA3, 0x07, 0x0A, 0x0A, 0xC9, 0x3C, 0x00, +0x90, 0x06, 0xA2, 0x01, 0x03, 0x4C, 0xBC, 0xFF, 0xAA, 0xBF, 0x28, 0x99, 0xFE, 0x83, 0x09, 0xBF, +0x2A, 0x99, 0xFE, 0x83, 0x0B, 0x4C, 0xB7, 0xFF, 0xC3, 0x00, 0xE1, 0x00, 0xC4, 0x00, 0xE1, 0x00, +0xC7, 0x00, 0xE1, 0x00, 0xC8, 0x00, 0xE1, 0x00, 0xC9, 0x00, 0xE1, 0x00, 0xDC, 0x00, 0xE1, 0x00, +0xCA, 0x00, 0xE1, 0x00, 0xCB, 0x00, 0xE1, 0x00, 0xCC, 0x00, 0xE1, 0x00, 0x08, 0x01, 0xE1, 0x00, +0xE1, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xB8, 0x02, 0xE1, 0x00, 0xD0, 0x1D, 0xE1, 0x00, +0x04, 0x01, 0xE1, 0x00, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0x90, 0xFF, 0x08, 0x78, 0x20, 0x96, +0x9B, 0xE2, 0x30, 0xAF, 0xE0, 0x00, 0xE1, 0xAA, 0xBF, 0x78, 0x05, 0x00, 0x83, 0x0D, 0xBF, 0x78, +0x04, 0x00, 0x83, 0x0C, 0xBF, 0xF8, 0x05, 0x00, 0x83, 0x0B, 0xBF, 0xF8, 0x04, 0x00, 0x83, 0x0A, +0xBF, 0x78, 0x07, 0x00, 0x83, 0x09, 0xBF, 0xF8, 0x07, 0x00, 0x83, 0x08, 0xC2, 0x30, 0x28, 0x4C, +0x8B, 0xFF, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0xBC, 0xFF, 0x08, 0x78, 0xA3, 0x08, 0x29, 0x0F, +0x00, 0x20, 0x8C, 0x9B, 0x28, 0x4C, 0xB7, 0xFF, 0x08, 0xA3, 0x08, 0x8F, 0xBE, 0x02, 0xE1, 0xA3, +0x0A, 0x8F, 0xBA, 0x02, 0xE1, 0xA3, 0x0C, 0x8F, 0xBC, 0x02, 0xE1, 0xA3, 0x0E, 0x8F, 0xB8, 0x02, +0xE1, 0x20, 0x6A, 0x9B, 0x90, 0x04, 0x28, 0x4C, 0xDD, 0xFF, 0x78, 0xE2, 0x30, 0xA3, 0x0F, 0x8F, +0x78, 0x05, 0x00, 0xA3, 0x0E, 0x8F, 0x78, 0x04, 0x00, 0xA3, 0x0D, 0x8F, 0xF8, 0x05, 0x00, 0xA3, +0x0C, 0x8F, 0xF8, 0x04, 0x00, 0xC2, 0x30, 0xA9, 0x00, 0x00, 0x20, 0xA5, 0x9B, 0xE2, 0x30, 0xA3, +0x0B, 0x8F, 0x78, 0x05, 0x00, 0xA3, 0x0A, 0x8F, 0x78, 0x04, 0x00, 0xA3, 0x09, 0x8F, 0xF8, 0x05, +0x00, 0xA3, 0x08, 0x8F, 0xF8, 0x04, 0x00, 0xC2, 0x30, 0xA9, 0x01, 0x00, 0x20, 0xA5, 0x9B, 0x28, +0x4C, 0xD8, 0xFF, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0xC7, 0xFF, 0x08, 0x78, 0xE2, 0x30, 0xAF, +0xE0, 0x00, 0xE1, 0xAA, 0xA3, 0x0B, 0x9F, 0x78, 0x05, 0x00, 0xA3, 0x0A, 0x9F, 0x78, 0x04, 0x00, +0xA3, 0x09, 0x9F, 0xF8, 0x05, 0x00, 0xA3, 0x08, 0x9F, 0xF8, 0x04, 0x00, 0xC2, 0x30, 0x20, 0xA0, +0x9B, 0x28, 0x4C, 0xC2, 0xFF, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0x90, 0xFF, 0x08, 0x78, 0x20, +0x91, 0x9B, 0xE2, 0x30, 0xAF, 0xE0, 0x00, 0xE1, 0xAA, 0xBF, 0x78, 0x07, 0x00, 0x83, 0x08, 0xC2, +0x30, 0x28, 0x4C, 0x8B, 0xFF, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0x90, 0xFF, 0x0B, 0x3B, 0x5B, +0xE2, 0x30, 0xAF, 0xE0, 0x00, 0xE1, 0xC9, 0x03, 0xD0, 0x0A, 0xAF, 0x17, 0xC0, 0x00, 0x29, 0x80, +0xF0, 0x0C, 0xD0, 0x27, 0xAA, 0xAD, 0x2D, 0xC0, 0x6A, 0xCA, 0x10, 0xFC, 0xB0, 0x1D, 0xC2, 0x30, +0xAF, 0xBE, 0x02, 0xE1, 0x85, 0x09, 0xAF, 0xBA, 0x02, 0xE1, 0x85, 0x0B, 0xAF, 0xBC, 0x02, 0xE1, +0x85, 0x0D, 0xAF, 0xB8, 0x02, 0xE1, 0x85, 0x0F, 0x4C, 0x8C, 0xFF, 0x08, 0x78, 0xE2, 0x30, 0x8B, +0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xAF, 0xE0, 0x00, 0xE1, 0x09, 0xC0, 0xAA, 0x0A, 0x0A, 0x0A, 0x0A, +0xA8, 0x9C, 0xF8, 0x04, 0xA9, 0x4E, 0x8D, 0x78, 0x04, 0x20, 0x1D, 0x9B, 0x85, 0x09, 0xCE, 0x78, +0x04, 0x20, 0x1D, 0x9B, 0x85, 0x0D, 0xCE, 0x78, 0x04, 0x20, 0x1D, 0x9B, 0x85, 0x0A, 0xCE, 0x78, +0x04, 0x20, 0x1D, 0x9B, 0x85, 0x0E, 0xCE, 0x78, 0x04, 0x20, 0x1D, 0x9B, 0x85, 0x0B, 0xCE, 0x78, +0x04, 0x20, 0x1D, 0x9B, 0x85, 0x0F, 0xCE, 0x78, 0x04, 0x20, 0x1D, 0x9B, 0x85, 0x0C, 0xCE, 0x78, +0x04, 0x20, 0x1D, 0x9B, 0x85, 0x10, 0xAB, 0x28, 0xC2, 0x30, 0x4C, 0x8C, 0xFF, 0xAF, 0xE0, 0x00, +0xE1, 0x09, 0xC0, 0xAA, 0x0A, 0x0A, 0x0A, 0x0A, 0xA8, 0xA9, 0x00, 0xC2, 0x30, 0x20, 0xAF, 0x9B, +0xE2, 0x30, 0xAD, 0x78, 0x05, 0x60, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0x90, 0xFF, 0x08, 0x78, +0x20, 0x9B, 0x9B, 0x28, 0x4C, 0x8B, 0xFF, 0x20, 0x6A, 0x9B, 0x90, 0x03, 0x4C, 0x90, 0xFF, 0x08, +0x78, 0x20, 0xAA, 0x9B, 0x28, 0x4C, 0x8B, 0xFF, 0x08, 0x78, 0x20, 0xB4, 0x9B, 0x90, 0x07, 0x28, +0xA2, 0x02, 0x03, 0x4C, 0xBC, 0xFF, 0x28, 0x4C, 0xB7, 0xFF, 0xE2, 0x20, 0xAF, 0xE0, 0x00, 0xE1, +0x30, 0x13, 0x09, 0xC0, 0xEB, 0xA9, 0x0B, 0xAA, 0xC2, 0x20, 0xBF, 0x00, 0x00, 0x00, 0xC9, 0x01, +0x20, 0xD0, 0x02, 0x18, 0x60, 0xC2, 0x30, 0x38, 0xA2, 0x09, 0x03, 0x60, 0xF4, 0x12, 0xC0, 0x80, +0x7A, 0xF4, 0x13, 0xC0, 0x80, 0x75, 0xF4, 0x14, 0xC0, 0x80, 0x70, 0xF4, 0x15, 0xC0, 0x80, 0x6B, +0xF4, 0x16, 0xC0, 0x80, 0x66, 0xF4, 0x17, 0xC0, 0x80, 0x61, 0xF4, 0x18, 0xC0, 0x80, 0x5C, 0xF4, +0x1A, 0xC0, 0x80, 0x57, 0xE2, 0x30, 0xA3, 0x0A, 0x8B, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xC9, 0x00, +0xF0, 0x14, 0xC2, 0x30, 0x29, 0x07, 0x00, 0xEB, 0x09, 0x0B, 0xC0, 0xAA, 0xBD, 0x00, 0x00, 0xC9, +0x01, 0x20, 0xF0, 0x27, 0xD0, 0x18, 0xC2, 0x30, 0xA2, 0x0B, 0xC7, 0xBD, 0x00, 0x00, 0xC9, 0x01, +0x20, 0xF0, 0x18, 0x8A, 0x38, 0xE9, 0x00, 0x01, 0xAA, 0xC9, 0x0B, 0xC0, 0xD0, 0xED, 0xE2, 0x20, +0xA9, 0x80, 0x8F, 0xE0, 0x00, 0xE1, 0xC2, 0x30, 0xAB, 0x38, 0x60, 0xAB, 0x8A, 0xEB, 0xE2, 0x30, +0x29, 0x07, 0x8F, 0xE0, 0x00, 0xE1, 0xC2, 0x30, 0xF4, 0x19, 0xC0, 0x48, 0x0B, 0x3B, 0x5B, 0xE2, +0x20, 0xAF, 0xE0, 0x00, 0xE1, 0xC2, 0x20, 0x10, 0x12, 0xC2, 0x30, 0xF4, 0x09, 0x03, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x15, 0x22, 0x00, 0x00, 0xE1, 0xEB, 0x29, 0x00, 0x07, 0x09, +0x00, 0x10, 0xAA, 0xBF, 0x0B, 0xB0, 0x00, 0xC9, 0x01, 0x20, 0xD0, 0xDD, 0x8A, 0x29, 0xFF, 0xEF, +0x05, 0x05, 0x85, 0x05, 0xAA, 0xE2, 0x20, 0xBF, 0x00, 0x00, 0x00, 0x3A, 0x85, 0x05, 0xAF, 0xE0, +0x00, 0xE1, 0x09, 0xC0, 0xAA, 0x0A, 0x0A, 0x0A, 0x0A, 0xA8, 0xC2, 0x20, 0x2B, 0x68, 0xE2, 0x30, +0x48, 0x8B, 0xA9, 0x00, 0x48, 0xAB, 0xAD, 0x36, 0xC0, 0x48, 0xAD, 0x68, 0xC0, 0x48, 0xA9, 0x08, +0x8D, 0x68, 0xC0, 0x0B, 0x3B, 0x5B, 0xDA, 0xC2, 0x20, 0xA5, 0x07, 0x1A, 0xEB, 0xE2, 0x20, 0xC9, +0xC8, 0xB0, 0x2A, 0x29, 0xF0, 0xC9, 0xC0, 0xD0, 0x24, 0xC2, 0x20, 0xA5, 0x07, 0x1A, 0xEB, 0xE2, +0x20, 0x29, 0x07, 0xC9, 0x03, 0xD0, 0x08, 0xAF, 0x17, 0xC0, 0x00, 0x29, 0x80, 0x80, 0x0B, 0xAA, +0xAD, 0x2D, 0xC0, 0x6A, 0xCA, 0x10, 0xFC, 0xA9, 0x00, 0x6A, 0x1C, 0x36, 0xC0, 0xFA, 0xC2, 0x30, +0x8A, 0xEB, 0xE2, 0x20, 0x98, 0xC2, 0x20, 0xAA, 0x3B, 0xA8, 0xE2, 0x20, 0xEB, 0x3A, 0xF0, 0x0A, +0xA9, 0x01, 0xEB, 0xAF, 0x00, 0x01, 0x01, 0xC2, 0x20, 0x1B, 0x5A, 0xC2, 0x20, 0x8A, 0xE2, 0x30, +0xA8, 0xEB, 0xAA, 0x0B, 0xF4, 0xEA, 0x9C, 0xAD, 0x15, 0xC0, 0x48, 0xC2, 0x20, 0xA5, 0x07, 0x48, +0xE2, 0x30, 0xA5, 0x06, 0xF4, 0x00, 0x00, 0x2B, 0x82, 0x1F, 0x00, 0x2B, 0x85, 0x07, 0x08, 0x68, +0x85, 0x08, 0xC2, 0x30, 0x68, 0x1B, 0xE2, 0x30, 0x2B, 0x68, 0x8D, 0x68, 0xC0, 0x68, 0x8D, 0x36, +0xC0, 0xAB, 0xE2, 0x30, 0x68, 0x68, 0x28, 0xC2, 0x30, 0x60, 0xEB, 0x8A, 0xC2, 0x30, 0xFA, 0x4B, +0xF4, 0x33, 0x9D, 0xF4, 0xD3, 0xF8, 0xDA, 0xE2, 0x30, 0xAA, 0xEB, 0xEB, 0xAF, 0x36, 0xC0, 0x00, +0x29, 0x7F, 0x0F, 0x37, 0x01, 0xE1, 0x8F, 0x36, 0xC0, 0x00, 0xEB, 0x8B, 0xF4, 0xB4, 0xF8, 0x8F, +0x06, 0xC0, 0x00, 0x6B, 0xE2, 0x30, 0xEB, 0x8B, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xA9, 0x80, 0x0C, +0x36, 0xC0, 0xA3, 0x02, 0x10, 0x07, 0x8D, 0x07, 0xC0, 0xAB, 0x68, 0xEB, 0x60, 0x8D, 0x06, 0xC0, +0x80, 0xF7, 0x0B, 0x8B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0x3B, 0x5B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAF, 0xD2, 0x0F, 0xE1, 0x48, +0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0xFA, 0x86, 0x05, 0x86, +0x09, 0xE8, 0xE8, 0x68, 0xAF, 0xD2, 0x0F, 0xE1, 0xA8, 0x5A, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xF4, +0x00, 0x00, 0xDA, 0x5A, 0x48, 0xA2, 0x02, 0x19, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x02, 0x20, 0x22, +0x00, 0x00, 0xE1, 0x20, 0x43, 0x91, 0x86, 0x01, 0x84, 0x03, 0xA4, 0x05, 0xF0, 0x04, 0x88, 0x88, +0x84, 0x05, 0xA5, 0x14, 0x29, 0x00, 0xF0, 0x1A, 0x85, 0x07, 0x29, 0x00, 0xF0, 0xD0, 0x05, 0xA2, +0x01, 0x03, 0x80, 0x3F, 0xA5, 0x14, 0x29, 0x00, 0x0F, 0x85, 0x14, 0xC0, 0x00, 0x00, 0xF0, 0x1C, +0xB7, 0x01, 0x29, 0xFF, 0xF0, 0xC5, 0x07, 0xF0, 0x09, 0xC0, 0x00, 0x00, 0xF0, 0x0E, 0x88, 0x88, +0x80, 0xEE, 0xE6, 0x07, 0xA4, 0x05, 0xC6, 0x09, 0xC6, 0x09, 0xD0, 0xE4, 0xA5, 0x07, 0x05, 0x14, +0x85, 0x16, 0xA4, 0x05, 0xC8, 0xC8, 0x97, 0x01, 0xA2, 0x00, 0x00, 0x29, 0xFF, 0x00, 0xD0, 0x03, +0xA2, 0x0B, 0x03, 0xDA, 0xAF, 0xD2, 0x0F, 0xE1, 0x48, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xA2, 0x02, +0x22, 0x22, 0x00, 0x00, 0xE1, 0xFA, 0x68, 0x68, 0x68, 0x68, 0x68, 0xAB, 0x2B, 0xE0, 0x00, 0x00, +0xD0, 0x03, 0x4C, 0xB7, 0xFF, 0xDA, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAF, 0xD2, 0x0F, 0xE1, +0x48, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x38, 0xA3, 0x01, +0xE9, 0x02, 0x00, 0x83, 0x01, 0xAF, 0xD2, 0x0F, 0xE1, 0x48, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xA2, +0x02, 0x19, 0x22, 0x00, 0x00, 0xE1, 0xFA, 0x4C, 0xBC, 0xFF, 0x0B, 0x8B, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x3B, 0x5B, 0xA5, 0x12, 0x29, 0xFF, 0xF0, 0x85, +0x12, 0xAF, 0xD2, 0x0F, 0xE1, 0xA8, 0x5A, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0x5A, 0x48, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0x5A, 0x48, 0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x05, +0x68, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x20, 0x43, 0x91, 0x86, 0x01, 0x84, 0x03, 0xA5, +0x05, 0xF0, 0x26, 0xA0, 0x00, 0x00, 0xB7, 0x01, 0x29, 0xFF, 0xF0, 0xC5, 0x12, 0xF0, 0x08, 0xC8, +0xC8, 0xC4, 0x05, 0xD0, 0xF1, 0xF0, 0x12, 0xE6, 0x07, 0xC4, 0x05, 0xF0, 0x0C, 0xC8, 0xC8, 0xB7, +0x01, 0x88, 0x88, 0x97, 0x01, 0xC8, 0xC8, 0x80, 0xF0, 0x06, 0x07, 0xA2, 0x02, 0x22, 0x22, 0x00, +0x00, 0xE1, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAF, 0xD2, 0x0F, 0xE1, 0x48, 0xAF, 0xD0, 0x0F, +0xE1, 0x48, 0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x38, 0xA3, 0x01, 0xE5, 0x07, 0x83, 0x01, +0xAF, 0xD2, 0x0F, 0xE1, 0x48, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xA2, 0x02, 0x19, 0x22, 0x00, 0x00, +0xE1, 0x68, 0x68, 0x68, 0x68, 0xAB, 0x4C, 0xB8, 0xFF, 0x0B, 0x8B, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0x3B, 0x5B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAF, 0xD2, 0x0F, 0xE1, +0xA8, 0x5A, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0x5A, 0x48, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, +0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x05, 0x68, 0x20, 0x43, 0x91, 0x86, 0x01, +0x84, 0x03, 0xA5, 0x10, 0x29, 0xFF, 0xF0, 0x85, 0x10, 0xA0, 0x00, 0x00, 0xC4, 0x05, 0xF0, 0x0D, +0xB7, 0x01, 0x29, 0xFF, 0xF0, 0xC5, 0x10, 0xF0, 0x06, 0xC8, 0xC8, 0x80, 0xEF, 0x64, 0x05, 0xAF, +0xD2, 0x0F, 0xE1, 0x48, 0xAF, 0xD0, 0x0F, 0xE1, 0x48, 0xA2, 0x02, 0x22, 0x22, 0x00, 0x00, 0xE1, +0x68, 0x68, 0x68, 0xAB, 0xC9, 0x00, 0x00, 0xF0, 0x03, 0x4C, 0xB8, 0xFF, 0xA2, 0x0B, 0x03, 0x4C, +0xBB, 0xFF, 0xA3, 0x07, 0x0A, 0xAA, 0xE0, 0x20, 0x00, 0xB0, 0x12, 0xF4, 0x95, 0x9F, 0xBF, 0xA3, +0x9F, 0xFE, 0x48, 0xE2, 0x30, 0x60, 0xC2, 0x30, 0xB0, 0x03, 0x4C, 0xB7, 0xFF, 0xA2, 0x01, 0x03, +0x4C, 0xBC, 0xFF, 0xC2, 0x9F, 0x16, 0xA0, 0x2C, 0xA0, 0x37, 0xA0, 0x42, 0xA0, 0x4D, 0xA0, 0x58, +0xA0, 0x63, 0xA0, 0x9A, 0xA0, 0x9B, 0xA0, 0x9C, 0xA0, 0xA7, 0xA0, 0x6E, 0xA0, 0x79, 0xA0, 0x84, +0xA0, 0x8F, 0xA0, 0xA9, 0x80, 0x8F, 0xD4, 0x0F, 0xE1, 0xC2, 0x30, 0xA9, 0x01, 0x00, 0x8F, 0x50, +0x01, 0xE1, 0xA9, 0x5A, 0xA5, 0x8F, 0x52, 0x01, 0xE1, 0xA9, 0x06, 0xA0, 0x48, 0xEB, 0x29, 0x00, +0xFF, 0x09, 0x5C, 0x00, 0x8F, 0x54, 0x01, 0xE1, 0x68, 0x29, 0x00, 0xFF, 0x09, 0xFE, 0x00, 0xEB, +0x8F, 0x56, 0x01, 0xE1, 0xF4, 0xE1, 0x00, 0xF4, 0x4C, 0x01, 0xA2, 0x03, 0x12, 0x22, 0x00, 0x00, +0xE1, 0xE2, 0x30, 0x18, 0x80, 0x27, 0xA9, 0x01, 0x8F, 0x50, 0x01, 0xE1, 0xAF, 0x00, 0xC0, 0x00, +0x10, 0x04, 0x5C, 0x3C, 0x00, 0xE1, 0x6B, 0xA9, 0x00, 0x8F, 0xD4, 0x0F, 0xE1, 0xC2, 0x30, 0xF4, +0xE1, 0x00, 0xF4, 0x4C, 0x01, 0xA2, 0x03, 0x13, 0x22, 0x00, 0x00, 0xE1, 0x60, 0xAF, 0x41, 0xC0, +0x00, 0x09, 0x08, 0x8F, 0x41, 0xC0, 0x00, 0x60, 0xAF, 0x41, 0xC0, 0x00, 0x29, 0xF7, 0x8F, 0x41, +0xC0, 0x00, 0x60, 0xAF, 0x41, 0xC0, 0x00, 0x09, 0x10, 0x8F, 0x41, 0xC0, 0x00, 0x60, 0xAF, 0x41, +0xC0, 0x00, 0x29, 0xEF, 0x8F, 0x41, 0xC0, 0x00, 0x60, 0xAF, 0x23, 0xC0, 0x00, 0x09, 0x04, 0x8F, +0x23, 0xC0, 0x00, 0x60, 0xAF, 0x23, 0xC0, 0x00, 0x29, 0xFB, 0x8F, 0x23, 0xC0, 0x00, 0x60, 0xAF, +0x23, 0xC0, 0x00, 0x09, 0x02, 0x8F, 0x23, 0xC0, 0x00, 0x60, 0xAF, 0x23, 0xC0, 0x00, 0x29, 0xFD, +0x8F, 0x23, 0xC0, 0x00, 0x60, 0xAF, 0x23, 0xC0, 0x00, 0x09, 0x01, 0x8F, 0x23, 0xC0, 0x00, 0x60, +0xAF, 0x23, 0xC0, 0x00, 0x29, 0xFE, 0x8F, 0x23, 0xC0, 0x00, 0x60, 0x60, 0x60, 0xAF, 0x27, 0xC0, +0x00, 0x09, 0x10, 0x8F, 0x27, 0xC0, 0x00, 0x60, 0xAF, 0x27, 0xC0, 0x00, 0x29, 0xEF, 0x8F, 0x27, +0xC0, 0x00, 0x60, 0x08, 0x78, 0xAF, 0xDC, 0x00, 0xE1, 0x83, 0x08, 0xAF, 0xDE, 0x00, 0xE1, 0x83, +0x0A, 0x28, 0x4C, 0x8B, 0xFF, 0x0B, 0x3B, 0x5B, 0xA5, 0x09, 0x3A, 0xF4, 0xD7, 0xA0, 0x48, 0xA4, +0x0B, 0xA6, 0x0D, 0xA5, 0x0F, 0x82, 0x86, 0xFB, 0x08, 0x29, 0xFF, 0x00, 0x85, 0x15, 0x86, 0x13, +0x84, 0x11, 0xA3, 0x01, 0x29, 0xC7, 0x00, 0xEB, 0x85, 0x17, 0xC2, 0x20, 0x28, 0x4C, 0xD9, 0xFF, +0x0B, 0x3B, 0x38, 0xE9, 0x14, 0x00, 0x1B, 0x5B, 0xA7, 0x27, 0xAA, 0xA0, 0x02, 0x00, 0xB7, 0x27, +0x85, 0x03, 0x86, 0x01, 0xA7, 0x23, 0x85, 0x11, 0xA5, 0x1D, 0x38, 0xE9, 0x05, 0x00, 0x18, 0x65, +0x1F, 0x85, 0x09, 0xA5, 0x21, 0x85, 0x07, 0x69, 0x00, 0x00, 0x85, 0x0B, 0xA5, 0x1F, 0x85, 0x05, +0xA9, 0x00, 0x00, 0xA8, 0x97, 0x05, 0x85, 0x13, 0xE6, 0x13, 0xA9, 0xFF, 0xFF, 0x85, 0x0D, 0x85, +0x0F, 0x20, 0x33, 0xA3, 0x90, 0x03, 0x4C, 0xC7, 0xA1, 0xA2, 0x01, 0x00, 0x20, 0x33, 0xA3, 0xB0, +0x29, 0xE0, 0x40, 0x00, 0xF0, 0x24, 0xA5, 0x11, 0xF0, 0x20, 0x38, 0xE9, 0x04, 0x00, 0x90, 0x1A, +0xA5, 0x01, 0x18, 0x69, 0x04, 0x00, 0x85, 0x01, 0xA5, 0x03, 0x69, 0x00, 0x00, 0x85, 0x03, 0xE8, +0xA5, 0x11, 0x38, 0xE9, 0x04, 0x00, 0x85, 0x11, 0x80, 0xD2, 0xCA, 0xDA, 0x20, 0x18, 0xA3, 0xF0, +0x2B, 0x68, 0x09, 0x80, 0x00, 0xA0, 0x00, 0x00, 0x97, 0x05, 0xB7, 0x01, 0xC8, 0x97, 0x05, 0xC8, +0xB7, 0x01, 0x85, 0x13, 0xC8, 0x97, 0x05, 0xA5, 0x05, 0x85, 0x0D, 0x18, 0x69, 0x05, 0x00, 0x85, +0x05, 0xA5, 0x07, 0x85, 0x0F, 0x69, 0x00, 0x00, 0x85, 0x07, 0x80, 0x25, 0x68, 0x09, 0xC0, 0x00, +0x87, 0x05, 0xA0, 0x03, 0x00, 0xB7, 0x01, 0x85, 0x13, 0xA0, 0x01, 0x00, 0x97, 0x05, 0xA5, 0x05, +0x85, 0x0D, 0x18, 0x69, 0x02, 0x00, 0x85, 0x05, 0xA5, 0x07, 0x85, 0x0F, 0x69, 0x00, 0x00, 0x85, +0x07, 0xA2, 0x04, 0x00, 0x4C, 0x1D, 0xA2, 0x20, 0x33, 0xA3, 0x90, 0x06, 0xC8, 0xC0, 0x04, 0x00, +0x90, 0xF5, 0x5A, 0xA0, 0x00, 0x00, 0x20, 0x18, 0xA3, 0x8A, 0xFA, 0xA0, 0x00, 0x00, 0x48, 0x8A, +0x38, 0xE3, 0x01, 0x90, 0x03, 0xA3, 0x01, 0xAA, 0x68, 0x8A, 0xC5, 0x11, 0x90, 0x02, 0xA6, 0x11, +0xA5, 0x13, 0xEB, 0xC5, 0x13, 0xD0, 0x59, 0xA5, 0x0F, 0xC9, 0xFF, 0xFF, 0xF0, 0x52, 0xB7, 0x0D, +0x29, 0xFF, 0x00, 0xC9, 0xC0, 0x00, 0xD0, 0x48, 0x8A, 0x18, 0x69, 0x03, 0x00, 0x09, 0x40, 0x00, +0x48, 0xB7, 0x0D, 0x29, 0x00, 0xFF, 0x97, 0x0D, 0x68, 0x17, 0x0D, 0x97, 0x0D, 0x8A, 0x18, 0x65, +0x01, 0x85, 0x01, 0xA5, 0x03, 0x69, 0x00, 0x00, 0x85, 0x03, 0xDA, 0xA5, 0x11, 0x38, 0xE3, 0x01, +0xFA, 0x85, 0x11, 0xC9, 0x00, 0x00, 0xD0, 0x03, 0x4C, 0xDE, 0xA2, 0xA5, 0x07, 0xC5, 0x0B, 0xD0, +0x09, 0xA5, 0x05, 0xC5, 0x09, 0x90, 0x03, 0x4C, 0xDE, 0xA2, 0xA0, 0x00, 0x00, 0x4C, 0x31, 0xA1, +0xE0, 0x03, 0x00, 0x90, 0x36, 0xF0, 0x05, 0xA9, 0xC0, 0x00, 0x80, 0x03, 0xA9, 0x42, 0x00, 0x48, +0xB7, 0x01, 0x29, 0xFF, 0x00, 0xEB, 0x97, 0x05, 0x68, 0x17, 0x05, 0x97, 0x05, 0x9B, 0x88, 0xB7, +0x01, 0x85, 0x13, 0xA0, 0x00, 0x00, 0xA5, 0x05, 0x85, 0x0D, 0x18, 0x69, 0x02, 0x00, 0x85, 0x05, +0xA5, 0x07, 0x85, 0x0F, 0x69, 0x00, 0x00, 0x85, 0x07, 0x80, 0x92, 0xA5, 0x0F, 0xC9, 0xFF, 0xFF, +0xF0, 0x3D, 0xB7, 0x0D, 0x29, 0xC0, 0x00, 0xC9, 0x00, 0x00, 0xD0, 0x33, 0xB7, 0x0D, 0x29, 0xFF, +0x00, 0xC9, 0x3F, 0x00, 0xF0, 0x29, 0xE0, 0x02, 0x00, 0xD0, 0x08, 0xC9, 0x3E, 0x00, 0xD0, 0x03, +0xA2, 0x01, 0x00, 0x8A, 0x18, 0x77, 0x0D, 0x97, 0x0D, 0xB7, 0x01, 0x85, 0x13, 0x97, 0x05, 0x8A, +0x18, 0x65, 0x05, 0x85, 0x05, 0xA5, 0x07, 0x69, 0x00, 0x00, 0x85, 0x07, 0x4C, 0x1D, 0xA2, 0xB7, +0x01, 0x85, 0x13, 0x29, 0xFF, 0x00, 0xEB, 0x97, 0x05, 0xA2, 0x01, 0x00, 0x80, 0x98, 0xA5, 0x05, +0x38, 0xE5, 0x1F, 0x85, 0x2B, 0xA5, 0x01, 0x38, 0xE7, 0x27, 0x48, 0xA7, 0x23, 0x38, 0xE3, 0x01, +0x87, 0x23, 0x68, 0xA5, 0x01, 0x87, 0x27, 0xA5, 0x03, 0xA0, 0x02, 0x00, 0x97, 0x27, 0xA5, 0x15, +0x5B, 0xA3, 0x17, 0x83, 0x25, 0xA3, 0x19, 0x83, 0x27, 0xA3, 0x1B, 0x83, 0x29, 0x3B, 0x18, 0x69, +0x24, 0x00, 0x1B, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0xA2, 0x01, 0x00, 0xB7, 0x01, 0xEB, 0xD7, 0x01, +0xD0, 0x10, 0xE8, 0xC8, 0xD7, 0x01, 0xD0, 0x0A, 0xE8, 0xC8, 0xD7, 0x01, 0xD0, 0x04, 0xE8, 0xE0, +0x04, 0x00, 0x60, 0x5A, 0xB7, 0x01, 0xC8, 0xC8, 0xC8, 0xC8, 0xD7, 0x01, 0xD0, 0x17, 0x88, 0x88, +0xB7, 0x01, 0xC8, 0xC8, 0xC8, 0xC8, 0xD7, 0x01, 0xD0, 0x0B, 0xA5, 0x11, 0x38, 0xE9, 0x08, 0x00, +0x30, 0x03, 0x7A, 0x18, 0x60, 0x7A, 0x38, 0x60, 0x0B, 0x3B, 0x38, 0xE9, 0x14, 0x00, 0x1B, 0x5B, +0xA7, 0x21, 0xAA, 0xA0, 0x02, 0x00, 0xB7, 0x21, 0x85, 0x07, 0x86, 0x05, 0xA7, 0x1D, 0x85, 0x11, +0xA5, 0x27, 0x85, 0x01, 0x18, 0x65, 0x25, 0x85, 0x09, 0xA5, 0x29, 0x85, 0x03, 0x69, 0x00, 0x00, +0x85, 0x0B, 0xA0, 0x00, 0x00, 0xB7, 0x01, 0x85, 0x0D, 0x29, 0x3F, 0x00, 0xAA, 0xE6, 0x01, 0xD0, +0x02, 0xE6, 0x03, 0x24, 0x0C, 0x30, 0x04, 0x70, 0x0D, 0x80, 0x08, 0x70, 0x16, 0x80, 0x1C, 0x68, +0x4C, 0x81, 0xA4, 0x48, 0x80, 0x1B, 0xA5, 0x0D, 0x29, 0x00, 0xFF, 0x48, 0xEB, 0x03, 0x01, 0x83, +0x01, 0x80, 0x0E, 0xE8, 0x8A, 0x0A, 0x0A, 0xAA, 0xCA, 0x80, 0xEB, 0xE8, 0x8A, 0x0A, 0xAA, 0xCA, +0x48, 0xE4, 0x11, 0xB0, 0xDA, 0xA9, 0x01, 0x00, 0x24, 0x0C, 0x70, 0x09, 0x30, 0x04, 0x8A, 0x1A, +0x80, 0x03, 0xA9, 0x04, 0x00, 0x18, 0x65, 0x01, 0x48, 0xA5, 0x03, 0x69, 0x00, 0x00, 0xC5, 0x0B, +0x90, 0x09, 0x68, 0xC5, 0x09, 0x90, 0x05, 0xF0, 0x03, 0x80, 0xB4, 0x68, 0xE0, 0x00, 0x00, 0x30, +0x51, 0x24, 0x0C, 0x30, 0x36, 0x70, 0x1A, 0xE0, 0x00, 0x00, 0xF0, 0x09, 0xB7, 0x01, 0x97, 0x05, +0xC8, 0xC8, 0x4C, 0x3E, 0xA4, 0xE2, 0x20, 0xB7, 0x01, 0x97, 0x05, 0xC2, 0x20, 0xC8, 0x4C, 0x3E, +0xA4, 0xE0, 0x00, 0x00, 0xF0, 0x09, 0xA3, 0x01, 0x97, 0x05, 0xC8, 0xC8, 0x4C, 0x3E, 0xA4, 0xE2, +0x20, 0xA3, 0x01, 0x97, 0x05, 0xC2, 0x20, 0xC8, 0x4C, 0x3E, 0xA4, 0x70, 0xE4, 0xA7, 0x01, 0x97, +0x05, 0x5A, 0xA0, 0x02, 0x00, 0xB7, 0x01, 0x7A, 0xC8, 0xC8, 0x97, 0x05, 0xC8, 0xC8, 0xCA, 0xCA, +0x80, 0xAD, 0x68, 0xA5, 0x0D, 0x29, 0x3F, 0x00, 0x1A, 0x24, 0x0C, 0x30, 0x13, 0x50, 0x03, 0xA9, +0x01, 0x00, 0x18, 0x65, 0x01, 0x85, 0x01, 0xA5, 0x03, 0x69, 0x00, 0x00, 0x85, 0x03, 0x80, 0x07, +0x70, 0xED, 0xA9, 0x04, 0x00, 0x80, 0xEB, 0x98, 0x18, 0x65, 0x05, 0x85, 0x05, 0xA5, 0x07, 0x69, +0x00, 0x00, 0x85, 0x07, 0x98, 0x85, 0x0D, 0xA5, 0x11, 0x38, 0xE5, 0x0D, 0x85, 0x11, 0x4C, 0x82, +0xA3, 0xA5, 0x01, 0x38, 0xE5, 0x27, 0x3A, 0x85, 0x2B, 0xA5, 0x05, 0x38, 0xE7, 0x21, 0x48, 0xA7, +0x1D, 0x38, 0xE3, 0x01, 0x87, 0x1D, 0x68, 0xA5, 0x05, 0x87, 0x21, 0xA5, 0x07, 0xA0, 0x02, 0x00, +0x97, 0x21, 0xA5, 0x15, 0x5B, 0xA3, 0x17, 0x83, 0x25, 0xA3, 0x19, 0x83, 0x27, 0xA3, 0x1B, 0x83, +0x29, 0x3B, 0x18, 0x69, 0x24, 0x00, 0x1B, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0x0B, 0x3B, 0x38, 0xE9, +0x14, 0x00, 0x1B, 0x5B, 0xA7, 0x31, 0x85, 0x09, 0x85, 0x01, 0xA0, 0x02, 0x00, 0xB7, 0x31, 0x85, +0x0B, 0x85, 0x03, 0xA7, 0x2D, 0x85, 0x0D, 0xC5, 0x21, 0xB0, 0x02, 0x85, 0x21, 0xC5, 0x27, 0xB0, +0x02, 0x85, 0x27, 0xA7, 0x1D, 0x85, 0x13, 0xA5, 0x29, 0x85, 0x05, 0xAA, 0xA5, 0x2B, 0x85, 0x07, +0xD0, 0x07, 0xE0, 0x00, 0x00, 0xD0, 0x02, 0x80, 0x34, 0xA5, 0x0D, 0x38, 0xE5, 0x27, 0xF0, 0x05, +0x90, 0x03, 0x4C, 0x1A, 0xA5, 0xA5, 0x0D, 0x85, 0x27, 0x20, 0x70, 0xA6, 0xF0, 0x1F, 0xA9, 0x00, +0x00, 0x87, 0x1D, 0x85, 0x35, 0xC6, 0x35, 0x4C, 0x31, 0xA6, 0xAA, 0xA5, 0x27, 0x20, 0x70, 0xA6, +0xF0, 0x0B, 0xE6, 0x01, 0xD0, 0x02, 0xE6, 0x03, 0xCA, 0x10, 0xF0, 0x80, 0xE1, 0xA5, 0x23, 0xD0, +0x17, 0xA5, 0x25, 0xD0, 0x13, 0xA5, 0x27, 0xD0, 0x02, 0x85, 0x0D, 0x20, 0x4B, 0xA6, 0xA9, 0x00, +0x00, 0x85, 0x35, 0x87, 0x1D, 0x4C, 0x1C, 0xA6, 0x20, 0x4B, 0xA6, 0xA0, 0x02, 0x00, 0xA7, 0x31, +0x18, 0x67, 0x2D, 0x85, 0x05, 0xB7, 0x31, 0x69, 0x00, 0x00, 0x85, 0x07, 0xA5, 0x0D, 0x48, 0xA5, +0x27, 0x38, 0xE5, 0x21, 0x87, 0x1D, 0xA5, 0x01, 0x18, 0x65, 0x21, 0x85, 0x0F, 0xA5, 0x03, 0x69, +0x00, 0x00, 0x85, 0x11, 0xC5, 0x07, 0xB0, 0x0D, 0xA7, 0x1D, 0x10, 0x1C, 0x18, 0x65, 0x0D, 0x85, +0x0D, 0x83, 0x01, 0x80, 0x13, 0xD0, 0x06, 0xA5, 0x05, 0xC5, 0x0F, 0xB0, 0xEB, 0xA5, 0x05, 0x38, +0xE5, 0x01, 0x85, 0x21, 0x68, 0x4C, 0xFF, 0xA5, 0xFA, 0xA5, 0x0B, 0x48, 0xA5, 0x09, 0x48, 0xA5, +0x11, 0x48, 0xA5, 0x0F, 0x48, 0xF4, 0x00, 0x00, 0xDA, 0xA2, 0x02, 0x2B, 0x22, 0x00, 0x00, 0xE1, +0xA5, 0x27, 0x38, 0xE5, 0x21, 0xF0, 0x48, 0x90, 0x46, 0x48, 0xA5, 0x09, 0x18, 0x65, 0x0D, 0x85, +0x0F, 0xAA, 0xA5, 0x0B, 0x69, 0x00, 0x00, 0x85, 0x11, 0x8A, 0x38, 0xE3, 0x01, 0x85, 0x0F, 0xA5, +0x11, 0xE9, 0x00, 0x00, 0x85, 0x11, 0xA7, 0x0F, 0x29, 0x00, 0xFF, 0x05, 0x13, 0x87, 0x0F, 0xA5, +0x13, 0xEB, 0x05, 0x13, 0xAA, 0xA3, 0x01, 0x29, 0x01, 0x00, 0xF0, 0x0B, 0x68, 0x3A, 0xF0, 0x0F, +0x48, 0xE6, 0x0F, 0xD0, 0x02, 0xE6, 0x10, 0x7A, 0x8A, 0x88, 0x88, 0x97, 0x0F, 0xD0, 0xFA, 0xA5, +0x21, 0xF0, 0x19, 0xA5, 0x25, 0x48, 0xA5, 0x23, 0x48, 0xA5, 0x03, 0x48, 0xA5, 0x01, 0x48, 0xF4, +0x00, 0x00, 0xA5, 0x21, 0x48, 0xA2, 0x02, 0x2B, 0x22, 0x00, 0x00, 0xE1, 0xA0, 0x02, 0x00, 0xA5, +0x01, 0x18, 0x65, 0x21, 0x87, 0x31, 0xA5, 0x03, 0x69, 0x00, 0x00, 0x97, 0x31, 0xA5, 0x0D, 0x87, +0x2D, 0xA5, 0x15, 0x5B, 0xA3, 0x17, 0x83, 0x2F, 0xA3, 0x19, 0x83, 0x31, 0xA3, 0x1B, 0x83, 0x33, +0x3B, 0x18, 0x69, 0x2E, 0x00, 0x1B, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0xA5, 0x01, 0x18, 0x65, 0x27, +0x85, 0x0F, 0xA5, 0x03, 0x69, 0x00, 0x00, 0x85, 0x11, 0xA5, 0x0F, 0x38, 0xE5, 0x09, 0x85, 0x05, +0xA5, 0x0D, 0x38, 0xE5, 0x05, 0x85, 0x0D, 0xA5, 0x0F, 0x85, 0x09, 0xA5, 0x11, 0x85, 0x0B, 0x60, +0xA0, 0x00, 0x00, 0xDA, 0xC9, 0x00, 0x00, 0xD0, 0x05, 0xA9, 0x00, 0x00, 0x80, 0x1A, 0x48, 0x29, +0x01, 0x00, 0xF0, 0x22, 0xA7, 0x01, 0x29, 0xFF, 0x00, 0x48, 0xA7, 0x05, 0x29, 0xFF, 0x00, 0xC3, +0x01, 0xF0, 0x0A, 0x68, 0x68, 0xA9, 0x01, 0x00, 0xFA, 0xC9, 0x00, 0x00, 0x60, 0x68, 0x68, 0x3A, +0xF0, 0x11, 0x48, 0xA0, 0x01, 0x00, 0xFA, 0xB7, 0x01, 0xD7, 0x05, 0xD0, 0xE8, 0xC8, 0xC8, 0xCA, +0xCA, 0xD0, 0xF4, 0xA9, 0x00, 0x00, 0x80, 0xE0, 0x0B, 0x3B, 0x5B, 0x64, 0x09, 0xE2, 0x20, 0xAF, +0xD4, 0x0F, 0xE1, 0x04, 0x09, 0xAF, 0x41, 0xC0, 0x00, 0x48, 0x29, 0x08, 0xF0, 0x04, 0xA9, 0x40, +0x04, 0x09, 0x68, 0x29, 0x10, 0x0A, 0x04, 0x09, 0xAF, 0x23, 0xC0, 0x00, 0x48, 0x29, 0x04, 0x0A, +0x0A, 0x04, 0x09, 0xAF, 0x27, 0xC0, 0x00, 0x29, 0x10, 0x4A, 0x4A, 0x04, 0x09, 0x68, 0x29, 0x03, +0x04, 0x09, 0xC2, 0x30, 0x4C, 0x8C, 0xFF, 0xA3, 0x0D, 0x8F, 0xD0, 0x1D, 0xE1, 0xA3, 0x09, 0x8F, +0xD2, 0x1D, 0xE1, 0xA3, 0x0B, 0x8F, 0xD4, 0x1D, 0xE1, 0xA3, 0x07, 0x8F, 0xD6, 0x1D, 0xE1, 0x5C, +0xD8, 0xFF, 0xFE, 0xAF, 0xD0, 0x1D, 0xE1, 0x83, 0x0D, 0xAF, 0xD2, 0x1D, 0xE1, 0x83, 0x09, 0xAF, +0xD4, 0x1D, 0xE1, 0x83, 0x0B, 0xAF, 0xD6, 0x1D, 0xE1, 0x83, 0x07, 0x5C, 0x8B, 0xFF, 0xFE, 0xA2, +0x08, 0x00, 0xA9, 0xDD, 0xFB, 0x48, 0xCA, 0xD0, 0xFC, 0xA2, 0x03, 0x24, 0x22, 0x00, 0x00, 0xE1, +0x68, 0x68, 0x68, 0x68, 0x4C, 0x8B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xDA, 0xA7, 0xFE, 0x00, 0x06, +0xA8, 0xFE, 0x00, 0x06, 0xA8, 0xFE, 0x00, 0x09, 0xA8, 0xFE, 0x00, 0xDA, 0xA7, 0xFE, 0x00, 0x11, +0xA8, 0xFE, 0x00, 0x06, 0xA8, 0xFE, 0x00, 0x06, 0xA8, 0xFE, 0x00, 0x19, 0xA8, 0xFE, 0x00, 0x37, +0xA8, 0xFE, 0x00, 0x3C, 0xA8, 0xFE, 0x00, 0x41, 0xA8, 0xFE, 0x00, 0x5F, 0xA8, 0xFE, 0x00, 0x64, +0xA8, 0xFE, 0x00, 0x69, 0xA8, 0xFE, 0x00, 0x90, 0xA8, 0xFE, 0x00, 0x95, 0xA8, 0xFE, 0x00, 0x9A, +0xA8, 0xFE, 0x00, 0xC1, 0xA8, 0xFE, 0x00, 0xC6, 0xA8, 0xFE, 0x00, 0xCB, 0xA8, 0xFE, 0x00, 0x4B, +0xA9, 0xFE, 0x00, 0x7E, 0xA9, 0xFE, 0x00, 0xA7, 0xA9, 0xFE, 0x00, 0xAA, 0xA9, 0xFE, 0x00, 0xFC, +0xA9, 0xFE, 0x00, 0xFF, 0xA9, 0xFE, 0x00, 0x1E, 0xAA, 0xFE, 0x00, 0x21, 0xAA, 0xFE, 0x00, 0x4C, +0xAA, 0xFE, 0x00, 0x4F, 0xAA, 0xFE, 0x00, 0x7B, 0xAA, 0xFE, 0x00, 0x7E, 0xAA, 0xFE, 0x00, 0x9B, +0xAA, 0xFE, 0x00, 0xE3, 0xAA, 0xFE, 0x00, 0x2F, 0xAB, 0xFE, 0x00, 0x8B, 0xF4, 0x15, 0xE1, 0xAB, +0xAB, 0xA2, 0x0E, 0x00, 0x9E, 0xB0, 0x15, 0xCA, 0xCA, 0x10, 0xF9, 0xA9, 0xFF, 0x80, 0x8D, 0xAA, +0x15, 0x8D, 0xAC, 0x15, 0x8D, 0xAE, 0x15, 0xA9, 0x03, 0x00, 0x8D, 0xB3, 0x15, 0x8D, 0xB7, 0x15, +0x8D, 0xBB, 0x15, 0xAB, 0x4C, 0x8B, 0xFF, 0x4C, 0x8B, 0xFF, 0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, +0x8B, 0xFF, 0xA9, 0xFF, 0xFF, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xA2, 0x00, 0x00, 0x0B, 0x3B, 0x5B, +0x8B, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0xE2, 0x20, 0xA5, 0x09, 0x9D, 0xAB, 0x15, 0xA5, 0x0B, 0x9D, +0xAA, 0x15, 0xAB, 0xC2, 0x20, 0x4C, 0xC3, 0xFF, 0xA2, 0x02, 0x00, 0x80, 0xE0, 0xA2, 0x04, 0x00, +0x80, 0xDB, 0xA2, 0x00, 0x00, 0x0B, 0x3B, 0x5B, 0x8B, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0xE2, 0x20, +0xBD, 0xAB, 0x15, 0x85, 0x09, 0xBD, 0xAA, 0x15, 0x85, 0x0B, 0xC2, 0x20, 0xAB, 0x4C, 0x8C, 0xFF, +0xA2, 0x02, 0x00, 0x80, 0xE0, 0xA2, 0x04, 0x00, 0x80, 0xDB, 0xA2, 0x00, 0x00, 0x0B, 0x8B, 0x3B, +0x5B, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0x8A, 0x0A, 0x0A, 0xA8, 0xE2, 0x20, 0xA5, 0x0E, 0x9D, 0xB0, +0x15, 0xC2, 0x20, 0xA5, 0x0A, 0x99, 0xB3, 0x15, 0xA5, 0x0C, 0x99, 0xB5, 0x15, 0xAB, 0x4C, 0xCE, +0xFF, 0xA2, 0x01, 0x00, 0x80, 0xD7, 0xA2, 0x02, 0x00, 0x80, 0xD2, 0xA2, 0x00, 0x00, 0x0B, 0x8B, +0x3B, 0x5B, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0x8A, 0x0A, 0x0A, 0xA8, 0xE2, 0x20, 0xBD, 0xB0, 0x15, +0x85, 0x0E, 0xC2, 0x20, 0xB9, 0xB3, 0x15, 0x85, 0x0A, 0xB9, 0xB5, 0x15, 0x85, 0x0C, 0xAB, 0x4C, +0x8C, 0xFF, 0xA2, 0x01, 0x00, 0x80, 0xD7, 0xA2, 0x02, 0x00, 0x80, 0xD2, 0x0B, 0x8B, 0xF4, 0x00, +0x00, 0x3B, 0x5B, 0xE2, 0x30, 0xA5, 0x0C, 0xC9, 0x03, 0x90, 0x0A, 0xC2, 0x30, 0xA2, 0x01, 0x0C, +0xAB, 0x2B, 0x4C, 0xBC, 0xFF, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0xA8, 0xB9, 0xB0, 0x15, 0xD0, 0x29, +0x98, 0x0A, 0x0A, 0xAA, 0xC2, 0x20, 0xBD, 0xB3, 0x15, 0xEB, 0x09, 0x00, 0xC0, 0xC0, 0x00, 0xD0, +0x06, 0x8F, 0x38, 0x00, 0x00, 0x80, 0x10, 0xC0, 0x02, 0xD0, 0x08, 0x48, 0xAF, 0x36, 0x00, 0x00, +0x85, 0x01, 0x68, 0x8F, 0x36, 0x00, 0x00, 0xE2, 0x20, 0xA9, 0x00, 0x20, 0xF9, 0xAC, 0x48, 0x48, +0x29, 0x7F, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0x20, 0x6F, 0xAB, 0xFA, 0x68, 0x08, 0x29, 0xC0, 0x00, +0xC9, 0x80, 0x00, 0xD0, 0x0E, 0xAF, 0x36, 0x00, 0x00, 0x8F, 0xBF, 0x15, 0xE1, 0xA5, 0x01, 0x8F, +0x36, 0x00, 0x00, 0x28, 0x68, 0xAB, 0x2B, 0xB0, 0x99, 0x4C, 0xB7, 0xFF, 0x0B, 0x8B, 0x3B, 0x5B, +0xE2, 0x30, 0xA5, 0x0C, 0xC9, 0x03, 0x90, 0x07, 0xA2, 0x01, 0xAB, 0x2B, 0x4C, 0xBC, 0xFF, 0xA8, +0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0xB9, 0xB0, 0x15, 0xF0, 0xEE, 0xA9, 0x04, 0x20, 0xF9, 0xAC, 0xC2, +0x30, 0xA6, 0x0A, 0xDA, 0x20, 0x6F, 0xAB, 0xFA, 0xAB, 0x2B, 0xB0, 0xE0, 0x4C, 0xC2, 0xFF, 0x0B, +0x8B, 0x3B, 0x5B, 0xE2, 0x30, 0xA5, 0x0C, 0xC9, 0x03, 0x90, 0x07, 0xA2, 0x01, 0xAB, 0x2B, 0x4C, +0xC7, 0xFF, 0xA8, 0xA9, 0x03, 0x20, 0xF9, 0xAC, 0xC2, 0x30, 0xA6, 0x0A, 0xDA, 0x20, 0x6F, 0xAB, +0xFA, 0xAB, 0x2B, 0xB0, 0xEA, 0x4C, 0xC2, 0xFF, 0xB8, 0x50, 0x02, 0xE2, 0x40, 0xA3, 0x07, 0x20, +0xB6, 0xA9, 0x5C, 0xBC, 0xFF, 0xFE, 0x70, 0x0D, 0x2F, 0xAC, 0x15, 0xE1, 0x0F, 0xAD, 0x15, 0xE1, +0xA0, 0x01, 0x00, 0x80, 0x0B, 0x2F, 0xAE, 0x15, 0xE1, 0x0F, 0xAF, 0x15, 0xE1, 0xA0, 0x02, 0x00, +0x48, 0x5A, 0xA9, 0x02, 0x00, 0xE2, 0x30, 0x20, 0xF9, 0xAC, 0xC2, 0x30, 0x7A, 0x20, 0x6F, 0xAB, +0xE2, 0x20, 0x98, 0x4A, 0x29, 0x40, 0xB8, 0x08, 0x03, 0x01, 0x83, 0x01, 0x28, 0xC2, 0x20, 0xB0, +0x05, 0xA2, 0x00, 0x00, 0x80, 0x05, 0x8A, 0x09, 0x00, 0x0C, 0xAA, 0x68, 0x60, 0xB8, 0x50, 0x02, +0xE2, 0x40, 0x20, 0x2A, 0xAA, 0xB0, 0x14, 0xA9, 0x0D, 0x00, 0x20, 0xB6, 0xA9, 0xB0, 0x0C, 0x98, +0x29, 0x40, 0x00, 0xF0, 0x06, 0xA9, 0x0A, 0x00, 0x20, 0xB6, 0xA9, 0x5C, 0xC7, 0xFF, 0xFE, 0xB8, +0x50, 0x02, 0xE2, 0x40, 0x20, 0x2A, 0xAA, 0x4C, 0x1B, 0xAA, 0x48, 0x0B, 0x3B, 0x5B, 0xA7, 0x0D, +0x29, 0xFF, 0x00, 0x1A, 0x85, 0x03, 0xA0, 0x01, 0x00, 0xC4, 0x03, 0xF0, 0x0C, 0xB7, 0x0D, 0x5A, +0x20, 0xB6, 0xA9, 0x7A, 0xC8, 0xB0, 0x03, 0x80, 0xF0, 0x18, 0x2B, 0x68, 0x60, 0xB8, 0x50, 0x02, +0xE2, 0x40, 0x0B, 0x3B, 0x5B, 0x08, 0x18, 0xA5, 0x0D, 0x65, 0x0B, 0x85, 0x0D, 0xA5, 0x0F, 0x69, +0x00, 0x00, 0x85, 0x0F, 0x28, 0x64, 0x0B, 0xA4, 0x0B, 0xC4, 0x09, 0xF0, 0x0B, 0xB7, 0x0D, 0x20, +0xB6, 0xA9, 0xB0, 0x04, 0xE6, 0x0B, 0x80, 0xEF, 0x5C, 0xDC, 0xFF, 0xFE, 0xB8, 0x50, 0x02, 0xE2, +0x40, 0x0B, 0x3B, 0x5B, 0xA0, 0x00, 0x00, 0xB7, 0x09, 0x29, 0xFF, 0x00, 0xF0, 0x0A, 0x5A, 0x20, +0xB6, 0xA9, 0x7A, 0xC8, 0xB0, 0x02, 0x80, 0xEF, 0x5C, 0xC6, 0xFF, 0xFE, 0x0B, 0x3B, 0x5B, 0x20, +0xC1, 0xAA, 0xB0, 0x1A, 0x2F, 0xAA, 0x15, 0xE1, 0x0F, 0xAB, 0x15, 0xE1, 0x85, 0x0B, 0xA4, 0x09, +0xF0, 0x09, 0xB8, 0x48, 0xA2, 0x0C, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0xB8, 0xFF, 0x4C, 0xBB, +0xFF, 0xA0, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xE2, 0x30, 0xA9, 0x01, 0x20, 0xF9, 0xAC, 0xC2, 0x30, +0x20, 0x6F, 0xAB, 0xE2, 0x30, 0x98, 0x0A, 0x29, 0x40, 0xB8, 0x08, 0x03, 0x01, 0x83, 0x01, 0x28, +0xC2, 0x30, 0x68, 0x60, 0x0B, 0x3B, 0x5B, 0x08, 0x18, 0xA5, 0x0D, 0x65, 0x0F, 0x85, 0x0F, 0xA9, +0x00, 0x00, 0x65, 0x11, 0x85, 0x11, 0x28, 0x64, 0x0D, 0x48, 0xA5, 0x09, 0x48, 0x22, 0x2B, 0xAB, +0xFE, 0xB0, 0x24, 0x8B, 0x18, 0xE6, 0x0D, 0xA6, 0x0F, 0xE2, 0x20, 0xA5, 0x11, 0x48, 0xAB, 0xA3, +0x02, 0x9D, 0x00, 0x00, 0xC2, 0x20, 0xAB, 0x68, 0xE6, 0x0F, 0xD0, 0x02, 0xE6, 0x11, 0xA5, 0x0D, +0xC5, 0x0B, 0xD0, 0xD5, 0x4C, 0x97, 0xFF, 0x68, 0x4C, 0x9A, 0xFF, 0x22, 0x9C, 0xAA, 0xFE, 0x6B, +0x0B, 0x3B, 0x5B, 0x64, 0x13, 0x48, 0xA5, 0x09, 0x48, 0x22, 0x2B, 0xAB, 0xFE, 0x68, 0xB0, 0x2C, +0xE2, 0x20, 0xC5, 0x0B, 0xC2, 0x20, 0xF0, 0x21, 0xEB, 0xA6, 0x0F, 0xE2, 0x20, 0x8B, 0xA5, 0x11, +0x48, 0xAB, 0xEB, 0x9D, 0x00, 0x00, 0xAB, 0xC2, 0x20, 0xE6, 0x0F, 0xD0, 0x02, 0xE6, 0x11, 0xE6, +0x13, 0xF0, 0x09, 0xA5, 0x13, 0xC5, 0x0D, 0xD0, 0xCC, 0x4C, 0x97, 0xFF, 0x4C, 0x9A, 0xFF, 0x8B, +0x0B, 0xE2, 0x20, 0x48, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0xB9, 0xB0, 0x15, 0xC9, 0x02, 0xD0, 0x52, +0xE2, 0x10, 0x98, 0x0A, 0x0A, 0xAA, 0xC2, 0x10, 0xA3, 0x01, 0x48, 0x29, 0x07, 0x83, 0x01, 0x0A, +0x18, 0x63, 0x01, 0x83, 0x01, 0xC2, 0x20, 0x29, 0xFF, 0x00, 0x18, 0x7D, 0xB3, 0x15, 0xA8, 0xA9, +0x00, 0x00, 0x7D, 0xB5, 0x15, 0xAA, 0x4B, 0xF4, 0xC5, 0xAB, 0xE2, 0x20, 0x8A, 0x48, 0x5A, 0xC2, +0x20, 0x38, 0xA3, 0x01, 0xE9, 0x01, 0x00, 0x83, 0x01, 0xE2, 0x20, 0xA3, 0x03, 0xE9, 0x00, 0x83, +0x03, 0xC2, 0x20, 0xA3, 0x0E, 0x6B, 0x83, 0x08, 0xE2, 0x20, 0x68, 0x68, 0xA8, 0xC2, 0x20, 0x2B, +0xAB, 0x60, 0xAF, 0x68, 0xC0, 0x00, 0x48, 0xA9, 0x08, 0x8F, 0x68, 0xC0, 0x00, 0xF4, 0x00, 0x00, +0x3B, 0x5B, 0xA9, 0x00, 0xEB, 0x98, 0x0A, 0x0A, 0xA8, 0xA5, 0x04, 0x29, 0x0F, 0x0A, 0xAA, 0x24, +0x04, 0xA5, 0x04, 0x3A, 0xC2, 0x30, 0xD0, 0x05, 0xA9, 0x0C, 0xFD, 0x80, 0x29, 0xE2, 0x20, 0x3A, +0xC2, 0x20, 0xD0, 0x05, 0xA9, 0xED, 0xFD, 0x80, 0x1D, 0xE2, 0x20, 0x29, 0x0F, 0xC2, 0x20, 0xF0, +0xF3, 0xB9, 0xB3, 0x15, 0xEB, 0x09, 0x00, 0xC0, 0xE2, 0x20, 0x4B, 0xAB, 0x1D, 0xD9, 0xAC, 0x50, +0x05, 0xAA, 0xBF, 0x00, 0x00, 0x00, 0xC2, 0x20, 0xF4, 0xA4, 0xAC, 0x3A, 0x48, 0x1A, 0xEB, 0xAA, +0x0A, 0x0A, 0x0A, 0x0A, 0xA8, 0xA3, 0x01, 0x1A, 0x29, 0x00, 0xFF, 0xDA, 0x5A, 0xAA, 0x50, 0x2A, +0xE2, 0x20, 0xBF, 0x05, 0x00, 0x00, 0xEB, 0xBF, 0x07, 0x00, 0x00, 0xC2, 0x20, 0xC9, 0x18, 0x38, +0xF0, 0x36, 0xC2, 0x30, 0x68, 0x68, 0x68, 0x68, 0x68, 0xE2, 0x30, 0x68, 0x8F, 0x68, 0xC0, 0x00, +0x68, 0x2B, 0xAB, 0xC2, 0x30, 0xA9, 0x01, 0x0C, 0x38, 0x60, 0xE2, 0x20, 0xA5, 0x04, 0x29, 0x0F, +0x3A, 0xF0, 0x15, 0x3A, 0xF0, 0x12, 0xA0, 0x0A, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0xD3, 0xDF, +0x00, 0x00, 0x00, 0xD0, 0xCD, 0x88, 0x10, 0xF7, 0xE2, 0x20, 0x7A, 0xFA, 0x24, 0x04, 0xC2, 0x20, +0x10, 0x0E, 0xAF, 0x36, 0x00, 0x00, 0x85, 0x01, 0xAF, 0xBF, 0x15, 0xE1, 0x8F, 0x36, 0x00, 0x00, +0xA5, 0x0A, 0x82, 0xB9, 0xEF, 0x85, 0x0A, 0x08, 0xE2, 0x20, 0xA5, 0x04, 0xC9, 0x4B, 0xF0, 0x03, +0x28, 0x18, 0x08, 0xE2, 0x20, 0x24, 0x04, 0xC2, 0x20, 0x10, 0x0E, 0xAF, 0x36, 0x00, 0x00, 0x8F, +0xBF, 0x15, 0xE1, 0xA5, 0x01, 0x8F, 0x36, 0x00, 0x00, 0x28, 0x68, 0xE2, 0x20, 0x68, 0x8F, 0x68, +0xC0, 0x00, 0x68, 0xA8, 0xC2, 0x30, 0x2B, 0xAB, 0x60, 0x00, 0xC0, 0x0C, 0xFD, 0xED, 0xFD, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x0E, 0xC0, 0x0F, 0xC0, 0x10, +0xC0, 0x12, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xF4, 0x15, 0xE1, 0xAB, 0xAB, 0x48, +0xB9, 0xB0, 0x15, 0xF0, 0x07, 0x3A, 0xD0, 0x04, 0x68, 0x09, 0x48, 0x48, 0xC0, 0x02, 0xD0, 0x04, +0x68, 0x09, 0x80, 0x48, 0x68, 0xAB, 0x60, 0x08, 0x78, 0xF4, 0x12, 0x00, 0xF4, 0xFE, 0x00, 0xF4, +0xB9, 0xAD, 0xA2, 0x03, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xA9, 0xFF, 0x00, 0x8F, 0x67, 0x1D, 0xE0, +0xA9, 0xF7, 0xB7, 0x8F, 0x8A, 0x1D, 0xE0, 0xA9, 0x00, 0x00, 0x8F, 0x7C, 0x1D, 0xE0, 0xA9, 0x08, +0x00, 0x8F, 0x88, 0x1D, 0xE0, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x50, 0xA2, 0x03, 0x20, 0x22, 0x00, +0x00, 0xE1, 0x68, 0x8F, 0x82, 0x1D, 0xE0, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xF4, 0x20, 0x00, 0xAF, 0x82, 0x1D, 0xE0, 0x48, 0xF4, 0x08, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0xA2, 0x02, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x2F, 0x68, 0x8F, 0x84, 0x1D, 0xE0, 0x68, +0x8F, 0x86, 0x1D, 0xE0, 0xF4, 0xFE, 0x00, 0xF4, 0x29, 0xB8, 0x22, 0xAB, 0xAD, 0xFE, 0xF4, 0xFE, +0x00, 0xF4, 0x29, 0xB8, 0xF4, 0xFE, 0x00, 0xF4, 0xC1, 0xB4, 0xA2, 0x05, 0x13, 0x22, 0x00, 0x00, +0xE1, 0x22, 0x6E, 0xC0, 0xFF, 0x28, 0x4C, 0x8B, 0xFF, 0x00, 0x11, 0x22, 0x57, 0xB8, 0xFE, 0x6B, +0xE2, 0x30, 0x22, 0xB9, 0xAD, 0xFE, 0xC2, 0x30, 0x6B, 0x08, 0xAF, 0x67, 0x1D, 0xE0, 0x1A, 0xF0, +0x03, 0x82, 0x83, 0x00, 0xC2, 0x30, 0xAF, 0xFF, 0x00, 0xE1, 0xF0, 0x25, 0xF4, 0x00, 0x00, 0xF4, +0xFE, 0x00, 0xF4, 0xB0, 0xAD, 0xA2, 0x07, 0x09, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xE2, 0x30, 0xAF, +0x67, 0x1D, 0xE0, 0x3A, 0xC9, 0xFF, 0xF0, 0x02, 0xA9, 0xFF, 0x8F, 0x67, 0x1D, 0xE0, 0xAB, 0x18, +0x6B, 0x3B, 0x8F, 0x9C, 0x1D, 0xE0, 0x8B, 0xA2, 0x00, 0x01, 0xA0, 0x00, 0x03, 0xA9, 0xFF, 0x00, +0x54, 0xE0, 0x00, 0xAB, 0xA9, 0xFB, 0x01, 0x1B, 0xA2, 0x05, 0x0B, 0x22, 0x00, 0x00, 0xE1, 0xA2, +0x05, 0x11, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x05, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0xA9, 0xFF, 0x00, +0x8F, 0x67, 0x1D, 0xE0, 0xE2, 0x30, 0x8B, 0x68, 0x8F, 0x00, 0x1D, 0xE0, 0xC2, 0x30, 0xA2, 0x00, +0x03, 0xA0, 0x00, 0x01, 0xA9, 0xFF, 0x00, 0x54, 0x00, 0xE0, 0xAF, 0x9C, 0x1D, 0xE0, 0x1B, 0xE2, +0x30, 0xAF, 0x00, 0x1D, 0xE0, 0x48, 0xAB, 0x28, 0x18, 0x6B, 0x4C, 0x8B, 0xFF, 0x4C, 0x8B, 0xFF, +0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xE2, 0x30, 0xA9, 0xFF, 0x8F, 0x67, 0x1D, 0xE0, +0xC2, 0x30, 0x4C, 0x8B, 0xFF, 0xA9, 0xFF, 0xFF, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0x1C, 0x00, 0x00, +0x00, 0x16, 0xAD, 0xFE, 0x00, 0x49, 0xAE, 0xFE, 0x00, 0x4C, 0xAE, 0xFE, 0x00, 0x4F, 0xAE, 0xFE, +0x00, 0x57, 0xAE, 0xFE, 0x00, 0x64, 0xAE, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, +0x00, 0xDC, 0xAE, 0xFE, 0x00, 0x17, 0xAF, 0xFE, 0x00, 0xCA, 0xAF, 0xFE, 0x00, 0x46, 0xB2, 0xFE, +0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x56, 0xB8, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, +0x00, 0xE3, 0xB4, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x39, 0xBA, 0xFE, 0x00, 0x96, 0xBA, 0xFE, +0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, +0x00, 0x8A, 0xFF, 0xFE, 0x00, 0xBD, 0xB3, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8B, 0x20, 0xE5, +0xAE, 0xAB, 0x4C, 0x8B, 0xFF, 0xC2, 0x30, 0xA2, 0x00, 0x04, 0xA0, 0x00, 0x0C, 0xA9, 0xFF, 0x03, +0x54, 0xE0, 0x00, 0xA2, 0x00, 0x04, 0xA0, 0x00, 0x10, 0xA9, 0xFF, 0x03, 0x54, 0xE0, 0x01, 0xA2, +0x00, 0x04, 0xA0, 0x00, 0x14, 0xA9, 0xFF, 0x03, 0x54, 0xE0, 0xE0, 0xA2, 0x00, 0x04, 0xA0, 0x00, +0x18, 0xA9, 0xFF, 0x03, 0x54, 0xE0, 0xE1, 0x60, 0x8B, 0x20, 0x20, 0xAF, 0xAB, 0x4C, 0x8B, 0xFF, +0xC2, 0x30, 0xA2, 0x07, 0x00, 0xEC, 0x6A, 0x1D, 0xF0, 0x08, 0xE0, 0x03, 0x00, 0xF0, 0x03, 0x20, +0x66, 0xAF, 0xCA, 0xD0, 0xF0, 0xA2, 0x00, 0x0C, 0xA0, 0x00, 0x04, 0xA9, 0xFF, 0x03, 0x54, 0x00, +0xE0, 0xA2, 0x00, 0x10, 0xA0, 0x00, 0x04, 0xA9, 0xFF, 0x03, 0x54, 0x01, 0xE0, 0xA2, 0x00, 0x14, +0xA0, 0x00, 0x04, 0xA9, 0xFF, 0x03, 0x54, 0xE0, 0xE0, 0xA2, 0x00, 0x18, 0xA0, 0x00, 0x04, 0xA9, +0xFF, 0x03, 0x54, 0xE1, 0xE0, 0x60, 0xE2, 0x30, 0xBF, 0x78, 0x04, 0x00, 0x9F, 0x78, 0x14, 0xE0, +0x9F, 0x78, 0x0C, 0xE0, 0xBF, 0xF8, 0x04, 0x00, 0x9F, 0xF8, 0x14, 0xE0, 0x9F, 0xF8, 0x0C, 0xE0, +0xBF, 0x78, 0x05, 0x00, 0x9F, 0x78, 0x15, 0xE0, 0x9F, 0x78, 0x0D, 0xE0, 0xBF, 0xF8, 0x05, 0x00, +0x9F, 0xF8, 0x15, 0xE0, 0x9F, 0xF8, 0x0D, 0xE0, 0xBF, 0x78, 0x06, 0x00, 0x9F, 0x78, 0x16, 0xE0, +0x9F, 0x78, 0x0E, 0xE0, 0xBF, 0xF8, 0x06, 0x00, 0x9F, 0xF8, 0x16, 0xE0, 0x9F, 0xF8, 0x0E, 0xE0, +0xBF, 0x78, 0x07, 0x00, 0x9F, 0x78, 0x17, 0xE0, 0x9F, 0x78, 0x0F, 0xE0, 0xBF, 0xF8, 0x07, 0x00, +0x9F, 0xF8, 0x17, 0xE0, 0x9F, 0xF8, 0x0F, 0xE0, 0xC2, 0x30, 0x60, 0xE2, 0x30, 0x8B, 0x68, 0x8F, +0x00, 0x1D, 0xE0, 0xA9, 0xE0, 0x48, 0xAB, 0xA9, 0x00, 0x8D, 0x02, 0x1D, 0xAD, 0x68, 0xC0, 0x8D, +0x03, 0x1D, 0xA9, 0x0C, 0x8D, 0x68, 0xC0, 0x8B, 0xAD, 0x02, 0x1D, 0xC2, 0x30, 0x10, 0x03, 0x4C, +0x5F, 0xB1, 0xF0, 0x08, 0xA2, 0xC3, 0x00, 0xA0, 0x20, 0x1D, 0x80, 0x06, 0xA2, 0xC3, 0x00, 0xA0, +0x39, 0x1D, 0xA9, 0x0C, 0x00, 0x54, 0xE0, 0xE1, 0xE2, 0x30, 0xAC, 0x02, 0x1D, 0xAF, 0xD7, 0x00, +0xE1, 0x99, 0x61, 0x1D, 0xC2, 0x30, 0x98, 0xF0, 0x08, 0xA2, 0x08, 0x01, 0xA0, 0x2D, 0x1D, 0x80, +0x06, 0xA2, 0x08, 0x01, 0xA0, 0x4C, 0x1D, 0xA9, 0x13, 0x00, 0x54, 0xE0, 0xE1, 0xAB, 0x0B, 0x68, +0x8D, 0x63, 0x1D, 0xA9, 0x00, 0x00, 0x48, 0x2B, 0xE2, 0x30, 0xAD, 0x18, 0xC0, 0x8D, 0x04, 0x1D, +0xAD, 0x29, 0xC0, 0x8D, 0x18, 0x1D, 0xC2, 0x30, 0xAD, 0x1A, 0xC0, 0x8D, 0x1A, 0x1D, 0xAD, 0x1C, +0xC0, 0x8D, 0x1C, 0x1D, 0xAD, 0x1E, 0xC0, 0x8D, 0x1E, 0x1D, 0x20, 0xE5, 0xAE, 0xA2, 0x00, 0x00, +0xA0, 0x00, 0x1C, 0xA9, 0xFF, 0x00, 0x54, 0xE0, 0x00, 0x20, 0x61, 0xB1, 0xAF, 0x34, 0x01, 0xE1, +0x8D, 0x16, 0x1D, 0xE2, 0x30, 0x38, 0x22, 0x94, 0x00, 0xE1, 0xAD, 0x17, 0xC0, 0x8D, 0x65, 0x1D, +0xAD, 0x29, 0xC0, 0x29, 0x7F, 0x8D, 0x29, 0xC0, 0x8D, 0x51, 0xC0, 0x8D, 0x52, 0xC0, 0x8D, 0x54, +0xC0, 0xA9, 0xFF, 0x8F, 0x32, 0x00, 0x00, 0xC2, 0x30, 0x48, 0x48, 0x48, 0xA2, 0x0C, 0x13, 0x22, +0x00, 0x00, 0xE1, 0x68, 0x8D, 0xA2, 0x1D, 0x68, 0x8D, 0xA4, 0x1D, 0x68, 0x8D, 0xA6, 0x1D, 0x48, +0x48, 0xA2, 0x0C, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8D, 0x9E, 0x1D, 0x68, 0x8D, 0xA0, 0x1D, +0x48, 0x48, 0x48, 0xA2, 0x0C, 0x12, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8D, 0xB4, 0x1D, 0x68, 0x8D, +0xB6, 0x1D, 0x68, 0x8D, 0xB8, 0x1D, 0x48, 0x48, 0xA2, 0x0C, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0x68, +0x8D, 0xBA, 0x1D, 0x68, 0x8D, 0xBC, 0x1D, 0xF4, 0xFF, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x0C, 0x0A, +0x22, 0x00, 0x00, 0xE1, 0x90, 0x02, 0x00, 0x01, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x03, +0x00, 0xA2, 0x0C, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x02, 0x00, 0x02, 0xE2, 0x30, 0xA2, 0x00, +0xAD, 0x05, 0xC3, 0xC9, 0x38, 0xD0, 0x0C, 0xAD, 0x07, 0xC3, 0xC9, 0x18, 0xD0, 0x05, 0xE8, 0xD0, +0xEF, 0x80, 0x05, 0x8D, 0x0A, 0xC0, 0x80, 0xE8, 0xC2, 0x30, 0xF4, 0x01, 0x00, 0xA2, 0x0C, 0x15, +0x22, 0x00, 0x00, 0xE1, 0x90, 0x02, 0x00, 0x03, 0xF4, 0x00, 0x00, 0xF4, 0x19, 0x00, 0xA2, 0x03, +0x0C, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8D, 0x66, 0x1D, 0xD0, 0x0A, 0xF4, 0x11, 0x00, 0xA2, 0x0C, +0x18, 0x22, 0x00, 0x00, 0xE1, 0xA9, 0x00, 0x00, 0x48, 0xAB, 0xAB, 0x58, 0x4C, 0x8B, 0xFF, 0x00, +0xFF, 0xA9, 0x00, 0xC7, 0x8D, 0x6C, 0x1D, 0xAD, 0x6C, 0x1D, 0x48, 0xE2, 0x30, 0xA0, 0x0C, 0xB3, +0x01, 0xC9, 0x20, 0xD0, 0x08, 0xA0, 0xFB, 0xB3, 0x01, 0xC9, 0xD6, 0xF0, 0x1B, 0xC2, 0x30, 0x68, +0xAD, 0x6C, 0x1D, 0xEB, 0x3A, 0xC9, 0xC0, 0x00, 0xF0, 0x06, 0xEB, 0x8D, 0x6C, 0x1D, 0x80, 0xD7, +0xA9, 0xFF, 0xFF, 0x8D, 0x68, 0x1D, 0x80, 0x6B, 0xC2, 0x30, 0x68, 0xEB, 0x29, 0x0F, 0x00, 0x8D, +0x6A, 0x1D, 0x18, 0x69, 0xF8, 0x07, 0xAA, 0xE2, 0x20, 0xB5, 0x00, 0xF0, 0x20, 0x8D, 0x68, 0x1D, +0xE2, 0x30, 0xAF, 0xE0, 0x00, 0xE1, 0x48, 0xAD, 0x6A, 0x1D, 0x8F, 0xE0, 0x00, 0xE1, 0xC2, 0x30, +0xA9, 0x00, 0x00, 0x48, 0xA2, 0x03, 0x19, 0x22, 0x00, 0x00, 0xE1, 0x80, 0x0A, 0xC2, 0x30, 0xA9, +0x00, 0x00, 0x8D, 0x68, 0x1D, 0x80, 0x2C, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xA2, 0x03, 0x1D, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8D, 0x0B, 0x1D, 0x68, 0x8D, +0x07, 0x1D, 0x68, 0x8D, 0x09, 0x1D, 0x68, 0x8D, 0x05, 0x1D, 0xE2, 0x30, 0x68, 0x8F, 0xE0, 0x00, +0xE1, 0xC2, 0x30, 0x60, 0xAD, 0x68, 0x1D, 0x30, 0x3D, 0xF0, 0x3B, 0xE2, 0x30, 0xAF, 0xE0, 0x00, +0xE1, 0x48, 0xAD, 0x6A, 0x1D, 0x8F, 0xE0, 0x00, 0xE1, 0xC2, 0x30, 0xAD, 0x68, 0x1D, 0x48, 0xA2, +0x03, 0x19, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0x05, 0x1D, 0x48, 0xAD, 0x09, 0x1D, 0x48, 0xAD, 0x07, +0x1D, 0x48, 0xAD, 0x0B, 0x1D, 0x48, 0xA2, 0x03, 0x1C, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x68, +0x8F, 0xE0, 0x00, 0xE1, 0xC2, 0x30, 0x60, 0x78, 0xE2, 0x30, 0xA9, 0xE0, 0x48, 0xAB, 0xAD, 0x04, +0x1D, 0x30, 0x05, 0x8D, 0x00, 0xC0, 0x80, 0x03, 0x8D, 0x01, 0xC0, 0xAD, 0x1F, 0x1D, 0x30, 0x05, +0x8D, 0x0C, 0xC0, 0x80, 0x03, 0x8D, 0x0D, 0xC0, 0x8B, 0xAD, 0x02, 0x1D, 0xC2, 0x30, 0xF0, 0x08, +0xA2, 0x20, 0x1D, 0xA0, 0xC3, 0x00, 0x80, 0x06, 0xA2, 0x39, 0x1D, 0xA0, 0xC3, 0x00, 0xA9, 0x0C, +0x00, 0x54, 0xE1, 0xE0, 0xE2, 0x30, 0xAB, 0xAC, 0x02, 0x1D, 0xB9, 0x61, 0x1D, 0x8F, 0xD7, 0x00, +0xE1, 0x8B, 0xC2, 0x30, 0x98, 0xF0, 0x08, 0xA2, 0x2D, 0x1D, 0xA0, 0x08, 0x01, 0x80, 0x06, 0xA2, +0x4C, 0x1D, 0xA0, 0x08, 0x01, 0xA9, 0x13, 0x00, 0x54, 0xE1, 0xE0, 0x20, 0x20, 0xAF, 0xA2, 0x00, +0x1C, 0xA0, 0x00, 0x00, 0xA9, 0xFF, 0x00, 0x54, 0x00, 0xE0, 0xAB, 0x20, 0x04, 0xB2, 0xAD, 0x16, +0x1D, 0x8F, 0x34, 0x01, 0xE1, 0xAD, 0x63, 0x1D, 0x48, 0x2B, 0xE2, 0x30, 0xAD, 0x18, 0x1D, 0x29, +0xC0, 0x0D, 0x29, 0xC0, 0x8D, 0x29, 0xC0, 0xAD, 0x1E, 0x1D, 0x10, 0x05, 0x8D, 0x0F, 0xC0, 0x80, +0x03, 0x8D, 0x0E, 0xC0, 0xAD, 0x1A, 0x1D, 0x10, 0x05, 0x8D, 0x51, 0xC0, 0x80, 0x03, 0x8D, 0x50, +0xC0, 0xAD, 0x1B, 0x1D, 0x10, 0x05, 0x8D, 0x53, 0xC0, 0x80, 0x03, 0x8D, 0x52, 0xC0, 0xAD, 0x1C, +0x1D, 0x10, 0x05, 0x8D, 0x55, 0xC0, 0x80, 0x03, 0x8D, 0x54, 0xC0, 0xAD, 0x1D, 0x1D, 0x10, 0x05, +0x8D, 0x57, 0xC0, 0x80, 0x03, 0x8D, 0x56, 0xC0, 0xAD, 0x65, 0x1D, 0x10, 0x05, 0x8D, 0x0B, 0xC0, +0x80, 0x4B, 0x8D, 0x0A, 0xC0, 0xC2, 0x30, 0xAD, 0xA6, 0x1D, 0x48, 0xAD, 0xA4, 0x1D, 0x48, 0xAD, +0xA2, 0x1D, 0x48, 0xA2, 0x0C, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0xA0, 0x1D, 0x48, 0xAD, 0x9E, +0x1D, 0x48, 0xA2, 0x0C, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0xB8, 0x1D, 0x48, 0xAD, 0xB6, 0x1D, +0x48, 0xAD, 0xB4, 0x1D, 0x48, 0xA2, 0x0C, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0xBC, 0x1D, 0x48, +0xAD, 0xBA, 0x1D, 0x48, 0xA2, 0x0C, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xAD, 0x03, 0x1D, +0x8D, 0x68, 0xC0, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0xF4, 0x20, 0x00, 0xA2, 0x03, 0x0C, 0x22, 0x00, +0x00, 0xE1, 0x68, 0xE2, 0x30, 0xD0, 0x0C, 0xAF, 0x1A, 0x01, 0xE1, 0x29, 0x7F, 0x8F, 0x1A, 0x01, +0xE1, 0x80, 0x0A, 0xAF, 0x1A, 0x01, 0xE1, 0x09, 0x80, 0x8F, 0x1A, 0x01, 0xE1, 0xC2, 0x30, 0xF4, +0x00, 0x00, 0xF4, 0x1E, 0x00, 0xA2, 0x03, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xE2, 0x30, 0x8F, +0xCA, 0x00, 0xE1, 0xAF, 0x00, 0x1D, 0xE0, 0x48, 0xAB, 0xC2, 0x30, 0x4C, 0x8B, 0xFF, 0x08, 0x78, +0xA3, 0x08, 0xC9, 0x0A, 0x00, 0xD0, 0x1F, 0xA9, 0x04, 0xB8, 0x8F, 0x8A, 0x1D, 0xE0, 0xE2, 0x30, +0x22, 0xB9, 0xAD, 0xFE, 0xC2, 0x30, 0xA9, 0xF7, 0xB7, 0x8F, 0x8A, 0x1D, 0xE0, 0xA9, 0x01, 0x00, +0x83, 0x18, 0x28, 0x4C, 0xE9, 0xFF, 0xA9, 0x00, 0x00, 0x83, 0x18, 0x28, 0x4C, 0xE9, 0xFF, 0xA0, +0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, +0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, +0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xA0, 0x00, 0x5A, 0xA0, 0x41, 0xA0, 0xC4, 0xE5, 0xF3, 0xEB, +0xA0, 0xC1, 0xE3, 0xE3, 0xE5, 0xF3, 0xF3, 0xEF, 0xF2, 0xE9, 0xE5, 0xF3, 0xA0, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5F, +0x00, 0x5A, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, +0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, +0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x5F, 0x00, 0x5A, 0xFF, 0x24, 0xA0, 0x5F, 0x00, +0x5A, 0xA0, 0xD3, 0xE5, 0xEC, 0xE5, 0xE3, 0xF4, 0xBA, 0xA0, 0x4A, 0xA0, 0x4B, 0xA0, 0xA0, 0xA0, +0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xCF, 0xF0, +0xE5, 0xEE, 0xBA, 0xA0, 0x4D, 0xA0, 0xA0, 0x5F, 0x00, 0xA0, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, +0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, +0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, +0x00, 0x18, 0xB4, 0xFE, 0x00, 0xD1, 0xB4, 0xFE, 0x00, 0xDF, 0xB4, 0xFE, 0x00, 0x70, 0xB4, 0xFE, +0x00, 0xC3, 0xEF, 0xEE, 0xF4, 0xF2, 0xEF, 0xEC, 0xA0, 0xD0, 0xE1, 0xEE, 0xE5, 0xEC, 0x00, 0xD1, +0xF5, 0xE9, 0xF4, 0x00, 0x8B, 0xF4, 0xE0, 0xE0, 0xAB, 0xAB, 0xF4, 0xFF, 0x00, 0xF4, 0x00, 0x00, +0xA2, 0x0C, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x02, 0x00, 0x01, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0xF4, 0x03, 0x00, 0xA2, 0x0C, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x02, 0x00, 0x02, 0xE2, +0x30, 0xA2, 0x00, 0xAD, 0x05, 0xC3, 0xC9, 0x38, 0xD0, 0x0C, 0xAD, 0x07, 0xC3, 0xC9, 0x18, 0xD0, +0x05, 0xE8, 0xD0, 0xEF, 0x80, 0x05, 0x8D, 0x0A, 0xC0, 0x80, 0xE8, 0xA9, 0xFF, 0x8F, 0x32, 0x00, +0x00, 0xC2, 0x30, 0xF4, 0x01, 0x00, 0xA2, 0x0C, 0x15, 0x22, 0x00, 0x00, 0xE1, 0x90, 0x02, 0x00, +0x03, 0xF4, 0x00, 0x00, 0xF4, 0x19, 0x00, 0xA2, 0x03, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8D, +0x66, 0x1D, 0x20, 0x97, 0xB7, 0xA9, 0x0C, 0x00, 0x20, 0x75, 0xB7, 0xA9, 0x1B, 0x00, 0x20, 0x75, +0xB7, 0xAD, 0x66, 0x1D, 0xD0, 0x18, 0xA9, 0x11, 0x00, 0x20, 0x75, 0xB7, 0xA9, 0x00, 0x00, 0x8D, +0x72, 0x1D, 0x8D, 0x76, 0x1D, 0x8D, 0x7E, 0x1D, 0xA9, 0x27, 0x00, 0x8D, 0x80, 0x1D, 0x20, 0x4A, +0xB7, 0xF4, 0xFE, 0x00, 0xF4, 0xEF, 0xB3, 0xA2, 0x0C, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x20, 0x6E, +0xB7, 0xAD, 0xAC, 0x1D, 0x85, 0x3C, 0xAD, 0xAE, 0x1D, 0x85, 0x3E, 0xA0, 0x02, 0x00, 0xB7, 0x3C, +0x48, 0xA7, 0x3C, 0x48, 0xA2, 0x0C, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x20, 0x6E, 0xB7, 0xF4, 0xFE, +0x00, 0xF4, 0x41, 0xB4, 0xA2, 0x0C, 0x20, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0x7E, 0x1D, 0x8D, 0x72, +0x1D, 0x20, 0x6E, 0xB7, 0xF4, 0x13, 0x00, 0xFA, 0xCA, 0x30, 0x29, 0xDA, 0xF4, 0x5A, 0x00, 0xA2, +0x0C, 0x18, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0x80, 0x1D, 0x8D, 0x72, 0x1D, 0x20, 0x4A, 0xB7, 0xF4, +0x5F, 0x00, 0xA2, 0x0C, 0x18, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0x7E, 0x1D, 0x8D, 0x72, 0x1D, 0x20, +0x6E, 0xB7, 0x80, 0xD3, 0xAD, 0xAC, 0x1D, 0x85, 0x3C, 0xAD, 0xAE, 0x1D, 0x85, 0x3E, 0xA0, 0x0E, +0x00, 0xB7, 0x3C, 0x48, 0x88, 0x88, 0xB7, 0x3C, 0x48, 0xA2, 0x0C, 0x20, 0x22, 0x00, 0x00, 0xE1, +0x20, 0x6E, 0xB7, 0xF4, 0xFE, 0x00, 0xF4, 0x99, 0xB4, 0xA2, 0x0C, 0x20, 0x22, 0x00, 0x00, 0xE1, +0xA9, 0x18, 0x00, 0x20, 0x75, 0xB7, 0xA9, 0xFF, 0x00, 0x8D, 0xB0, 0x1D, 0x18, 0xAD, 0x76, 0x1D, +0x69, 0x02, 0x00, 0x8D, 0x72, 0x1D, 0x18, 0xAD, 0x78, 0x1D, 0x69, 0x04, 0x00, 0x8D, 0x74, 0x1D, +0x8D, 0x6E, 0x1D, 0x20, 0x4A, 0xB7, 0xAD, 0x7C, 0x1D, 0x18, 0x69, 0x05, 0x00, 0xCD, 0x7A, 0x1D, +0x90, 0x03, 0xAD, 0x7A, 0x1D, 0x8D, 0x70, 0x1D, 0xF4, 0xFF, 0x00, 0xF4, 0x80, 0x00, 0xA2, 0x0C, +0x0A, 0x22, 0x00, 0x00, 0xE1, 0x20, 0x11, 0xB9, 0x62, 0x05, 0x00, 0xAD, 0x8A, 0x1D, 0x3A, 0x48, +0x60, 0x29, 0x7F, 0x00, 0xC9, 0x0D, 0x00, 0xD0, 0x03, 0x4C, 0xCB, 0xB7, 0xC9, 0x0B, 0x00, 0xF0, +0x60, 0xC9, 0x0A, 0x00, 0xF0, 0x11, 0xC9, 0x1B, 0x00, 0xD0, 0x03, 0x82, 0x8E, 0x00, 0xA9, 0x07, +0x00, 0x20, 0x75, 0xB7, 0x82, 0xD1, 0xFF, 0xC2, 0x30, 0x20, 0x4A, 0xB7, 0xAC, 0xB0, 0x1D, 0xA9, +0x00, 0x00, 0x20, 0x62, 0xB9, 0xAD, 0xB0, 0x1D, 0xC9, 0xFF, 0x00, 0xD0, 0x0E, 0xAD, 0x6E, 0x1D, +0x8D, 0x74, 0x1D, 0x20, 0x4A, 0xB7, 0xA9, 0x00, 0x00, 0x80, 0x19, 0x1A, 0xCD, 0x7C, 0x1D, 0x90, +0x05, 0xF0, 0x03, 0xA9, 0xFF, 0x00, 0x48, 0xAD, 0x74, 0x1D, 0x1A, 0x8D, 0x74, 0x1D, 0x20, 0x4A, +0xB7, 0x68, 0x80, 0x00, 0x8D, 0xB0, 0x1D, 0xA8, 0xA9, 0xFF, 0x00, 0x20, 0x62, 0xB9, 0x82, 0x87, +0xFF, 0xC2, 0x30, 0x20, 0x4A, 0xB7, 0xAC, 0xB0, 0x1D, 0xA9, 0x00, 0x00, 0x20, 0x62, 0xB9, 0xAD, +0xB0, 0x1D, 0xD0, 0x0E, 0xAD, 0x70, 0x1D, 0x8D, 0x74, 0x1D, 0x20, 0x4A, 0xB7, 0xA9, 0xFF, 0x00, +0x80, 0xD2, 0xAD, 0x74, 0x1D, 0x3A, 0x8D, 0x74, 0x1D, 0x20, 0x4A, 0xB7, 0xAD, 0xB0, 0x1D, 0xC9, +0xFF, 0x00, 0xD0, 0x05, 0xAD, 0x7C, 0x1D, 0x80, 0xBB, 0x3A, 0x80, 0xB8, 0x20, 0x4A, 0xB7, 0xAC, +0xB0, 0x1D, 0xA9, 0x00, 0x00, 0x20, 0x62, 0xB9, 0xAD, 0x70, 0x1D, 0x8D, 0x74, 0x1D, 0x20, 0x4A, +0xB7, 0xA9, 0xFF, 0x00, 0x8D, 0xB0, 0x1D, 0xA8, 0x20, 0x62, 0xB9, 0x82, 0x2A, 0xFF, 0xE2, 0x30, +0xA9, 0xFF, 0x85, 0x32, 0xC2, 0x30, 0xAB, 0x4C, 0x8B, 0xFF, 0xE2, 0x30, 0xAD, 0x72, 0x1D, 0x85, +0x24, 0xAD, 0x74, 0x1D, 0x85, 0x25, 0xC2, 0x30, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF4, +0x22, 0xFC, 0xA2, 0x03, 0x24, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x68, 0x68, 0x68, 0x60, 0xEE, 0x74, +0x1D, 0x20, 0x4A, 0xB7, 0x60, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0xED, 0xFD, 0xA2, 0x03, 0x24, 0x22, 0x00, +0x00, 0xE1, 0x68, 0x68, 0x68, 0x68, 0x60, 0xA9, 0x04, 0x00, 0x8D, 0x6E, 0x1D, 0xA9, 0x12, 0x00, +0x8D, 0x70, 0x1D, 0xA9, 0x14, 0x00, 0x8D, 0x72, 0x1D, 0x8D, 0x7E, 0x1D, 0xA9, 0x3B, 0x00, 0x8D, +0x80, 0x1D, 0xA9, 0x00, 0x00, 0x8D, 0x74, 0x1D, 0xA9, 0x14, 0x00, 0x8D, 0x76, 0x1D, 0xA9, 0x00, +0x00, 0x8D, 0x78, 0x1D, 0xA9, 0x12, 0x00, 0x8D, 0x7A, 0x1D, 0x60, 0xC2, 0x30, 0xAD, 0xB0, 0x1D, +0xF0, 0x10, 0xC9, 0xFF, 0x00, 0xF0, 0x1D, 0xE2, 0x30, 0xFA, 0xC2, 0x30, 0x20, 0xF8, 0xB9, 0x4C, +0xE4, 0xB4, 0xE2, 0x30, 0x68, 0x8B, 0xA9, 0x00, 0x48, 0xAB, 0x22, 0x90, 0x00, 0xE1, 0xAB, 0xC2, +0x30, 0x4C, 0xE4, 0xB4, 0x4C, 0x3E, 0xB7, 0xE2, 0x30, 0xAD, 0x00, 0xC0, 0x10, 0xF9, 0x8D, 0x10, +0xC0, 0xC2, 0x30, 0x60, 0xF4, 0x00, 0x00, 0xF4, 0xFF, 0xFF, 0xF4, 0xE0, 0x00, 0xF4, 0x8C, 0x1D, +0xA2, 0x06, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xF0, 0xEA, 0xAD, 0x8C, 0x1D, 0xC9, 0x03, 0x00, +0xD0, 0xE2, 0xAD, 0x8E, 0x1D, 0x29, 0xFF, 0x00, 0x60, 0x2D, 0xB8, 0xFE, 0x00, 0x16, 0xC1, 0xEC, +0xF4, 0xE5, 0xF2, 0xEE, 0xE1, 0xF4, 0xE5, 0xA0, 0xC4, 0xE9, 0xF3, 0xF0, 0xEC, 0xE1, 0xF9, 0xA0, +0xCD, 0xEF, 0xE4, 0xE5, 0x48, 0xB8, 0xFE, 0x00, 0xE2, 0x30, 0x8B, 0xA9, 0x00, 0x48, 0xAB, 0x22, +0xA4, 0x00, 0xE1, 0xAB, 0xC2, 0x30, 0x6B, 0xAF, 0x7C, 0x1D, 0xE0, 0xC9, 0x0D, 0x00, 0xB0, 0x55, +0x8B, 0xF4, 0xE0, 0xE0, 0xAB, 0xAB, 0xAD, 0x88, 0x1D, 0x4A, 0x4A, 0xD0, 0x03, 0x20, 0xC7, 0xB8, +0xAD, 0x86, 0x1D, 0x48, 0xAD, 0x84, 0x1D, 0x48, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, 0xAD, +0x84, 0x1D, 0x85, 0x3C, 0xAD, 0x86, 0x1D, 0x85, 0x3E, 0x20, 0xBB, 0xB8, 0xAD, 0x7C, 0x1D, 0x0A, +0x0A, 0xA8, 0xA3, 0x08, 0x97, 0x40, 0xA3, 0x0A, 0xC8, 0xC8, 0x97, 0x40, 0xEE, 0x7C, 0x1D, 0xAD, +0x86, 0x1D, 0x48, 0xAD, 0x84, 0x1D, 0x48, 0xA2, 0x02, 0x22, 0x22, 0x00, 0x00, 0xE1, 0xCE, 0x88, +0x1D, 0xAB, 0x4C, 0xC2, 0xFF, 0xA9, 0x01, 0x05, 0x4C, 0xC7, 0xFF, 0xA0, 0x02, 0x00, 0xA7, 0x3C, +0x85, 0x40, 0xB7, 0x3C, 0x85, 0x42, 0x60, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xAD, 0x86, 0x1D, +0x48, 0xAD, 0x84, 0x1D, 0x48, 0xA2, 0x02, 0x18, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x3C, 0x68, +0x85, 0x3E, 0xA5, 0x3C, 0x18, 0x69, 0x20, 0x00, 0x85, 0x3C, 0xA5, 0x3E, 0x69, 0x00, 0x00, 0x85, +0x3E, 0xA5, 0x3E, 0x48, 0xA5, 0x3C, 0x48, 0xAD, 0x86, 0x1D, 0x48, 0xAD, 0x84, 0x1D, 0x48, 0xA2, +0x02, 0x19, 0x22, 0x00, 0x00, 0xE1, 0xAD, 0x88, 0x1D, 0x18, 0x69, 0x08, 0x00, 0x8D, 0x88, 0x1D, +0x60, 0x20, 0xD7, 0xB9, 0xAD, 0x72, 0x1D, 0x48, 0x18, 0x69, 0x02, 0x00, 0x8D, 0x72, 0x1D, 0x48, +0x20, 0x4A, 0xB7, 0xA9, 0x00, 0x00, 0xA8, 0x5A, 0x20, 0x62, 0xB9, 0xAE, 0x7C, 0x1D, 0xF0, 0x19, +0xDA, 0x20, 0x6E, 0xB7, 0xA3, 0x03, 0x1A, 0x83, 0x03, 0xA8, 0xA9, 0x00, 0x00, 0x20, 0x62, 0xB9, +0xA3, 0x01, 0x3A, 0x83, 0x01, 0xD0, 0xEA, 0xAA, 0x7A, 0x7A, 0xAD, 0x70, 0x1D, 0x8D, 0x74, 0x1D, +0x68, 0x8D, 0x72, 0x1D, 0x20, 0x4A, 0xB7, 0xA9, 0xFF, 0x00, 0xA0, 0xFF, 0x00, 0x20, 0x62, 0xB9, +0x68, 0x60, 0xC9, 0x00, 0x00, 0xD0, 0x0A, 0xE2, 0x30, 0xA9, 0xFF, 0x85, 0x32, 0xC2, 0x30, 0x80, +0x08, 0xE2, 0x30, 0xA9, 0x7F, 0x85, 0x32, 0xC2, 0x30, 0xC0, 0x00, 0x00, 0xD0, 0x07, 0xA0, 0x06, +0x00, 0x20, 0xBB, 0xB9, 0x60, 0xC0, 0xFF, 0x00, 0xD0, 0x07, 0xA0, 0x0A, 0x00, 0x20, 0xBB, 0xB9, +0x60, 0xAD, 0xA8, 0x1D, 0x85, 0x40, 0xAD, 0xAA, 0x1D, 0x85, 0x42, 0x98, 0x3A, 0x0A, 0x0A, 0xA8, +0xB7, 0x40, 0x85, 0x3C, 0xC8, 0xC8, 0xB7, 0x40, 0x85, 0x3E, 0x20, 0xBB, 0xB8, 0xA5, 0x42, 0x48, +0xA5, 0x40, 0x48, 0xA2, 0x0C, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0x60, 0x5A, 0xAD, 0xAC, 0x1D, 0x85, +0x3C, 0xAD, 0xAE, 0x1D, 0x85, 0x3E, 0x7A, 0xB7, 0x3C, 0x48, 0x88, 0x88, 0xB7, 0x3C, 0x48, 0xA2, +0x0C, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x60, 0xAD, 0x86, 0x1D, 0x48, 0x85, 0x3E, 0xAD, 0x84, 0x1D, +0x48, 0x85, 0x3C, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x20, 0xBB, 0xB8, 0xA5, 0x40, 0x8D, +0xA8, 0x1D, 0xA5, 0x42, 0x8D, 0xAA, 0x1D, 0x60, 0x78, 0xA8, 0xE2, 0x30, 0xA9, 0xFF, 0x85, 0x32, +0xC2, 0x30, 0xAD, 0xA8, 0x1D, 0x85, 0x40, 0xAD, 0xAA, 0x1D, 0x85, 0x42, 0x98, 0x3A, 0x0A, 0x0A, +0xA8, 0xB7, 0x40, 0x85, 0x3C, 0xC8, 0xC8, 0xB7, 0x40, 0x85, 0x3E, 0x20, 0xBB, 0xB8, 0xA7, 0x40, +0x29, 0xFF, 0x00, 0xA8, 0xC8, 0x4B, 0x62, 0x0F, 0x00, 0xB7, 0x40, 0xAA, 0xC8, 0xC8, 0xB7, 0x40, +0xE2, 0x20, 0x48, 0xC2, 0x30, 0xCA, 0xDA, 0x58, 0x6B, 0x60, 0x8B, 0xA5, 0x3C, 0x48, 0xA5, 0x3E, +0x48, 0xA5, 0x40, 0x48, 0xA5, 0x42, 0x48, 0xA9, 0xE0, 0xE0, 0x48, 0xAB, 0xAB, 0xA3, 0x10, 0x8D, +0xAC, 0x1D, 0xA3, 0x12, 0x8D, 0xAE, 0x1D, 0xAD, 0x86, 0x1D, 0x85, 0x3E, 0x48, 0xAD, 0x84, 0x1D, +0x85, 0x3C, 0x48, 0xA2, 0x02, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x20, 0xBB, 0xB8, 0xA0, 0x02, 0x00, +0xA3, 0x14, 0x87, 0x40, 0xA3, 0x16, 0x97, 0x40, 0xAD, 0x86, 0x1D, 0x48, 0xAD, 0x84, 0x1D, 0x48, +0xA2, 0x02, 0x22, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x42, 0x68, 0x85, 0x40, 0x68, 0x85, 0x3E, +0x68, 0x85, 0x3C, 0xAB, 0x4C, 0xD8, 0xFF, 0xAF, 0xAC, 0x1D, 0xE0, 0x83, 0x07, 0xAF, 0xAE, 0x1D, +0xE0, 0x83, 0x09, 0x4C, 0x8B, 0xFF, 0x00, 0x80, 0x00, 0x10, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, +0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, +0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x02, 0x00, 0x10, 0x00, 0x04, +0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x32, 0x00, 0x00, 0x00, 0x28, 0x00, +0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0A, 0x00, +0x00, 0x00, 0x10, 0x1A, 0x00, 0x00, 0x00, 0x6A, 0xBB, 0xFE, 0x00, 0x6D, 0xBB, 0xFE, 0x00, 0xDE, +0xBD, 0xFE, 0x00, 0xA0, 0xBE, 0xFE, 0x00, 0xA8, 0xBE, 0xFE, 0x00, 0xB6, 0xBE, 0xFE, 0x00, 0x8A, +0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0xBB, 0xBE, 0xFE, 0x00, 0xCF, 0xBE, 0xFE, 0x00, 0x34, +0xC0, 0xFE, 0x00, 0x41, 0xC0, 0xFE, 0x00, 0x80, 0xC0, 0xFE, 0x00, 0xC0, 0xC0, 0xFE, 0x00, 0x19, +0xC1, 0xFE, 0x00, 0x6B, 0xC1, 0xFE, 0x00, 0x9A, 0xC1, 0xFE, 0x00, 0xC7, 0xC1, 0xFE, 0x00, 0xF4, +0xC1, 0xFE, 0x00, 0x06, 0xC2, 0xFE, 0x00, 0x91, 0xC2, 0xFE, 0x00, 0xEE, 0xC2, 0xFE, 0x00, 0xB1, +0xC3, 0xFE, 0x00, 0xBE, 0xC3, 0xFE, 0x00, 0xCF, 0xC3, 0xFE, 0x00, 0x4C, 0x8B, 0xFF, 0xC9, 0x00, +0x00, 0xF0, 0x06, 0xA2, 0x01, 0x06, 0x4C, 0xB1, 0xFF, 0x0B, 0xA3, 0x15, 0x5B, 0xA2, 0xFE, 0x00, +0x74, 0x00, 0xCA, 0xCA, 0x10, 0xFA, 0xA9, 0x00, 0x00, 0xA2, 0x0A, 0x00, 0x9F, 0xE1, 0x00, 0xE1, +0xCA, 0xCA, 0x10, 0xF8, 0xA3, 0x09, 0x85, 0x60, 0xA3, 0x13, 0xD0, 0x03, 0xA9, 0x14, 0x00, 0xC9, +0x38, 0x0E, 0x90, 0x06, 0xA2, 0x06, 0x06, 0x4C, 0xB0, 0xFF, 0x1A, 0x85, 0x2C, 0x0A, 0x0A, 0x0A, +0x18, 0x65, 0x2C, 0x0A, 0xA6, 0x60, 0xA0, 0x04, 0x00, 0x20, 0x24, 0x11, 0x90, 0x06, 0xA2, 0x07, +0x06, 0x4C, 0xB0, 0xFF, 0x86, 0x24, 0x84, 0x26, 0x20, 0x94, 0xC4, 0xA6, 0x2C, 0xA0, 0x02, 0x00, +0xA9, 0xFF, 0xFF, 0x97, 0x28, 0x98, 0x18, 0x69, 0x12, 0x00, 0xA8, 0xCA, 0xD0, 0xF2, 0xA9, 0xEE, +0xEE, 0xA0, 0x02, 0x00, 0x97, 0x28, 0x20, 0xC0, 0xC4, 0xA9, 0xFF, 0xFF, 0x85, 0x22, 0x08, 0x08, +0x68, 0x85, 0x5E, 0x78, 0x48, 0xA2, 0x03, 0x29, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xEB, 0x2A, 0x26, +0x58, 0x2A, 0x26, 0x5A, 0x48, 0x48, 0xF4, 0x0D, 0x00, 0x22, 0x1F, 0x11, 0xFE, 0x68, 0x85, 0x42, +0x68, 0x85, 0x44, 0x48, 0x48, 0xF4, 0x0F, 0x00, 0x22, 0x1F, 0x11, 0xFE, 0x68, 0x85, 0x46, 0x68, +0x85, 0x48, 0x48, 0x48, 0xF4, 0x12, 0x00, 0x22, 0x1F, 0x11, 0xFE, 0x68, 0x85, 0x4A, 0x68, 0x85, +0x4C, 0x48, 0x48, 0xF4, 0x13, 0x00, 0x22, 0x1F, 0x11, 0xFE, 0x68, 0x85, 0x4E, 0x68, 0x85, 0x50, +0x48, 0x48, 0xF4, 0x0C, 0x00, 0x22, 0x1F, 0x11, 0xFE, 0x68, 0x85, 0x52, 0x68, 0x85, 0x54, 0xF4, +0x0D, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0xC8, 0xC5, 0x22, 0x1A, 0x11, 0xFE, 0xF4, 0x0F, 0x00, 0xF4, +0xFE, 0x00, 0xF4, 0x8D, 0xC5, 0x22, 0x1A, 0x11, 0xFE, 0xF4, 0x12, 0x00, 0xF4, 0xFE, 0x00, 0xF4, +0x86, 0xC6, 0x22, 0x1A, 0x11, 0xFE, 0xF4, 0x13, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0xA0, 0xC6, 0x22, +0x1A, 0x11, 0xFE, 0xF4, 0x0C, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0x74, 0x98, 0x22, 0x1A, 0x11, 0xFE, +0x48, 0xF4, 0x2B, 0x00, 0xA2, 0x03, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x56, 0xD0, 0x13, +0xF4, 0x01, 0x00, 0xF4, 0xFE, 0x00, 0xF4, 0x02, 0xBB, 0xF4, 0x04, 0x00, 0xA2, 0x09, 0x09, 0x22, +0x00, 0x00, 0xE1, 0xF4, 0x02, 0x00, 0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x00, 0x00, +0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x0A, 0x00, 0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, +0xE1, 0xAF, 0xDF, 0x00, 0xE1, 0x30, 0x0E, 0xEB, 0x29, 0xFF, 0x00, 0xAA, 0xBF, 0xF8, 0x07, 0x00, +0x29, 0x0F, 0x00, 0x85, 0x5C, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x18, 0x22, 0x00, 0x00, 0xE1, 0xB0, +0x69, 0xE6, 0x3E, 0xAF, 0xE0, 0x00, 0xE1, 0x29, 0xFF, 0x00, 0xC9, 0x04, 0x00, 0xD0, 0x19, 0xE2, +0x30, 0xAF, 0x2D, 0xC0, 0x00, 0xC2, 0x30, 0x29, 0x10, 0x00, 0xD0, 0x0C, 0xF4, 0x07, 0x00, 0xA2, +0x03, 0x19, 0x22, 0x00, 0x00, 0xE1, 0x80, 0x42, 0xF4, 0x01, 0x00, 0xA2, 0x03, 0x19, 0x22, 0x00, +0x00, 0xE1, 0xA9, 0x01, 0x00, 0x85, 0x40, 0x8F, 0xF1, 0x00, 0xE1, 0xA9, 0x5A, 0xA5, 0x8F, 0xF3, +0x00, 0xE1, 0xA9, 0xB7, 0xC6, 0x48, 0xEB, 0x29, 0x00, 0xFF, 0x09, 0x5C, 0x00, 0x8F, 0xF5, 0x00, +0xE1, 0x68, 0x29, 0x00, 0xFF, 0x09, 0xFE, 0x00, 0xEB, 0x8F, 0xF7, 0x00, 0xE1, 0xF4, 0xE1, 0x00, +0xF4, 0xED, 0x00, 0xA2, 0x03, 0x12, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x11, 0x48, 0x8F, 0xE9, 0x00, +0xE1, 0xA3, 0x11, 0x38, 0xE9, 0x01, 0x00, 0x48, 0xA3, 0x11, 0x48, 0x8F, 0xEB, 0x00, 0xE1, 0xA3, +0x11, 0x38, 0xE9, 0x01, 0x00, 0x48, 0xA2, 0x03, 0x1C, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x11, 0x48, +0xA3, 0x11, 0x38, 0xE9, 0x01, 0x00, 0x48, 0xA3, 0x11, 0x48, 0xA3, 0x11, 0x38, 0xE9, 0x01, 0x00, +0x48, 0xA2, 0x03, 0x2A, 0x22, 0x00, 0x00, 0xE1, 0xA2, 0x03, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0xB0, +0x19, 0x48, 0x48, 0x48, 0xA2, 0x03, 0x17, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x8F, 0xE7, 0x00, 0xE1, +0x68, 0x8F, 0xEB, 0x00, 0xE1, 0x68, 0x8F, 0xE9, 0x00, 0xE1, 0xAF, 0xE9, 0x00, 0xE1, 0x48, 0xAF, +0xEB, 0x00, 0xE1, 0x48, 0x22, 0x60, 0x00, 0xE1, 0xA3, 0x15, 0xF4, 0x00, 0x00, 0xF4, 0x06, 0x00, +0xF4, 0x00, 0x00, 0x48, 0xA2, 0x01, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x58, 0x4C, 0xAD, 0xFF, 0x0B, +0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0x8F, 0xFF, 0x78, 0xF4, 0xE1, 0x00, 0xF4, 0xED, 0x00, +0xA2, 0x03, 0x13, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x56, 0xD0, 0x13, 0xF4, 0x01, 0x00, 0xF4, 0xFE, +0x00, 0xF4, 0x02, 0xBB, 0xF4, 0x05, 0x00, 0xA2, 0x09, 0x09, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x5A, +0xD0, 0x0A, 0xF4, 0x03, 0x00, 0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x58, 0xD0, 0x0A, +0xF4, 0x01, 0x00, 0xA2, 0x03, 0x23, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x3E, 0xF0, 0x0A, 0xA5, 0x5C, +0x48, 0xA2, 0x03, 0x19, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x0D, 0x00, 0xA5, 0x44, 0x48, 0xA5, 0x42, +0x48, 0x22, 0x1A, 0x11, 0xFE, 0xF4, 0x0F, 0x00, 0xA5, 0x48, 0x48, 0xA5, 0x46, 0x48, 0x22, 0x1A, +0x11, 0xFE, 0xF4, 0x12, 0x00, 0xA5, 0x4C, 0x48, 0xA5, 0x4A, 0x48, 0x22, 0x1A, 0x11, 0xFE, 0xF4, +0x13, 0x00, 0xA5, 0x50, 0x48, 0xA5, 0x4E, 0x48, 0x22, 0x1A, 0x11, 0xFE, 0xF4, 0x0C, 0x00, 0xA5, +0x54, 0x48, 0xA5, 0x52, 0x48, 0x22, 0x1A, 0x11, 0xFE, 0xA5, 0x26, 0x48, 0xA5, 0x24, 0x48, 0xA2, +0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x00, 0x00, 0xF4, 0x06, 0x00, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0xA2, 0x01, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0xA5, 0x5E, 0x48, 0x28, 0x28, 0x4C, 0x8C, +0xFF, 0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xC9, 0x00, 0x00, 0xF0, 0x06, 0xA2, 0x02, +0x06, 0x4C, 0x90, 0xFF, 0x4C, 0x8B, 0xFF, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0x0B, 0x5B, 0xD0, 0x06, +0xA2, 0x03, 0x06, 0x4C, 0x8F, 0xFF, 0x83, 0x09, 0xA9, 0x01, 0x00, 0x85, 0x38, 0x4C, 0x8C, 0xFF, +0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xD1, 0xFF, 0xE6, 0x3A, 0xA3, 0x09, 0x85, 0x10, +0xA3, 0x0B, 0x85, 0x12, 0x20, 0x3A, 0xBF, 0x20, 0x41, 0xBF, 0xD0, 0x24, 0x20, 0xAB, 0xBF, 0xD0, +0x1F, 0x20, 0xCC, 0xBF, 0xD0, 0x1A, 0x20, 0xEC, 0xBF, 0xD0, 0x15, 0xAF, 0xE1, 0x00, 0xE1, 0xF0, +0x32, 0xF4, 0x00, 0x00, 0x18, 0x7B, 0x69, 0x00, 0x00, 0x48, 0x22, 0x23, 0xC0, 0xFE, 0x80, 0x1B, +0xA5, 0x3A, 0xF0, 0x1C, 0xF4, 0x00, 0x00, 0xA0, 0x0E, 0x00, 0xB7, 0x10, 0x48, 0x88, 0x88, 0x10, +0xF9, 0xA2, 0x05, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xF0, 0x05, 0xA9, 0x00, 0x00, 0x80, 0x03, +0xA9, 0x01, 0x00, 0x83, 0x0F, 0x64, 0x3A, 0x4C, 0xCE, 0xFF, 0xA9, 0x00, 0x00, 0x20, 0x09, 0xC0, +0x60, 0xA3, 0x0F, 0x29, 0x00, 0x01, 0xF0, 0x51, 0xA5, 0x82, 0xD0, 0x4E, 0xA5, 0x80, 0xF0, 0x49, +0xA0, 0x02, 0x00, 0xA5, 0x84, 0x97, 0x10, 0xC8, 0xC8, 0xA5, 0x86, 0x97, 0x10, 0xA9, 0x01, 0x00, +0x85, 0x20, 0xA5, 0x88, 0xF0, 0x14, 0xA5, 0x84, 0xF0, 0x10, 0xA0, 0x04, 0x00, 0xB7, 0x84, 0x45, +0x8C, 0x10, 0x07, 0xA5, 0x20, 0x09, 0x02, 0x00, 0x85, 0x20, 0xA0, 0x0E, 0x00, 0xB7, 0x10, 0x05, +0x20, 0x97, 0x10, 0xA5, 0x3A, 0xF0, 0x0A, 0xA5, 0x82, 0xF0, 0x04, 0x64, 0x82, 0x80, 0x02, 0x64, +0x80, 0xA9, 0x08, 0x00, 0x87, 0x10, 0xA9, 0x01, 0x00, 0x60, 0x64, 0x20, 0xA0, 0x02, 0x00, 0xA5, +0x88, 0x97, 0x10, 0xC8, 0xC8, 0xA5, 0x8A, 0x97, 0x10, 0x80, 0xB7, 0xA3, 0x0F, 0x29, 0x00, 0x02, +0xF0, 0x19, 0xA5, 0x36, 0xF0, 0x15, 0xA3, 0x0F, 0x20, 0xEE, 0xBF, 0xD0, 0x0E, 0xA5, 0x3A, 0xF0, +0x02, 0x64, 0x36, 0xA9, 0x09, 0x00, 0x87, 0x10, 0xA9, 0x01, 0x00, 0x60, 0xE6, 0x62, 0xA3, 0x0F, +0x20, 0x09, 0xC0, 0x64, 0x62, 0xAF, 0xE1, 0x00, 0xE1, 0xF0, 0x0E, 0xA5, 0x10, 0x85, 0x14, 0xA5, +0x12, 0x85, 0x16, 0xA2, 0x04, 0x00, 0x20, 0x7A, 0xC5, 0xA7, 0x10, 0x60, 0xA3, 0x0F, 0x29, 0x40, +0x00, 0xF0, 0x15, 0xA5, 0x38, 0xF0, 0x11, 0xF4, 0x00, 0x00, 0xA5, 0x12, 0x48, 0xA5, 0x10, 0x48, +0xA2, 0x0E, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x60, 0xF4, 0x00, 0x00, 0x48, 0xA5, 0x12, 0x48, +0xA5, 0x10, 0x48, 0xA5, 0x3A, 0xF0, 0x06, 0x22, 0x29, 0xC0, 0xFE, 0x80, 0x04, 0x22, 0x2F, 0xC0, +0xFE, 0x68, 0x60, 0x7B, 0x22, 0x42, 0xC0, 0xFE, 0x6B, 0x7B, 0x22, 0xEF, 0xC2, 0xFE, 0x6B, 0x7B, +0x22, 0xB2, 0xC3, 0xFE, 0x6B, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xD1, 0xFF, 0x4C, +0xDC, 0xBE, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xC6, 0xFF, 0x08, 0x78, 0xA3, 0x0A, +0x85, 0x1C, 0xA3, 0x0C, 0x85, 0x1E, 0xA0, 0x00, 0x00, 0x20, 0x2B, 0xC5, 0xAF, 0xE1, 0x00, 0xE1, +0xF0, 0x0E, 0xA5, 0x1C, 0x85, 0x14, 0xA5, 0x1E, 0x85, 0x16, 0xA2, 0x01, 0x00, 0x20, 0x7A, 0xC5, +0xA5, 0x1E, 0x48, 0xA5, 0x1C, 0x48, 0xA2, 0x04, 0x85, 0x22, 0x00, 0x00, 0xE1, 0x28, 0x4C, 0xC3, +0xFF, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xBB, 0xFF, 0xA3, 0x09, 0xC9, 0x02, 0x00, +0x90, 0x06, 0xA2, 0x05, 0x06, 0x4C, 0xBB, 0xFF, 0x0A, 0xAA, 0xAF, 0xE7, 0x00, 0xE1, 0x3F, 0xA6, +0xBA, 0xFE, 0xF0, 0x03, 0xA9, 0x01, 0x00, 0x83, 0x0B, 0xAF, 0xE1, 0x00, 0xE1, 0xF0, 0x0F, 0x64, +0x16, 0x18, 0x3B, 0x69, 0x0B, 0x00, 0x85, 0x14, 0xA2, 0x02, 0x00, 0x20, 0x7A, 0xC5, 0x4C, 0xB8, +0xFF, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xBB, 0xFF, 0xA3, 0x09, 0xC9, 0x02, 0x00, +0x90, 0x06, 0xA2, 0x05, 0x06, 0x4C, 0xBB, 0xFF, 0xF4, 0x00, 0x00, 0x48, 0x22, 0x0E, 0xC1, 0xFE, +0x68, 0xF0, 0x26, 0xE6, 0x32, 0xA3, 0x09, 0x85, 0x34, 0xF4, 0x00, 0x00, 0xF4, 0x07, 0x00, 0xF4, +0x00, 0x00, 0x7B, 0x18, 0x69, 0x00, 0x00, 0x48, 0x22, 0x14, 0xC1, 0xFE, 0x64, 0x32, 0x68, 0xD0, +0x05, 0xA9, 0x01, 0x00, 0x80, 0x03, 0xA9, 0x00, 0x00, 0x83, 0x0B, 0x4C, 0xB8, 0xFF, 0x7B, 0x22, +0x81, 0xC0, 0xFE, 0x6B, 0x7B, 0x22, 0x35, 0xC0, 0xFE, 0x6B, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, +0x06, 0x4C, 0xBB, 0xFF, 0xA3, 0x09, 0xC9, 0x02, 0x00, 0x90, 0x06, 0xA2, 0x05, 0x06, 0x4C, 0xBB, +0xFF, 0xF4, 0x00, 0x00, 0x48, 0x22, 0x60, 0xC1, 0xFE, 0x68, 0xD0, 0x1F, 0xE6, 0x32, 0xA3, 0x09, +0x85, 0x34, 0xF4, 0x00, 0x00, 0xF4, 0x04, 0x00, 0xF4, 0x00, 0x00, 0x7B, 0x18, 0x69, 0x00, 0x00, +0x48, 0x22, 0x66, 0xC1, 0xFE, 0x64, 0x32, 0x68, 0xA9, 0x00, 0x00, 0x83, 0x0B, 0x4C, 0xB8, 0xFF, +0x7B, 0x22, 0xC1, 0xC0, 0xFE, 0x6B, 0x7B, 0x22, 0xD0, 0xBE, 0xFE, 0x6B, 0xC9, 0x00, 0x00, 0xD0, +0x06, 0xA2, 0x03, 0x06, 0x4C, 0x90, 0xFF, 0xAF, 0xDC, 0x00, 0xE1, 0x83, 0x07, 0xAF, 0xDE, 0x00, +0xE1, 0x83, 0x09, 0xAF, 0xE1, 0x00, 0xE1, 0xF0, 0x0F, 0x64, 0x16, 0x18, 0x3B, 0x69, 0x07, 0x00, +0x85, 0x14, 0xA2, 0x00, 0x00, 0x20, 0x7A, 0xC5, 0x4C, 0x8B, 0xFF, 0xC9, 0x00, 0x00, 0xD0, 0x06, +0xA2, 0x03, 0x06, 0x4C, 0x90, 0xFF, 0xF4, 0x00, 0x00, 0xF4, 0x2E, 0x00, 0xA2, 0x03, 0x0C, 0x22, +0x00, 0x00, 0xE1, 0x68, 0x0A, 0x0A, 0xAA, 0xBF, 0xDA, 0xBA, 0xFE, 0x83, 0x07, 0xE8, 0xE8, 0xBF, +0xDA, 0xBA, 0xFE, 0x83, 0x09, 0x4C, 0x8B, 0xFF, 0xC9, 0x00, 0x00, 0xD0, 0x06, 0xA2, 0x03, 0x06, +0x4C, 0x90, 0xFF, 0xF4, 0x00, 0x00, 0xF4, 0x2F, 0x00, 0xA2, 0x03, 0x0C, 0x22, 0x00, 0x00, 0xE1, +0x68, 0x0A, 0x0A, 0xAA, 0xBF, 0xEE, 0xBA, 0xFE, 0x83, 0x07, 0xE8, 0xE8, 0xBF, 0xEE, 0xBA, 0xFE, +0x83, 0x09, 0x4C, 0x8B, 0xFF, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0x8F, 0xFF, 0xA9, +0x01, 0x00, 0x85, 0x36, 0x4C, 0x8C, 0xFF, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xD1, +0xFF, 0xA3, 0x0D, 0xC9, 0x10, 0x00, 0x90, 0x06, 0xA2, 0x04, 0x06, 0x4C, 0xD1, 0xFF, 0x08, 0x78, +0x0A, 0xAA, 0xBF, 0xAA, 0xBA, 0xFE, 0x25, 0x22, 0xD0, 0x09, 0xA9, 0x01, 0x00, 0x83, 0x10, 0x28, +0x4C, 0xCE, 0xFF, 0xA3, 0x0E, 0xC9, 0x05, 0x00, 0xD0, 0x04, 0xA5, 0x2E, 0xD0, 0xEC, 0x20, 0x94, +0xC4, 0xA0, 0x02, 0x00, 0xA6, 0x2C, 0xB7, 0x28, 0xC9, 0xFF, 0xFF, 0xF0, 0x11, 0x18, 0x98, 0x69, +0x12, 0x00, 0xA8, 0xCA, 0xD0, 0xF0, 0xA4, 0x2E, 0xB7, 0x28, 0x85, 0x2E, 0xC8, 0xC8, 0x18, 0x98, +0x65, 0x28, 0x85, 0x1C, 0xA9, 0x00, 0x00, 0x65, 0x2A, 0x85, 0x1E, 0x88, 0x88, 0x84, 0x1A, 0xA3, +0x0E, 0x87, 0x1C, 0xA0, 0x02, 0x00, 0xA3, 0x0A, 0x97, 0x1C, 0xC8, 0xC8, 0xA3, 0x0C, 0x97, 0x1C, +0x20, 0xE1, 0xC4, 0x20, 0x41, 0xC4, 0x20, 0xC0, 0xC4, 0x28, 0xA9, 0x00, 0x00, 0x83, 0x0F, 0x4C, +0xCE, 0xFF, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xC6, 0xFF, 0x08, 0x78, 0x20, 0x94, +0xC4, 0xA5, 0x2E, 0x85, 0x1A, 0xA8, 0xF0, 0x3E, 0xC8, 0xC8, 0xB7, 0x28, 0xC9, 0x10, 0x00, 0x90, +0x10, 0xF4, 0x81, 0x06, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x15, 0x22, 0x00, 0x00, +0xE1, 0x0A, 0xAA, 0xBF, 0xAA, 0xBA, 0xFE, 0xAA, 0x23, 0x0A, 0xD0, 0x18, 0x8A, 0x23, 0x0C, 0xF0, +0x08, 0xA9, 0xFF, 0xFF, 0x97, 0x28, 0x20, 0x5D, 0xC4, 0xA4, 0x1A, 0xB7, 0x28, 0x85, 0x1A, 0xA8, +0xD0, 0xC6, 0x80, 0x02, 0xB7, 0x28, 0x83, 0x0E, 0x20, 0xC0, 0xC4, 0x28, 0x4C, 0xC3, 0xFF, 0x0B, +0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xD1, 0xFF, 0xE6, 0x3C, 0x08, 0x78, 0x20, 0x94, 0xC4, +0xA3, 0x0E, 0xF0, 0x4A, 0xA5, 0x2E, 0x85, 0x1A, 0xA8, 0xF0, 0x43, 0xC8, 0xC8, 0xB7, 0x28, 0xC9, +0x10, 0x00, 0x90, 0x10, 0xF4, 0x81, 0x06, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x15, +0x22, 0x00, 0x00, 0xE1, 0x0A, 0xAA, 0xBF, 0xAA, 0xBA, 0xFE, 0x23, 0x0E, 0xF0, 0x17, 0xA5, 0x32, +0xF0, 0x3E, 0xB7, 0x28, 0xC9, 0x03, 0x00, 0xB0, 0x37, 0x18, 0x98, 0x69, 0x02, 0x00, 0xA8, 0xB7, +0x28, 0xC5, 0x34, 0xF0, 0x2B, 0xA4, 0x1A, 0xB7, 0x28, 0x85, 0x1A, 0xA8, 0xD0, 0xBD, 0xA5, 0x62, +0xD0, 0x19, 0xA3, 0x0A, 0x85, 0x1C, 0xA3, 0x0C, 0x85, 0x1E, 0xA9, 0x00, 0x00, 0x87, 0x1C, 0xA0, +0x02, 0x00, 0x97, 0x1C, 0xC8, 0xC8, 0x97, 0x1C, 0x20, 0xE1, 0xC4, 0xA9, 0x00, 0x00, 0x80, 0x37, +0xA3, 0x0A, 0x85, 0x10, 0xA3, 0x0C, 0x85, 0x12, 0x18, 0xA5, 0x1A, 0x69, 0x02, 0x00, 0x65, 0x28, +0x85, 0x1C, 0xA9, 0x00, 0x00, 0x65, 0x2A, 0x85, 0x1E, 0xA0, 0x0E, 0x00, 0xB7, 0x1C, 0x97, 0x10, +0x88, 0x88, 0x10, 0xF8, 0xA5, 0x3C, 0xF0, 0x0C, 0xA9, 0xFF, 0xFF, 0xA4, 0x1A, 0xC8, 0xC8, 0x97, +0x28, 0x20, 0x5D, 0xC4, 0xA9, 0x01, 0x00, 0x83, 0x10, 0x64, 0x3C, 0x20, 0xC0, 0xC4, 0x28, 0x4C, +0xCE, 0xFF, 0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xD1, 0xFF, 0x4C, 0xFB, 0xC2, 0x0B, +0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0xBB, 0xFF, 0xA3, 0x09, 0x85, 0x22, 0x4C, 0xB8, 0xFF, +0x0B, 0x5B, 0xD0, 0x06, 0xA2, 0x03, 0x06, 0x4C, 0x9A, 0xFF, 0xA3, 0x09, 0x8F, 0xE7, 0x00, 0xE1, +0xA3, 0x0B, 0x8F, 0xEB, 0x00, 0xE1, 0xA3, 0x0D, 0x8F, 0xE9, 0x00, 0xE1, 0xA5, 0x40, 0xD0, 0x2D, +0xE2, 0x30, 0xAF, 0xE0, 0x00, 0xE1, 0x30, 0x21, 0xAA, 0xAF, 0xE9, 0x00, 0xE1, 0x9F, 0x78, 0x04, +0x00, 0xAF, 0xEA, 0x00, 0xE1, 0x9F, 0x78, 0x05, 0x00, 0xAF, 0xEB, 0x00, 0xE1, 0x9F, 0xF8, 0x04, +0x00, 0xAF, 0xEC, 0x00, 0xE1, 0x9F, 0xF8, 0x05, 0x00, 0xC2, 0x30, 0x80, 0x11, 0xAF, 0xE9, 0x00, +0xE1, 0x48, 0xAF, 0xEB, 0x00, 0xE1, 0x48, 0xA2, 0x03, 0x1E, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x0F, +0xAA, 0xA3, 0x11, 0x22, 0x3C, 0xC4, 0xFE, 0xC2, 0x30, 0x4C, 0x97, 0xFF, 0x48, 0xDA, 0x4C, 0xFF, +0xC5, 0xA9, 0x00, 0x00, 0xA4, 0x1A, 0x97, 0x28, 0xA5, 0x2E, 0xD0, 0x08, 0xA5, 0x1A, 0x85, 0x2E, +0x85, 0x30, 0x80, 0x08, 0xA5, 0x1A, 0xA4, 0x30, 0x97, 0x28, 0x85, 0x30, 0x60, 0xA5, 0x2E, 0xC5, +0x1A, 0xF0, 0x0C, 0xA8, 0xB7, 0x28, 0xC5, 0x1A, 0xF0, 0x18, 0xB7, 0x28, 0xD0, 0xF5, 0x60, 0xA4, +0x1A, 0xB7, 0x28, 0x85, 0x2E, 0xA5, 0x1A, 0xC5, 0x30, 0xD0, 0xF3, 0xA9, 0x00, 0x00, 0x85, 0x30, +0x80, 0xEC, 0xBB, 0xA4, 0x1A, 0xB7, 0x28, 0x9B, 0x97, 0x28, 0xA5, 0x1A, 0xC5, 0x30, 0xD0, 0xDE, +0x86, 0x30, 0x80, 0xDA, 0xA5, 0x24, 0x05, 0x26, 0xD0, 0x10, 0xF4, 0x82, 0x06, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xA2, 0x03, 0x15, 0x22, 0x00, 0x00, 0xE1, 0xA0, 0x04, 0x00, 0xB7, 0x24, 0x09, +0x00, 0x80, 0x97, 0x24, 0xA0, 0x02, 0x00, 0xA7, 0x24, 0x85, 0x28, 0xB7, 0x24, 0x85, 0x2A, 0x60, +0xA5, 0x24, 0x05, 0x26, 0xD0, 0x10, 0xF4, 0x82, 0x06, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, +0x03, 0x15, 0x22, 0x00, 0x00, 0xE1, 0xA0, 0x04, 0x00, 0xB7, 0x24, 0x29, 0xFF, 0x7F, 0x97, 0x24, +0x60, 0xAF, 0xDC, 0x00, 0xE1, 0xA0, 0x06, 0x00, 0x97, 0x1C, 0xAF, 0xDE, 0x00, 0xE1, 0xC8, 0xC8, +0x97, 0x1C, 0xA0, 0x0A, 0x00, 0x20, 0x2B, 0xC5, 0xA7, 0x1C, 0xF0, 0x05, 0xC9, 0x06, 0x00, 0x90, +0x17, 0xE2, 0x30, 0xAF, 0x25, 0xC0, 0x00, 0x48, 0xA9, 0x00, 0x48, 0xC2, 0x30, 0x20, 0x3A, 0xC5, +0x68, 0x98, 0xA0, 0x0E, 0x00, 0x97, 0x1C, 0x60, 0xA0, 0x04, 0x00, 0xB7, 0x1C, 0xA0, 0x0E, 0x00, +0x97, 0x1C, 0xA9, 0x00, 0x00, 0xA0, 0x04, 0x00, 0x97, 0x1C, 0x60, 0xAF, 0xEB, 0x00, 0xE1, 0x97, +0x1C, 0xC8, 0xC8, 0xAF, 0xE9, 0x00, 0xE1, 0x97, 0x1C, 0x60, 0xA0, 0x00, 0x00, 0xA2, 0x00, 0x00, +0xAF, 0xE7, 0x00, 0xE1, 0x3F, 0xA6, 0xBA, 0xFE, 0xD0, 0x05, 0x98, 0x09, 0x80, 0x00, 0xA8, 0xA2, +0x02, 0x00, 0xAF, 0xE7, 0x00, 0xE1, 0x3F, 0xA6, 0xBA, 0xFE, 0xD0, 0x05, 0x98, 0x09, 0x40, 0x00, +0xA8, 0xA2, 0x0E, 0x00, 0xA3, 0x03, 0x48, 0xA3, 0x01, 0x0A, 0x83, 0x01, 0x90, 0x06, 0x98, 0x1F, +0xCA, 0xBA, 0xFE, 0xA8, 0xCA, 0xCA, 0x10, 0xEF, 0x68, 0x60, 0xAF, 0xE1, 0x00, 0xE1, 0xF0, 0x0C, +0x48, 0xDA, 0xA5, 0x16, 0x48, 0xA5, 0x14, 0x48, 0x22, 0xE3, 0x00, 0xE1, 0x60, 0xA9, 0x00, 0x48, +0xAF, 0x00, 0xC0, 0x00, 0x29, 0x7F, 0x48, 0xAF, 0x25, 0xC0, 0x00, 0x48, 0xA9, 0x00, 0x48, 0x8F, +0x10, 0xC0, 0x00, 0xC2, 0x30, 0x20, 0x3A, 0xC5, 0x68, 0xFA, 0xF4, 0x00, 0x00, 0x29, 0x00, 0x08, +0xD0, 0x05, 0xF4, 0x03, 0x00, 0x80, 0x03, 0xF4, 0x05, 0x00, 0x5A, 0xDA, 0xA2, 0x06, 0x14, 0x22, +0x00, 0x00, 0xE1, 0x68, 0xE2, 0x30, 0x18, 0x6B, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x1F, +0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xAF, 0x25, 0xC0, 0x00, 0x48, 0xA9, 0x00, 0x48, 0xC2, 0x30, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x17, 0x22, 0x00, 0x00, 0xE1, +0x68, 0x8F, 0xE7, 0x00, 0xE1, 0x68, 0x8F, 0xEB, 0x00, 0xE1, 0x68, 0x8F, 0xE9, 0x00, 0xE1, 0xAF, +0xE9, 0x00, 0xE1, 0x48, 0xAF, 0xEB, 0x00, 0xE1, 0x48, 0x22, 0x60, 0x00, 0xE1, 0xA3, 0x03, 0x29, +0x04, 0x00, 0xD0, 0x04, 0x68, 0x68, 0x80, 0x6A, 0x20, 0x3A, 0xC5, 0x68, 0x68, 0x5A, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0x98, 0x29, 0x80, 0x00, 0xD0, 0x10, 0xAF, 0xE7, 0x00, 0xE1, 0x0A, 0x0A, +0xB0, 0x18, 0xF4, 0x01, 0x00, 0xA9, 0x00, 0x00, 0x80, 0x36, 0xAF, 0xE7, 0x00, 0xE1, 0x0A, 0x0A, +0x90, 0x08, 0xF4, 0x02, 0x00, 0xA9, 0x00, 0x00, 0x80, 0x26, 0xA3, 0x05, 0xA8, 0x29, 0x40, 0x00, +0xD0, 0x10, 0xAF, 0xE7, 0x00, 0xE1, 0xEB, 0x4A, 0xB0, 0x25, 0xF4, 0x01, 0x00, 0xA9, 0x01, 0x00, +0x80, 0x0E, 0xAF, 0xE7, 0x00, 0xE1, 0xEB, 0x4A, 0x90, 0x15, 0xF4, 0x02, 0x00, 0xA9, 0x01, 0x00, +0x5A, 0x48, 0x83, 0x09, 0xA2, 0x06, 0x14, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x03, 0xF0, 0xCB, 0x68, +0x68, 0x68, 0xE2, 0x30, 0x18, 0x6B, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0xF4, 0x0A, 0x00, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x00, 0xA2, 0x06, 0x14, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xE2, 0x30, 0x18, 0x6B, +0xC2, 0x30, 0xF4, 0x00, 0x00, 0xF4, 0x28, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x06, 0x15, 0x22, 0x00, +0x00, 0xE1, 0x68, 0xE2, 0x30, 0x18, 0x6B, 0xC2, 0x30, 0xA9, 0x01, 0x00, 0x8F, 0xF1, 0x00, 0xE1, +0xF4, 0x00, 0x00, 0xE2, 0x30, 0xAF, 0x25, 0xC0, 0x00, 0x48, 0xA9, 0x00, 0x48, 0xC2, 0x30, 0xF4, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x03, 0x17, 0x22, 0x00, 0x00, 0xE1, 0xA0, +0x00, 0x00, 0xA3, 0x01, 0x29, 0x00, 0x20, 0xF0, 0x08, 0xA3, 0x09, 0x09, 0x02, 0x00, 0x83, 0x09, +0xC8, 0xA3, 0x01, 0x0A, 0x90, 0x05, 0x0A, 0x90, 0x18, 0xB0, 0x03, 0x0A, 0xB0, 0x13, 0xA3, 0x01, +0xEB, 0xAA, 0x29, 0x10, 0x00, 0xF0, 0x06, 0x8A, 0x4A, 0x90, 0x06, 0xB0, 0x0C, 0x8A, 0x4A, 0x90, +0x08, 0xA3, 0x09, 0x09, 0x04, 0x00, 0x83, 0x09, 0xC8, 0x98, 0xF0, 0x03, 0x4C, 0xF0, 0xC5, 0x68, +0x68, 0x68, 0x68, 0x68, 0xE2, 0x30, 0x6B, 0x2B, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, +0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0xD8, 0xC7, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0xE0, +0xC7, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0xE8, 0xC7, 0xFE, 0x00, 0x18, +0xC8, 0xFE, 0x00, 0x06, 0xC8, 0xFE, 0x00, 0x80, 0xC8, 0xFE, 0x00, 0xB0, 0xC8, 0xFE, 0x00, 0xF4, +0xC8, 0xFE, 0x00, 0x70, 0xC9, 0xFE, 0x00, 0x75, 0xC9, 0xFE, 0x00, 0x66, 0xC9, 0xFE, 0x00, 0x6B, +0xC9, 0xFE, 0x00, 0xE9, 0xCA, 0xFE, 0x00, 0xFF, 0xCA, 0xFE, 0x00, 0xB2, 0xCB, 0xFE, 0x00, 0xBE, +0xCB, 0xFE, 0x00, 0xDA, 0xCC, 0xFE, 0x00, 0x43, 0xCE, 0xFE, 0x00, 0x4A, 0xCE, 0xFE, 0x00, 0x54, +0xCE, 0xFE, 0x00, 0x86, 0xCE, 0xFE, 0x00, 0x59, 0xCE, 0xFE, 0x00, 0x8B, 0xCE, 0xFE, 0x00, 0x89, +0xCA, 0xFE, 0x00, 0x8E, 0xCA, 0xFE, 0x00, 0xC5, 0xCE, 0xFE, 0x00, 0xCA, 0xCE, 0xFE, 0x00, 0x1A, +0xCF, 0xFE, 0x00, 0x37, 0xCF, 0xFE, 0x00, 0x92, 0xCF, 0xFE, 0x00, 0xB4, 0xCF, 0xFE, 0x00, 0x4B, +0xD0, 0xFE, 0x00, 0xC8, 0xD0, 0xFE, 0x00, 0x56, 0xD1, 0xFE, 0x00, 0x96, 0xD1, 0xFE, 0x00, 0x7D, +0xD2, 0xFE, 0x00, 0xA2, 0xFF, 0xFF, 0x4C, 0x90, 0xFF, 0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, 0x8B, +0xFF, 0xA9, 0xFF, 0xFF, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0x0B, 0x3B, 0x5B, 0xA5, 0x09, 0x85, 0x0D, +0xA9, 0x00, 0x00, 0xA0, 0x11, 0x00, 0x18, 0x6A, 0x66, 0x0D, 0x90, 0x03, 0x18, 0x65, 0x0B, 0x88, +0xD0, 0xF5, 0x85, 0x0F, 0x4C, 0xC3, 0xFF, 0x0B, 0x3B, 0x5B, 0x22, 0x5D, 0xC8, 0xFE, 0xB0, 0x03, +0x4C, 0xC3, 0xFF, 0xA2, 0x01, 0x0B, 0x4C, 0xC6, 0xFF, 0x0B, 0x3B, 0x5B, 0xA5, 0x0B, 0x48, 0x45, +0x09, 0x48, 0xA5, 0x0B, 0x10, 0x06, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x0B, 0xA5, 0x09, 0x10, 0x06, +0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x09, 0x22, 0x5D, 0xC8, 0xFE, 0xB0, 0x19, 0x68, 0x10, 0x08, 0xA5, +0x0D, 0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x0D, 0x68, 0x10, 0x08, 0xA5, 0x0F, 0x49, 0xFF, 0xFF, 0x1A, +0x85, 0x0F, 0x4C, 0xC3, 0xFF, 0x68, 0x68, 0xA2, 0x01, 0x0B, 0x4C, 0xC6, 0xFF, 0x64, 0x0F, 0xA5, +0x09, 0xD0, 0x02, 0x38, 0x6B, 0xA5, 0x0B, 0x85, 0x0D, 0xA0, 0x10, 0x00, 0x38, 0x26, 0x0D, 0x26, +0x0F, 0x38, 0xA5, 0x0F, 0xE5, 0x09, 0x90, 0x02, 0x85, 0x0F, 0x88, 0xD0, 0xF0, 0x26, 0x0D, 0x18, +0x6B, 0x0B, 0x3B, 0x5B, 0x64, 0x15, 0x64, 0x17, 0xA5, 0x09, 0x85, 0x11, 0xA5, 0x0B, 0x85, 0x13, +0xA0, 0x21, 0x00, 0x18, 0x66, 0x17, 0x66, 0x15, 0x66, 0x13, 0x66, 0x11, 0x90, 0x0D, 0x18, 0xA5, +0x0D, 0x65, 0x15, 0x85, 0x15, 0xA5, 0x0F, 0x65, 0x17, 0x85, 0x17, 0x88, 0xD0, 0xE6, 0x4C, 0xD9, +0xFF, 0x0B, 0x3B, 0x5B, 0xA5, 0x0D, 0x85, 0x11, 0xA5, 0x0F, 0x85, 0x13, 0x64, 0x15, 0x64, 0x17, +0xA5, 0x09, 0x05, 0x0B, 0xD0, 0x03, 0x38, 0x80, 0x26, 0xA0, 0x20, 0x00, 0x38, 0x26, 0x11, 0x26, +0x13, 0x26, 0x15, 0x26, 0x17, 0x38, 0xA5, 0x15, 0xE5, 0x09, 0xAA, 0xA5, 0x17, 0xE5, 0x0B, 0x90, +0x04, 0x85, 0x17, 0x86, 0x15, 0x88, 0xD0, 0xE5, 0x26, 0x11, 0x26, 0x13, 0x4C, 0xD9, 0xFF, 0xA2, +0x01, 0x0B, 0x4C, 0xDC, 0xFF, 0x0B, 0x3B, 0x5B, 0xA5, 0x09, 0xD0, 0x07, 0xA9, 0xFF, 0x7F, 0x85, +0x0F, 0x80, 0x61, 0x45, 0x0B, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA5, 0x0B, 0x10, 0x04, +0x49, 0xFF, 0xFF, 0x1A, 0x48, 0xA5, 0x09, 0x10, 0x04, 0x49, 0xFF, 0xFF, 0x1A, 0x48, 0xA2, 0x0B, +0x0B, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x0F, 0xFA, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xDA, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA5, 0x09, 0x10, 0x04, +0x49, 0xFF, 0xFF, 0x1A, 0x48, 0xA2, 0x0B, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x85, 0x0D, 0x68, +0x68, 0x68, 0x68, 0x10, 0x0F, 0xA9, 0x00, 0x00, 0x38, 0xE5, 0x0D, 0x85, 0x0D, 0xA9, 0x00, 0x00, +0xE5, 0x0F, 0x85, 0x0F, 0x4C, 0xC3, 0xFF, 0xA0, 0x10, 0x00, 0x80, 0x0D, 0xA0, 0x1E, 0x00, 0x80, +0x08, 0xA0, 0x00, 0x00, 0x80, 0x03, 0xA0, 0xE1, 0xFF, 0x0B, 0x3B, 0x5B, 0x64, 0x11, 0x64, 0x13, +0xA5, 0x0F, 0x45, 0x0B, 0x48, 0xA5, 0x0F, 0x10, 0x0F, 0xA9, 0x00, 0x00, 0x38, 0xE5, 0x0D, 0x85, +0x0D, 0xA9, 0x00, 0x00, 0xE5, 0x0F, 0x85, 0x0F, 0xA5, 0x0B, 0x10, 0x0F, 0xA9, 0x00, 0x00, 0x38, +0xE5, 0x09, 0x85, 0x09, 0xA9, 0x00, 0x00, 0xE5, 0x0B, 0x85, 0x0B, 0x98, 0xD0, 0x33, 0xA0, 0x20, +0x00, 0x06, 0x11, 0x26, 0x13, 0x2A, 0x30, 0x51, 0x26, 0x09, 0x26, 0x0B, 0x90, 0x14, 0xAA, 0x18, +0xA5, 0x0D, 0x65, 0x11, 0x85, 0x11, 0xA5, 0x0F, 0x65, 0x13, 0x85, 0x13, 0x8A, 0x90, 0x03, 0x1A, +0x30, 0x37, 0x88, 0xD0, 0xDC, 0x06, 0x11, 0xA6, 0x13, 0x86, 0x11, 0x85, 0x13, 0xB0, 0x3E, 0x90, +0x46, 0x10, 0x59, 0x46, 0x13, 0x66, 0x11, 0x66, 0x0B, 0x66, 0x09, 0x90, 0x0D, 0x18, 0xA5, 0x0D, +0x65, 0x11, 0x85, 0x11, 0xA5, 0x0F, 0x65, 0x13, 0x85, 0x13, 0xC8, 0x30, 0xE6, 0xD0, 0x1A, 0x46, +0x09, 0x90, 0x16, 0x06, 0x0D, 0x26, 0x0F, 0x90, 0xE5, 0x64, 0x11, 0xA9, 0x00, 0x80, 0x85, 0x13, +0x68, 0x30, 0x26, 0xC6, 0x11, 0xC6, 0x13, 0x80, 0x20, 0x24, 0x0B, 0x10, 0x06, 0xE6, 0x11, 0xD0, +0x02, 0xE6, 0x13, 0x24, 0x13, 0x30, 0xE2, 0x68, 0x10, 0x0F, 0xA9, 0x00, 0x00, 0x38, 0xE5, 0x11, +0x85, 0x11, 0xA9, 0x00, 0x00, 0xE5, 0x13, 0x85, 0x13, 0x4C, 0xD9, 0xFF, 0xA5, 0x0D, 0x85, 0x11, +0x64, 0x0D, 0xA5, 0x0F, 0x85, 0x13, 0x64, 0x0F, 0x5A, 0xA0, 0x20, 0x00, 0x18, 0x26, 0x11, 0x26, +0x13, 0x26, 0x0D, 0x26, 0x0F, 0x38, 0xA5, 0x0D, 0xE5, 0x09, 0xAA, 0xA5, 0x0F, 0xE5, 0x0B, 0x90, +0x04, 0x85, 0x0F, 0x86, 0x0D, 0x88, 0xD0, 0xE5, 0x7A, 0x26, 0x11, 0x26, 0x13, 0x30, 0x9A, 0x26, +0x0D, 0x26, 0x0F, 0x38, 0xA5, 0x0D, 0xE5, 0x09, 0xAA, 0xA5, 0x0F, 0xE5, 0x0B, 0x90, 0x04, 0x85, +0x0F, 0x86, 0x0D, 0x88, 0x10, 0xE3, 0xB0, 0x95, 0x90, 0x9D, 0xA2, 0x0E, 0x40, 0x80, 0x03, 0xA2, +0x00, 0x40, 0x0B, 0x3B, 0x5B, 0xA9, 0x00, 0x00, 0xA8, 0x97, 0x09, 0xC8, 0xC8, 0x97, 0x09, 0xC8, +0xC8, 0xA5, 0x0F, 0x48, 0x10, 0x11, 0xA9, 0x00, 0x00, 0x38, 0xE5, 0x0D, 0x85, 0x0D, 0xA9, 0x00, +0x00, 0xE5, 0x0F, 0x85, 0x0F, 0x80, 0x18, 0xD0, 0x16, 0xA5, 0x0D, 0xD0, 0x0D, 0x97, 0x09, 0xC8, +0xC8, 0x97, 0x09, 0xC8, 0xC8, 0x97, 0x09, 0x68, 0x80, 0x1D, 0xCA, 0x06, 0x0D, 0x26, 0x0F, 0x10, +0xF9, 0xA5, 0x0D, 0x97, 0x09, 0xC8, 0xC8, 0xA5, 0x0F, 0x97, 0x09, 0xC8, 0xC8, 0x68, 0x85, 0x0F, +0x8A, 0x0A, 0x06, 0x0F, 0x6A, 0x97, 0x09, 0x4C, 0xD9, 0xFF, 0x0B, 0x3B, 0x5B, 0xA6, 0x0B, 0x86, +0x0D, 0xA5, 0x09, 0x10, 0x08, 0xE8, 0xE0, 0x00, 0x80, 0xF0, 0x02, 0x86, 0x0D, 0x4C, 0xC3, 0xFF, +0x0B, 0x3B, 0x5B, 0x64, 0x0F, 0x38, 0xA5, 0x0B, 0xE9, 0x00, 0x40, 0x90, 0x07, 0x85, 0x0B, 0xA9, +0x00, 0x40, 0x85, 0x0F, 0xA9, 0x00, 0x10, 0x85, 0x0D, 0x38, 0xA5, 0x0B, 0xE5, 0x0F, 0x90, 0x0F, +0xE5, 0x0D, 0x90, 0x0B, 0x85, 0x0B, 0x18, 0xA5, 0x0F, 0x65, 0x0D, 0x65, 0x0D, 0x85, 0x0F, 0x06, +0x09, 0x26, 0x0B, 0x46, 0x0D, 0x90, 0xE2, 0xA5, 0x09, 0xAA, 0x64, 0x09, 0x66, 0x09, 0x38, 0xE5, +0x0D, 0xA8, 0xA5, 0x0B, 0xE5, 0x0F, 0x90, 0x1B, 0x48, 0x98, 0xE5, 0x09, 0xA8, 0x68, 0xE9, 0x00, +0x00, 0x90, 0x10, 0x85, 0x0B, 0xBB, 0x18, 0xA5, 0x0D, 0x65, 0x09, 0x65, 0x09, 0x85, 0x0D, 0x90, +0x02, 0xE6, 0x0F, 0x8A, 0x0A, 0xAA, 0x26, 0x0B, 0x46, 0x09, 0x90, 0xD2, 0x38, 0xE5, 0x0D, 0xA8, +0xA5, 0x0B, 0xE5, 0x0F, 0x90, 0x18, 0x48, 0xA5, 0x09, 0xE9, 0x00, 0x80, 0x98, 0xE5, 0x09, 0xA8, +0x68, 0xE5, 0x09, 0x90, 0x09, 0x85, 0x0B, 0xBB, 0xE6, 0x0D, 0xD0, 0x02, 0xE6, 0x0F, 0x8A, 0x2A, +0x26, 0x0B, 0x38, 0xE5, 0x0D, 0xA8, 0xA5, 0x0B, 0xE5, 0x0F, 0x90, 0x14, 0x48, 0xA5, 0x09, 0xE9, +0x00, 0x40, 0x98, 0xE5, 0x09, 0x68, 0xE5, 0x09, 0x90, 0x06, 0xE6, 0x0D, 0xD0, 0x02, 0xE6, 0x0F, +0x4C, 0xC3, 0xFF, 0x0B, 0x3B, 0x5B, 0xA2, 0x02, 0x00, 0x24, 0x0B, 0x30, 0x0F, 0x10, 0x1C, 0x0B, +0x3B, 0x5B, 0xA2, 0x00, 0x00, 0x24, 0x0B, 0x10, 0x12, 0xA2, 0x04, 0x00, 0x38, 0xA9, 0x00, 0x00, +0xE5, 0x09, 0x85, 0x09, 0xA9, 0x00, 0x00, 0xE5, 0x0B, 0x85, 0x0B, 0xA0, 0x10, 0x00, 0x38, 0xA5, +0x0B, 0xE9, 0x88, 0x64, 0x30, 0x02, 0x85, 0x0B, 0x26, 0x09, 0x26, 0x0B, 0x88, 0xD0, 0xEF, 0x18, +0x8A, 0x65, 0x09, 0x48, 0x4A, 0x90, 0x07, 0xA9, 0x10, 0xC9, 0xE5, 0x0B, 0x85, 0x0B, 0x64, 0x09, +0x46, 0x0B, 0x66, 0x09, 0x46, 0x0B, 0x66, 0x09, 0x46, 0x0B, 0x66, 0x09, 0x48, 0x48, 0xD4, 0x0B, +0xD4, 0x09, 0xD4, 0x0B, 0xD4, 0x09, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x7A, 0x84, 0x0D, +0xFA, 0x86, 0x0F, 0x68, 0x48, 0x1A, 0x29, 0x02, 0x00, 0xD0, 0x4B, 0x48, 0x48, 0xDA, 0x5A, 0xF4, +0xA2, 0x10, 0xF4, 0xE5, 0x08, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x69, 0x4D, +0x31, 0xA8, 0x68, 0x69, 0xB3, 0xAA, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0F, 0xD4, 0x0D, 0xA2, 0x0B, +0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x69, 0x09, 0xD6, 0xA8, 0x68, 0x69, 0xFF, 0x7F, 0x48, +0x48, 0x48, 0x5A, 0xD4, 0x0B, 0xD4, 0x09, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x7A, 0x84, +0x0D, 0xFA, 0x86, 0x0F, 0x80, 0x4D, 0x48, 0x48, 0xDA, 0x5A, 0xF4, 0x6E, 0xFA, 0xF4, 0x42, 0x2A, +0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x69, 0x9A, 0xF2, 0xA8, 0x68, 0x69, 0xA7, +0x2A, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0F, 0xD4, 0x0D, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, +0x18, 0x68, 0x69, 0xA7, 0x11, 0xA8, 0x68, 0x69, 0x00, 0x80, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0F, +0xD4, 0x0D, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x85, 0x0D, 0x68, 0x69, 0x00, +0x40, 0x85, 0x0F, 0x68, 0x29, 0x04, 0x00, 0xF0, 0x0F, 0x38, 0xA9, 0x00, 0x00, 0xE5, 0x0D, 0x85, +0x0D, 0xA9, 0x00, 0x00, 0xE5, 0x0F, 0x85, 0x0F, 0x4C, 0xC3, 0xFF, 0x0B, 0x3B, 0x5B, 0x64, 0x11, +0xA5, 0x0B, 0x0A, 0x66, 0x11, 0x10, 0x0F, 0xA9, 0x00, 0x00, 0x38, 0xE5, 0x09, 0x85, 0x09, 0xA9, +0x00, 0x00, 0xE5, 0x0B, 0x85, 0x0B, 0xA5, 0x0F, 0x0A, 0x66, 0x11, 0x10, 0x0F, 0xA9, 0x00, 0x00, +0x38, 0xE5, 0x0D, 0x85, 0x0D, 0xA9, 0x00, 0x00, 0xE5, 0x0F, 0x85, 0x0F, 0x38, 0xA5, 0x0D, 0xE5, +0x09, 0xA5, 0x0F, 0xE5, 0x0B, 0x66, 0x11, 0xD4, 0x11, 0x64, 0x13, 0xA5, 0x0F, 0x05, 0x0D, 0xD0, +0x05, 0x64, 0x11, 0x82, 0xE3, 0x00, 0xA5, 0x0B, 0x05, 0x09, 0xF0, 0xF5, 0x48, 0x48, 0xA5, 0x11, +0x30, 0x0A, 0xD4, 0x0F, 0xD4, 0x0D, 0xD4, 0x0B, 0xD4, 0x09, 0x80, 0x08, 0xD4, 0x0B, 0xD4, 0x09, +0xD4, 0x0F, 0xD4, 0x0D, 0xA2, 0x0B, 0x12, 0x22, 0x00, 0x00, 0xE1, 0x7A, 0x84, 0x09, 0xFA, 0x86, +0x0B, 0x48, 0x48, 0xDA, 0x5A, 0xDA, 0x5A, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x7A, 0x84, +0x0D, 0xFA, 0x86, 0x0F, 0x48, 0x48, 0xDA, 0x5A, 0xF4, 0x3F, 0xFF, 0xF4, 0x62, 0xFE, 0xA2, 0x0B, +0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x69, 0xFE, 0x92, 0xA8, 0x68, 0x69, 0x5E, 0x03, 0x48, +0x48, 0x48, 0x5A, 0xD4, 0x0F, 0xD4, 0x0D, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, +0x69, 0xF2, 0x77, 0xA8, 0x68, 0x69, 0x8C, 0xF8, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0F, 0xD4, 0x0D, +0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x69, 0x2C, 0xF7, 0xA8, 0x68, 0x69, 0x62, +0x0C, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0F, 0xD4, 0x0D, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, +0x18, 0x68, 0x69, 0xBE, 0x4E, 0xA8, 0x68, 0x69, 0xB6, 0xEA, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0F, +0xD4, 0x0D, 0xA2, 0x0B, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x18, 0x68, 0x69, 0x73, 0xA0, 0xA8, 0x68, +0x69, 0xFF, 0x3F, 0x48, 0x48, 0x48, 0x5A, 0xD4, 0x0B, 0xD4, 0x09, 0xA2, 0x0B, 0x10, 0x22, 0x00, +0x00, 0xE1, 0x68, 0x7A, 0x84, 0x11, 0x0A, 0x26, 0x11, 0x26, 0x13, 0x0A, 0x26, 0x11, 0x26, 0x13, +0x0A, 0x90, 0x06, 0xE6, 0x11, 0xD0, 0x02, 0xE6, 0x13, 0x68, 0x0A, 0x85, 0x0D, 0xB0, 0x0E, 0xA9, +0x20, 0x92, 0xE5, 0x11, 0x85, 0x11, 0xA9, 0x01, 0x00, 0xE5, 0x13, 0x85, 0x13, 0x06, 0x0D, 0x90, +0x0E, 0xA9, 0x40, 0x24, 0xE5, 0x11, 0x85, 0x11, 0xA9, 0x03, 0x00, 0xE5, 0x13, 0x85, 0x13, 0x06, +0x0D, 0x90, 0x0E, 0xA9, 0x00, 0x00, 0xE5, 0x11, 0x85, 0x11, 0xA9, 0x00, 0x00, 0xE5, 0x13, 0x85, +0x13, 0x4C, 0xD9, 0xFF, 0x0B, 0x3B, 0x5B, 0xA5, 0x0B, 0x80, 0x05, 0x0B, 0x3B, 0x5B, 0xA5, 0x09, +0x85, 0x0D, 0x4C, 0xC3, 0xFF, 0xA2, 0x0F, 0x00, 0x80, 0x03, 0xA2, 0x0D, 0x00, 0x0B, 0x3B, 0x5B, +0xA5, 0x09, 0x85, 0x0D, 0xA5, 0x0B, 0x85, 0x0F, 0x48, 0x10, 0x11, 0xA9, 0x00, 0x00, 0x38, 0xE5, +0x0D, 0x85, 0x0D, 0xA9, 0x00, 0x00, 0xE5, 0x0F, 0x85, 0x0F, 0x30, 0x33, 0x06, 0x0D, 0x26, 0x0F, +0x30, 0x2D, 0xCA, 0x10, 0xF7, 0x80, 0x7F, 0xA2, 0x0F, 0x00, 0x80, 0x03, 0xA2, 0x0D, 0x00, 0x0B, +0x3B, 0x5B, 0xA5, 0x09, 0x85, 0x0D, 0xA5, 0x0B, 0x85, 0x0F, 0x48, 0x10, 0x0F, 0xA9, 0x00, 0x00, +0x38, 0xE5, 0x0D, 0x85, 0x0D, 0xA9, 0x00, 0x00, 0xE5, 0x0F, 0x85, 0x0F, 0x8A, 0x80, 0x44, 0x64, +0x0D, 0xA9, 0x00, 0x80, 0x85, 0x0F, 0x68, 0x30, 0x5F, 0xC6, 0x0D, 0xC6, 0x0F, 0x80, 0x59, 0x64, +0x0D, 0x64, 0x0F, 0x68, 0x80, 0x52, 0xA2, 0x0E, 0x40, 0x80, 0x03, 0xA2, 0x00, 0x40, 0x0B, 0x3B, +0x5B, 0xA0, 0x04, 0x00, 0xB7, 0x09, 0x85, 0x0D, 0xC8, 0xC8, 0xB7, 0x09, 0x85, 0x0F, 0xC8, 0xC8, +0xB7, 0x09, 0x48, 0x29, 0xFF, 0x7F, 0x85, 0x09, 0x8A, 0x18, 0xE5, 0x09, 0x30, 0xC1, 0xC9, 0x21, +0x00, 0x10, 0xCC, 0x46, 0x0F, 0x66, 0x0D, 0x3A, 0x10, 0xF9, 0x90, 0x06, 0xE6, 0x0D, 0xD0, 0x02, +0xE6, 0x0F, 0x24, 0x0F, 0x30, 0xA9, 0x68, 0x10, 0x0F, 0xA9, 0x00, 0x00, 0x38, 0xE5, 0x0D, 0x85, +0x0D, 0xA9, 0x00, 0x00, 0xE5, 0x0F, 0x85, 0x0F, 0x4C, 0xC3, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0x3B, 0x5B, 0xA5, 0x13, 0x85, 0x01, 0x20, 0x59, 0xCF, 0x68, 0x68, 0xE0, 0x00, 0x00, +0xD0, 0x03, 0x4C, 0xD9, 0xFF, 0x4C, 0xDC, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x3B, +0x5B, 0xA5, 0x13, 0x85, 0x01, 0xA5, 0x15, 0x85, 0x03, 0x20, 0x59, 0xCF, 0x68, 0x68, 0xE0, 0x00, +0x00, 0xD0, 0x03, 0x4C, 0x97, 0xFF, 0x4C, 0x9A, 0xFF, 0xA4, 0x0D, 0x88, 0x30, 0x1A, 0xA5, 0x01, +0x29, 0x0F, 0x00, 0x20, 0x86, 0xCF, 0xE2, 0x30, 0x97, 0x0F, 0xC2, 0x30, 0xA2, 0x04, 0x00, 0x46, +0x03, 0x66, 0x01, 0xCA, 0xD0, 0xF9, 0x80, 0xE3, 0xA5, 0x01, 0x05, 0x03, 0xD0, 0x04, 0xA2, 0x00, +0x00, 0x60, 0xA2, 0x04, 0x0B, 0x60, 0xC9, 0x0A, 0x00, 0x90, 0x04, 0x18, 0x69, 0x07, 0x00, 0x69, +0x30, 0x00, 0x60, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x3B, 0x5B, 0x20, +0xD3, 0xCF, 0x68, 0x85, 0x15, 0x68, 0xD0, 0x06, 0xFA, 0xD0, 0x07, 0x4C, 0xCE, 0xFF, 0xA2, 0x03, +0x0B, 0x68, 0x4C, 0xD1, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x3B, +0x5B, 0x20, 0xD3, 0xCF, 0x68, 0x85, 0x15, 0x68, 0x85, 0x17, 0xFA, 0xD0, 0x03, 0x4C, 0xCE, 0xFF, +0x4C, 0xD1, 0xFF, 0xA0, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x88, 0xC8, 0xC4, 0x0F, 0xB0, 0x41, 0xB7, +0x11, 0x29, 0x7F, 0x00, 0xC9, 0x20, 0x00, 0xF0, 0xF1, 0xC4, 0x0F, 0xB0, 0x2B, 0xB7, 0x11, 0x29, +0x7F, 0x00, 0x20, 0x23, 0xD0, 0x85, 0x05, 0xA5, 0x03, 0xC9, 0x00, 0x10, 0x90, 0x01, 0xE8, 0x06, +0x01, 0x26, 0x03, 0x06, 0x01, 0x26, 0x03, 0x06, 0x01, 0x26, 0x03, 0x06, 0x01, 0x26, 0x03, 0xA5, +0x01, 0x05, 0x05, 0x85, 0x01, 0xC8, 0x80, 0xD1, 0xE0, 0x00, 0x00, 0xF0, 0x03, 0xA2, 0x03, 0x0B, +0x86, 0x05, 0x60, 0xC9, 0x3A, 0x00, 0x90, 0x16, 0xC9, 0x47, 0x00, 0x90, 0x09, 0xC9, 0x67, 0x00, +0xB0, 0x13, 0x38, 0xE9, 0x20, 0x00, 0xC9, 0x41, 0x00, 0x90, 0x0A, 0xE9, 0x07, 0x00, 0x38, 0xE9, +0x30, 0x00, 0x90, 0x01, 0x60, 0x68, 0xA2, 0x02, 0x0B, 0x4C, 0x20, 0xD0, 0x0B, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x3B, 0x5B, 0xA4, 0x11, 0xA5, 0x17, 0x85, 0x01, 0x10, 0x0C, +0xA5, 0x0F, 0xF0, 0x08, 0x38, 0xA9, 0x00, 0x00, 0xE5, 0x01, 0x85, 0x01, 0x88, 0x30, 0x51, 0x64, +0x05, 0xA2, 0x10, 0x00, 0x18, 0x26, 0x01, 0x26, 0x05, 0x38, 0xA5, 0x05, 0xE9, 0x0A, 0x00, 0x90, +0x02, 0x85, 0x05, 0xCA, 0xD0, 0xEF, 0x26, 0x01, 0xA5, 0x05, 0x18, 0x69, 0x30, 0x00, 0xE2, 0x30, +0x97, 0x13, 0xC2, 0x30, 0xA5, 0x01, 0xD0, 0xD4, 0xA5, 0x0F, 0xF0, 0x10, 0xA5, 0x17, 0x10, 0x0C, +0x88, 0x30, 0x1D, 0xA9, 0x2D, 0x00, 0xE2, 0x30, 0x97, 0x13, 0xC2, 0x30, 0x88, 0x30, 0x0B, 0xE2, +0x30, 0xA9, 0x20, 0x97, 0x13, 0x88, 0x10, 0xF9, 0xC2, 0x30, 0x68, 0x68, 0x68, 0x4C, 0x97, 0xFF, +0xA2, 0x04, 0x0B, 0x68, 0x68, 0x68, 0x4C, 0x9A, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0x3B, 0x5B, 0xA4, 0x11, 0xA5, 0x17, 0x85, 0x01, 0xA5, 0x19, 0x85, 0x03, 0x10, +0x13, 0xA5, 0x0F, 0xF0, 0x0F, 0x38, 0xA9, 0x00, 0x00, 0xE5, 0x01, 0x85, 0x01, 0xA9, 0x00, 0x00, +0xE5, 0x03, 0x85, 0x03, 0x88, 0x30, 0x57, 0x64, 0x05, 0xA2, 0x20, 0x00, 0x18, 0x26, 0x01, 0x26, +0x03, 0x26, 0x05, 0x38, 0xA5, 0x05, 0xE9, 0x0A, 0x00, 0x90, 0x02, 0x85, 0x05, 0xCA, 0xD0, 0xED, +0x26, 0x01, 0x26, 0x03, 0xA5, 0x05, 0x18, 0x69, 0x30, 0x00, 0xE2, 0x30, 0x97, 0x13, 0xC2, 0x30, +0xA5, 0x01, 0x05, 0x02, 0xD0, 0xCE, 0xA5, 0x0F, 0xF0, 0x10, 0xA5, 0x19, 0x10, 0x0C, 0x88, 0x30, +0x1D, 0xA9, 0x2D, 0x00, 0xE2, 0x30, 0x97, 0x13, 0xC2, 0x30, 0x88, 0x30, 0x0B, 0xE2, 0x30, 0xA9, +0x20, 0x97, 0x13, 0x88, 0x10, 0xF9, 0xC2, 0x30, 0x68, 0x68, 0x68, 0x4C, 0xA2, 0xFF, 0xA2, 0x04, +0x0B, 0x68, 0x68, 0x68, 0x4C, 0xA5, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0x3B, 0x5B, 0x20, 0xE4, 0xD1, 0x68, 0x85, 0x17, 0x68, 0xD0, 0x24, 0xA5, 0x0F, 0xF0, 0x0F, +0xA5, 0x17, 0xC9, 0x00, 0x80, 0xD0, 0x05, 0xC0, 0x00, 0x00, 0xD0, 0x03, 0x0A, 0xB0, 0x11, 0xFA, +0xD0, 0x12, 0x98, 0xF0, 0x08, 0x38, 0xA9, 0x00, 0x00, 0xE5, 0x17, 0x85, 0x17, 0x4C, 0xD9, 0xFF, +0xA2, 0x03, 0x0B, 0x68, 0x4C, 0xDC, 0xFF, 0x0B, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x00, 0x3B, 0x5B, 0x20, 0xE4, 0xD1, 0x68, 0x85, 0x17, 0x68, 0x85, 0x19, 0xA5, 0x0F, 0xF0, 0x15, +0xA5, 0x19, 0xC9, 0x00, 0x80, 0xD0, 0x09, 0xA5, 0x17, 0xD0, 0x05, 0xC0, 0x00, 0x00, 0xD0, 0x05, +0xA5, 0x19, 0x0A, 0xB0, 0x18, 0xFA, 0xD0, 0x19, 0x98, 0xF0, 0x0F, 0x38, 0xA9, 0x00, 0x00, 0xE5, +0x17, 0x85, 0x17, 0xA9, 0x00, 0x00, 0xE5, 0x19, 0x85, 0x19, 0x4C, 0xD9, 0xFF, 0xA2, 0x03, 0x0B, +0x68, 0x4C, 0xDC, 0xFF, 0xA0, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x88, 0xC8, 0xC4, 0x11, 0x90, 0x01, +0x60, 0xB7, 0x13, 0x29, 0x7F, 0x00, 0xC9, 0x20, 0x00, 0xF0, 0xF0, 0xE4, 0x0F, 0xF0, 0x11, 0xC9, +0x2B, 0x00, 0xD0, 0x03, 0xC8, 0x80, 0x09, 0xC9, 0x2D, 0x00, 0xD0, 0x04, 0xC8, 0xA2, 0xFF, 0x00, +0xDA, 0xA2, 0x00, 0x00, 0xC4, 0x11, 0xB0, 0x54, 0xB7, 0x13, 0x29, 0x7F, 0x00, 0xC9, 0x30, 0x00, +0x90, 0x56, 0xC9, 0x3A, 0x00, 0xB0, 0x51, 0x38, 0xE9, 0x30, 0x00, 0x85, 0x05, 0x06, 0x01, 0x26, +0x03, 0x90, 0x01, 0xE8, 0xA5, 0x03, 0x85, 0x17, 0xA5, 0x01, 0x06, 0x01, 0x26, 0x03, 0x90, 0x01, +0xE8, 0x06, 0x01, 0x26, 0x03, 0x90, 0x02, 0xE8, 0x18, 0x65, 0x01, 0x85, 0x01, 0xA5, 0x17, 0x65, +0x03, 0x85, 0x03, 0x90, 0x02, 0xE8, 0x18, 0xA5, 0x01, 0x65, 0x05, 0x85, 0x01, 0x90, 0x0A, 0xA5, +0x03, 0x69, 0x00, 0x00, 0x85, 0x03, 0x90, 0x01, 0xE8, 0xC8, 0x80, 0xA8, 0xE0, 0x00, 0x00, 0xF0, +0x03, 0xA2, 0x03, 0x0B, 0x86, 0x05, 0x7A, 0x60, 0xA2, 0x02, 0x0B, 0x4C, 0x74, 0xD2, 0xE2, 0x30, +0xA3, 0x07, 0x29, 0xF0, 0x4A, 0x4A, 0x4A, 0x4A, 0x20, 0xB1, 0xD2, 0x83, 0x0B, 0xA3, 0x07, 0x29, +0x0F, 0x20, 0xB1, 0xD2, 0x83, 0x0C, 0xA3, 0x08, 0x29, 0xF0, 0x4A, 0x4A, 0x4A, 0x4A, 0x20, 0xB1, +0xD2, 0x83, 0x09, 0xA3, 0x08, 0x29, 0x0F, 0x20, 0xB1, 0xD2, 0x83, 0x0A, 0xC2, 0x30, 0x4C, 0xB7, +0xFF, 0xC9, 0x0A, 0x90, 0x03, 0x18, 0x69, 0x07, 0x69, 0x30, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x8A, +0xFF, 0xFE, 0x00, 0xEA, 0xD2, 0xFE, 0x00, 0x09, 0xD3, 0xFE, 0x00, 0x1F, 0xD3, 0xFE, 0x00, 0x8A, +0xFF, 0xFE, 0x00, 0x27, 0xD3, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0x8A, 0xFF, 0xFE, 0x00, 0xB7, +0xD3, 0xFE, 0x00, 0x46, 0xE9, 0xFE, 0x00, 0x14, 0xEF, 0xFE, 0x00, 0xA3, 0x07, 0x0B, 0x5B, 0x64, +0x18, 0x64, 0x1A, 0x64, 0x1C, 0x2B, 0xF4, 0x00, 0x00, 0xF4, 0x0A, 0x00, 0xF4, 0x00, 0x00, 0x48, +0xA2, 0x01, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0xB7, 0xFF, 0xF4, 0x00, 0x00, 0xF4, 0x0A, 0x00, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x01, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0x4C, 0x8B, 0xFF, +0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, 0x8B, 0xFF, 0xC9, 0x00, 0x00, 0xF0, 0xF6, 0xA9, 0xFF, 0xFF, +0x80, 0xF1, 0x08, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, +0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x16, 0x00, +0x0A, 0x00, 0x08, 0x00, 0x06, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x08, 0x00, 0x18, 0x00, +0x0C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x3C, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x00, +0x00, 0x00, 0x01, 0x3C, 0x81, 0x3F, 0x1E, 0x40, 0x0E, 0x40, 0x3E, 0x40, 0x00, 0x00, 0x42, 0x00, +0x37, 0x00, 0x1A, 0x00, 0x22, 0x00, 0x12, 0x00, 0x42, 0x00, 0x62, 0x00, 0x62, 0x00, 0xFF, 0x7F, +0xFF, 0x43, 0x7F, 0x40, 0x1E, 0x40, 0x0E, 0x40, 0x3E, 0x40, 0xFF, 0x7F, 0x30, 0x49, 0x4E, 0x4E, +0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, +0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x22, 0x64, 0x00, 0xE1, 0x0B, 0x5B, 0x68, 0x85, +0x06, 0x8B, 0x8B, 0x68, 0x85, 0x08, 0x4B, 0xAB, 0x80, 0x04, 0x22, 0x64, 0x00, 0xE1, 0x68, 0x85, +0x00, 0x68, 0x85, 0x02, 0x68, 0x85, 0x04, 0x64, 0x38, 0x64, 0x1E, 0x64, 0x4E, 0x64, 0x50, 0x68, +0x85, 0x0A, 0xEB, 0xA8, 0x29, 0x07, 0x00, 0x0A, 0x85, 0x2E, 0xAA, 0x98, 0x29, 0x70, 0x00, 0xF0, +0x03, 0x4A, 0x4A, 0x4A, 0x85, 0x30, 0xA5, 0x0A, 0x29, 0x1F, 0x00, 0x85, 0x36, 0xA8, 0x4A, 0x90, +0x05, 0xB9, 0xAC, 0xD4, 0x48, 0x60, 0xC9, 0x07, 0x00, 0x90, 0x09, 0xC9, 0x0F, 0x00, 0xD0, 0x72, +0xA6, 0x2E, 0x86, 0x30, 0x86, 0x32, 0xA6, 0x30, 0x86, 0x2E, 0x20, 0xAB, 0xD8, 0xA5, 0x10, 0x85, +0x0C, 0xA5, 0x12, 0x85, 0x0E, 0x20, 0x6D, 0xD8, 0xA6, 0x32, 0x86, 0x2E, 0xBC, 0x52, 0xD3, 0xC4, +0x42, 0x10, 0x02, 0xA4, 0x42, 0x84, 0x34, 0x20, 0xAB, 0xD8, 0xA5, 0x3C, 0x45, 0x46, 0x85, 0x50, +0xA5, 0x30, 0x85, 0x2E, 0xA9, 0xFD, 0xFF, 0xC5, 0x3A, 0x10, 0x06, 0xC5, 0x44, 0x30, 0x2F, 0x10, +0x1B, 0xC5, 0x44, 0x30, 0x06, 0xA5, 0x58, 0xC5, 0x72, 0x90, 0x11, 0x20, 0x4E, 0xD8, 0x38, 0xB0, +0x0E, 0x20, 0x1E, 0xD7, 0xA2, 0x01, 0x01, 0x86, 0x20, 0x4C, 0xFE, 0xD7, 0x20, 0x8C, 0xD8, 0xA5, +0x36, 0xC9, 0x08, 0x00, 0xF0, 0xEE, 0xC9, 0x0A, 0x00, 0xF0, 0xE6, 0x4C, 0xFB, 0xD7, 0xAD, 0xA9, +0xD4, 0x48, 0xA4, 0x36, 0xB9, 0x89, 0xD4, 0x48, 0x60, 0x9D, 0xDC, 0x92, 0xDC, 0xDC, 0xE7, 0x0B, +0xDE, 0xC8, 0xD4, 0xC8, 0xD4, 0x20, 0xDF, 0x5E, 0xD5, 0x6D, 0xD5, 0x88, 0xD5, 0xCA, 0xD5, 0xE2, +0xD5, 0x9D, 0xD5, 0x13, 0xD6, 0x79, 0xD6, 0x8A, 0xD6, 0xFA, 0xD7, 0x2B, 0xD8, 0x25, 0xD7, 0x2B, +0xD7, 0x32, 0xD7, 0x3B, 0xD7, 0x32, 0xE6, 0xEE, 0xE0, 0x46, 0xD7, 0x76, 0xD7, 0x99, 0xD7, 0x00, +0x00, 0xCF, 0xD7, 0xDE, 0xD7, 0xEF, 0xD7, 0xD5, 0xD7, 0x68, 0xAD, 0xAB, 0xD4, 0x48, 0xA5, 0x3A, +0x30, 0x05, 0xA9, 0xFF, 0xFF, 0x80, 0x05, 0xAA, 0xE8, 0x30, 0x01, 0x8A, 0xA6, 0x3C, 0xD0, 0x04, +0x49, 0xFF, 0xFF, 0x1A, 0x85, 0x24, 0xA5, 0x44, 0x30, 0x05, 0xA9, 0xFF, 0xFF, 0x80, 0x05, 0xAA, +0xE8, 0x30, 0x01, 0x8A, 0xA6, 0x46, 0xD0, 0x04, 0x49, 0xFF, 0xFF, 0x1A, 0xC5, 0x24, 0x30, 0x50, +0xD0, 0x57, 0x4A, 0x90, 0x42, 0x38, 0xA5, 0x48, 0xE5, 0x3E, 0xA8, 0xA5, 0x4A, 0xE5, 0x40, 0x30, +0x3B, 0xD0, 0x42, 0x98, 0xD0, 0x3F, 0xA6, 0x4C, 0xE4, 0x42, 0x10, 0x12, 0xA6, 0x42, 0x74, 0x72, +0xCA, 0xCA, 0xE4, 0x4C, 0xD0, 0xF8, 0xA6, 0x42, 0x10, 0x0A, 0x74, 0x58, 0xCA, 0xCA, 0xE4, 0x42, +0xD0, 0xF8, 0xA6, 0x4C, 0x86, 0x24, 0xA2, 0xFE, 0xFF, 0xE8, 0xE8, 0xB5, 0x72, 0xD5, 0x58, 0x90, +0x0B, 0xD0, 0x12, 0xE4, 0x24, 0x30, 0xF2, 0xA2, 0x02, 0x00, 0x80, 0x10, 0xA5, 0x46, 0xD0, 0x09, +0xA2, 0x80, 0x80, 0x80, 0x07, 0xA5, 0x46, 0xD0, 0xF7, 0xA2, 0x40, 0x40, 0x86, 0x20, 0x60, 0x68, +0x85, 0x0C, 0x68, 0x85, 0x0E, 0x20, 0xAB, 0xD8, 0xA5, 0x30, 0x85, 0x2E, 0x80, 0x15, 0x68, 0x85, +0x0C, 0x68, 0x85, 0x0E, 0xA5, 0x2E, 0x85, 0x32, 0xA5, 0x30, 0x85, 0x2E, 0x20, 0xAB, 0xD8, 0xA5, +0x32, 0x85, 0x2E, 0x20, 0x8C, 0xD8, 0x4C, 0xFB, 0xD7, 0xA5, 0x2E, 0x85, 0x30, 0x20, 0xAB, 0xD8, +0xA5, 0x10, 0x85, 0x0C, 0xA5, 0x12, 0x85, 0x0E, 0x20, 0x25, 0xE0, 0x4C, 0xFB, 0xD7, 0x20, 0xAB, +0xD8, 0xA5, 0x10, 0x85, 0x14, 0xA5, 0x12, 0x85, 0x16, 0xA5, 0x10, 0x85, 0x0C, 0xA5, 0x12, 0x85, +0x0E, 0x20, 0x6D, 0xD8, 0x18, 0x68, 0xAA, 0x65, 0x48, 0x85, 0x48, 0x8A, 0x30, 0x04, 0xA5, 0x38, +0xF0, 0x03, 0xA9, 0xFF, 0xFF, 0x65, 0x4A, 0x85, 0x4A, 0x80, 0xB8, 0x20, 0xAB, 0xD8, 0xA5, 0x10, +0x85, 0x0C, 0xA5, 0x12, 0x85, 0x0E, 0x20, 0x8C, 0xD8, 0xA5, 0x4E, 0x30, 0x03, 0x20, 0x48, 0xE5, +0x4C, 0xFB, 0xD7, 0x20, 0xAB, 0xD8, 0xA5, 0x10, 0x85, 0x0C, 0xA5, 0x12, 0x85, 0x0E, 0x20, 0x8C, +0xD8, 0xA5, 0x4E, 0x30, 0x1C, 0xA5, 0x1C, 0x85, 0x34, 0x09, 0x00, 0xC0, 0x85, 0x1C, 0x20, 0x48, +0xE5, 0xA5, 0x34, 0x29, 0x00, 0xC0, 0x85, 0x34, 0xA5, 0x1C, 0x29, 0xFF, 0x3F, 0x05, 0x34, 0x85, +0x1C, 0x4C, 0xFB, 0xD7, 0xA5, 0x2E, 0x85, 0x30, 0x20, 0xAB, 0xD8, 0xA5, 0x10, 0x85, 0x0C, 0xA5, +0x12, 0x85, 0x0E, 0xAD, 0xA9, 0xD4, 0x48, 0xA5, 0x44, 0x30, 0x3B, 0xA9, 0x02, 0x00, 0x85, 0x56, +0x38, 0xA5, 0x48, 0xE9, 0xFF, 0x3F, 0x85, 0x8E, 0xA5, 0x4A, 0xE5, 0x38, 0x85, 0x8C, 0x10, 0x0F, +0x38, 0xA5, 0x38, 0xE5, 0x8E, 0x85, 0x8E, 0xA5, 0x38, 0xE5, 0x8C, 0x85, 0x8C, 0xE6, 0x50, 0x64, +0x54, 0xA9, 0x1E, 0x40, 0x85, 0x52, 0x20, 0xC1, 0xDD, 0xA5, 0x4E, 0x10, 0x08, 0x24, 0x1C, 0x10, +0x04, 0x70, 0x02, 0xE6, 0x50, 0x60, 0x1A, 0xD0, 0x0B, 0xA9, 0x08, 0x00, 0x20, 0x21, 0xD7, 0xE6, +0x50, 0x4C, 0x07, 0xD7, 0x1A, 0xF0, 0xFA, 0x4C, 0x8C, 0xD8, 0x20, 0xAB, 0xD8, 0xA5, 0x44, 0x29, +0xFF, 0x00, 0x0A, 0x46, 0x46, 0x6A, 0x85, 0x20, 0x4C, 0x2C, 0xD8, 0x20, 0xCE, 0xD4, 0x8A, 0x29, +0x00, 0xC0, 0xD0, 0x03, 0x4C, 0x4E, 0xD8, 0x64, 0x46, 0x85, 0x24, 0x10, 0x02, 0xE6, 0x46, 0x45, +0x3C, 0x85, 0x50, 0xA5, 0x1C, 0x48, 0x29, 0xFF, 0x3F, 0x05, 0x24, 0x85, 0x1C, 0x64, 0x44, 0x64, +0x48, 0xA9, 0x00, 0xF0, 0x85, 0x4A, 0x64, 0x4C, 0xA9, 0x00, 0x80, 0x85, 0x72, 0xA5, 0x3A, 0xC9, +0xFE, 0xFF, 0xD0, 0x10, 0x64, 0x3A, 0x64, 0x3E, 0xA9, 0xFF, 0x0F, 0x85, 0x40, 0x64, 0x42, 0xA9, +0x00, 0x80, 0x85, 0x58, 0x20, 0x9E, 0xDC, 0x20, 0xB8, 0xDA, 0x68, 0x29, 0x00, 0xC0, 0x85, 0x34, +0xA5, 0x1C, 0x29, 0xFF, 0x3F, 0x05, 0x34, 0x85, 0x1C, 0xA5, 0x1E, 0x29, 0x06, 0x00, 0xF0, 0x0F, +0x29, 0x02, 0x00, 0xD0, 0x06, 0xA5, 0x4E, 0x30, 0x08, 0x10, 0x04, 0xA5, 0x8C, 0x10, 0x02, 0x64, +0x1E, 0x60, 0xA9, 0xFF, 0xFF, 0xD0, 0x03, 0xA9, 0xFE, 0xFF, 0x85, 0x4E, 0xA9, 0xFE, 0xFF, 0x85, +0x56, 0x60, 0x64, 0x56, 0x09, 0x00, 0x40, 0x85, 0x8C, 0xA9, 0xFD, 0xFF, 0x85, 0x4E, 0xA9, 0x01, +0x00, 0x05, 0x1E, 0x85, 0x1E, 0x60, 0x68, 0x85, 0x1C, 0x4C, 0x2C, 0xD8, 0xA6, 0x1C, 0x86, 0x20, +0x4C, 0x2C, 0xD8, 0x68, 0x85, 0x18, 0x68, 0x85, 0x1A, 0x4C, 0x2C, 0xD8, 0xA6, 0x18, 0x86, 0x20, +0xA4, 0x1A, 0x84, 0x22, 0x4C, 0x2C, 0xD8, 0x68, 0x85, 0x10, 0x68, 0x85, 0x12, 0xBC, 0x32, 0xD3, +0xE0, 0x06, 0x00, 0xB0, 0x0A, 0xB7, 0x10, 0x49, 0x00, 0x80, 0x97, 0x10, 0x4C, 0x2C, 0xD8, 0xE0, +0x0C, 0x00, 0xB0, 0xF1, 0xBB, 0xA4, 0x38, 0x38, 0xA5, 0x38, 0xF7, 0x10, 0x97, 0x10, 0xC8, 0xCA, +0xC8, 0xCA, 0x10, 0xF4, 0x4C, 0x2C, 0xD8, 0x68, 0x85, 0x10, 0x68, 0x85, 0x12, 0xBC, 0x32, 0xD3, +0xB7, 0x10, 0xE0, 0x06, 0x00, 0xB0, 0x08, 0x29, 0xFF, 0x7F, 0x97, 0x10, 0x4C, 0x2C, 0xD8, 0xE0, +0x0C, 0x00, 0xB0, 0xF3, 0x0A, 0xB0, 0xCD, 0x4C, 0x2C, 0xD8, 0x68, 0x85, 0x0C, 0x68, 0x85, 0x0E, +0x68, 0x85, 0x10, 0x68, 0x85, 0x12, 0xBC, 0x32, 0xD3, 0xB7, 0x10, 0xA6, 0x30, 0xBC, 0x32, 0xD3, +0xE0, 0x06, 0x00, 0xB0, 0x0C, 0x0A, 0x08, 0xB7, 0x0C, 0x0A, 0x28, 0x6A, 0x97, 0x0C, 0x4C, 0x2C, +0xD8, 0xE0, 0x0C, 0x00, 0xB0, 0xEF, 0x57, 0x10, 0x29, 0x00, 0x80, 0xD0, 0x97, 0x4C, 0x2C, 0xD8, +0x68, 0xD0, 0x2D, 0x4C, 0x2C, 0xD8, 0x68, 0xEB, 0x25, 0x1C, 0x85, 0x20, 0x4C, 0x2C, 0xD8, 0x68, +0x85, 0x14, 0x68, 0x85, 0x16, 0xA4, 0x38, 0xA5, 0x1C, 0x97, 0x14, 0x64, 0x1C, 0x4C, 0x2C, 0xD8, +0xA5, 0x1C, 0xEB, 0x85, 0x1E, 0x68, 0x85, 0x1C, 0x4C, 0xFE, 0xD7, 0x20, 0xF6, 0xD9, 0xA5, 0x1E, +0x29, 0x1F, 0x00, 0x24, 0x1C, 0xF0, 0x20, 0xA4, 0x18, 0xD0, 0x13, 0xA4, 0x1A, 0xF0, 0x18, 0x80, +0x0D, 0xA4, 0x19, 0xA5, 0x18, 0xD0, 0x01, 0x88, 0x3A, 0x5A, 0x8B, 0x83, 0x01, 0x6B, 0x22, 0x11, +0xD8, 0xFE, 0xA5, 0x1E, 0x29, 0x1F, 0x00, 0xEB, 0x05, 0x1C, 0x85, 0x1C, 0x24, 0x20, 0xA5, 0x20, +0xA4, 0x21, 0xAA, 0x29, 0x00, 0xFF, 0xD4, 0x04, 0xD4, 0x02, 0xD4, 0x00, 0x08, 0xA5, 0x08, 0x48, +0xAB, 0xAB, 0xA5, 0x06, 0x5B, 0xA5, 0x38, 0x28, 0x18, 0x22, 0x68, 0x00, 0xE1, 0x6B, 0xA5, 0x3A, +0x85, 0x4E, 0xA5, 0x3C, 0x85, 0x50, 0xA5, 0x3E, 0x85, 0x52, 0xA5, 0x40, 0x85, 0x54, 0xA6, 0x42, +0x86, 0x56, 0x30, 0x08, 0xB5, 0x58, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0x44, 0x85, +0x3A, 0xA5, 0x46, 0x85, 0x3C, 0xA5, 0x48, 0x85, 0x3E, 0xA5, 0x4A, 0x85, 0x40, 0xA6, 0x4C, 0x86, +0x42, 0x30, 0x08, 0xB5, 0x72, 0x95, 0x58, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0x44, 0x85, 0x4E, +0xA5, 0x46, 0x85, 0x50, 0xA5, 0x48, 0x85, 0x52, 0xA5, 0x4A, 0x85, 0x54, 0xA6, 0x4C, 0x86, 0x56, +0x30, 0x08, 0xB5, 0x72, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xFA, 0x68, 0x85, 0x10, 0x68, +0x85, 0x12, 0xDA, 0x64, 0x44, 0x64, 0x46, 0x64, 0x4A, 0xA6, 0x2E, 0xBC, 0x32, 0xD3, 0xE0, 0x06, +0x00, 0x90, 0x6E, 0xE0, 0x0C, 0x00, 0xB0, 0x69, 0x64, 0x74, 0x64, 0x76, 0x64, 0x78, 0xB7, 0x10, +0x10, 0x29, 0xBB, 0xA4, 0x46, 0xE6, 0x46, 0x38, 0xA5, 0x44, 0xF7, 0x10, 0x95, 0x72, 0xC8, 0xCA, +0xC8, 0xCA, 0x10, 0xF4, 0xAA, 0x10, 0x21, 0xA5, 0x2E, 0xC9, 0x0A, 0x00, 0xD0, 0x1A, 0x64, 0x4C, +0xA9, 0x16, 0x40, 0x85, 0x72, 0xA9, 0xFD, 0xFF, 0x85, 0x44, 0x60, 0xBB, 0xA4, 0x46, 0xB7, 0x10, +0x95, 0x72, 0xC8, 0xCA, 0xC8, 0xCA, 0x10, 0xF6, 0xA5, 0x72, 0xD0, 0x17, 0xA5, 0x74, 0x85, 0x72, +0xA5, 0x76, 0x85, 0x74, 0xA5, 0x78, 0x85, 0x76, 0x64, 0x78, 0x88, 0x88, 0xD0, 0xEA, 0x64, 0x4C, +0x4C, 0xA2, 0xD9, 0x98, 0x85, 0x4C, 0x0A, 0x0A, 0x0A, 0x69, 0xFE, 0x3F, 0x85, 0x48, 0x4C, 0xE3, +0xD9, 0xB7, 0x10, 0x0A, 0x26, 0x46, 0x4A, 0x85, 0x48, 0xA2, 0xFE, 0xFF, 0x86, 0x4C, 0x88, 0x88, +0xE8, 0xE8, 0xB7, 0x10, 0xF0, 0x02, 0x86, 0x4C, 0x95, 0x72, 0x88, 0x88, 0x10, 0xF2, 0xA4, 0x2E, +0xF0, 0x3D, 0xC0, 0x0C, 0x00, 0xB0, 0x38, 0xBE, 0x32, 0xD3, 0x86, 0x4C, 0x74, 0x72, 0xBE, 0x60, +0xD3, 0x46, 0x48, 0x66, 0x72, 0x66, 0x74, 0x66, 0x76, 0x66, 0x78, 0xCA, 0xD0, 0xF3, 0xA5, 0x48, +0x38, 0xD0, 0x05, 0xE6, 0x44, 0xE6, 0x48, 0x18, 0x66, 0x72, 0x66, 0x74, 0x66, 0x76, 0x66, 0x78, +0x20, 0xE7, 0xD9, 0xA5, 0x48, 0xD9, 0x6A, 0xD3, 0xB0, 0x21, 0x79, 0x64, 0xD3, 0x85, 0x48, 0xA5, +0x48, 0xD0, 0x06, 0xA6, 0x72, 0x30, 0x02, 0xE6, 0x44, 0xC9, 0xFF, 0x7F, 0xF0, 0x0D, 0xA6, 0x4C, +0x10, 0x41, 0xA9, 0xFF, 0xFF, 0x85, 0x44, 0x3A, 0x85, 0x4C, 0x60, 0xA5, 0x72, 0xA2, 0xFE, 0xFF, +0xA4, 0x4C, 0x30, 0x19, 0xD0, 0x05, 0xC9, 0x00, 0x80, 0xF0, 0x12, 0xCA, 0x09, 0x00, 0x40, 0xC5, +0x72, 0xF0, 0x0A, 0xCA, 0x85, 0x72, 0xA5, 0x1E, 0x09, 0x01, 0x00, 0x85, 0x1E, 0x86, 0x44, 0x4C, +0xE7, 0xD9, 0xA6, 0x4C, 0x18, 0x36, 0x72, 0xCA, 0xCA, 0x10, 0xFA, 0xA5, 0x48, 0xD0, 0x02, 0xC6, +0x4A, 0xC6, 0x48, 0xA5, 0x72, 0x10, 0xEB, 0xA6, 0x4C, 0x30, 0x0A, 0xB5, 0x72, 0xD0, 0x06, 0xCA, +0xCA, 0x86, 0x4C, 0x10, 0xF6, 0x60, 0xA6, 0x2E, 0xA4, 0x4E, 0x30, 0x2B, 0x20, 0xB8, 0xDA, 0xA6, +0x2E, 0xD0, 0x03, 0x4C, 0x8C, 0xDA, 0xE0, 0x06, 0x00, 0x90, 0x4F, 0xE0, 0x0C, 0x00, 0xB0, 0x7C, +0xBC, 0x32, 0xD3, 0xA6, 0x50, 0xF0, 0x0E, 0xBB, 0x38, 0xA5, 0x38, 0xF5, 0x8C, 0x95, 0x8C, 0xCA, +0xCA, 0x10, 0xF6, 0xA6, 0x38, 0xF0, 0x7E, 0xC8, 0xD0, 0x12, 0x64, 0x56, 0xA5, 0x56, 0xC6, 0x56, +0xE0, 0x06, 0x00, 0x90, 0x5A, 0xE0, 0x0C, 0x00, 0x90, 0x58, 0xB0, 0x53, 0xBD, 0x8E, 0xD3, 0x85, +0x52, 0xE0, 0x06, 0x00, 0x90, 0xB9, 0xE0, 0x0C, 0x00, 0xB0, 0xB4, 0x20, 0x1E, 0xD7, 0xBC, 0x32, +0xD3, 0x64, 0x56, 0xA6, 0x56, 0xA9, 0x00, 0x80, 0xD0, 0x4D, 0xBC, 0x60, 0xD3, 0xA6, 0x56, 0x30, +0x07, 0x18, 0x36, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, 0xA6, 0x4E, 0xE8, 0xD0, 0x03, 0x8A, 0xF0, 0x1F, +0x10, 0x01, 0x38, 0xA6, 0x2E, 0xA5, 0x52, 0xFD, 0x64, 0xD3, 0x85, 0x52, 0x18, 0xA6, 0x56, 0x30, +0x06, 0x36, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, 0x26, 0x52, 0x88, 0xD0, 0xF0, 0xA5, 0x52, 0x0A, 0x46, +0x50, 0x6A, 0xA6, 0x2E, 0xBC, 0x32, 0xD3, 0x97, 0x0C, 0xA2, 0xFF, 0xFF, 0x88, 0x30, 0x0E, 0xE4, +0x56, 0x10, 0x0B, 0xE8, 0x88, 0xB5, 0x8C, 0x97, 0x0C, 0xE8, 0x88, 0x10, 0xF2, 0x60, 0xA9, 0x00, +0x00, 0x88, 0x97, 0x0C, 0x88, 0x10, 0xFA, 0x60, 0xA6, 0x2E, 0xA9, 0xC0, 0x00, 0x25, 0x1C, 0xF0, +0x0A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0xC5, 0x2E, 0x90, 0x01, 0xAA, 0x86, 0x32, 0xE0, 0x0E, 0x00, +0xF0, 0x20, 0x18, 0xBD, 0x70, 0xD3, 0xE5, 0x52, 0x85, 0xBE, 0xA5, 0x38, 0xE5, 0x54, 0x30, 0x12, +0x85, 0xC0, 0xE6, 0xBE, 0xD0, 0x02, 0xE6, 0xC0, 0xBD, 0x70, 0xD3, 0x85, 0x52, 0x64, 0x54, 0x20, +0x8C, 0xE8, 0xA4, 0x32, 0xBE, 0x42, 0xD3, 0x86, 0x2A, 0x88, 0x30, 0x4D, 0x88, 0xD0, 0x23, 0xA9, +0x04, 0x00, 0xC5, 0x56, 0x10, 0x47, 0xA5, 0x92, 0x29, 0x00, 0x08, 0x85, 0x26, 0xA5, 0x92, 0x29, +0x00, 0x04, 0x85, 0x24, 0xA5, 0x92, 0x85, 0x28, 0x29, 0x00, 0xF8, 0x85, 0x92, 0xA9, 0xFF, 0x03, +0xD0, 0x22, 0x88, 0x88, 0xD0, 0x23, 0xA5, 0x56, 0xF0, 0x23, 0xA5, 0x8E, 0x29, 0x00, 0x01, 0x85, +0x26, 0xA5, 0x8E, 0x29, 0x80, 0x00, 0x85, 0x24, 0xA5, 0x8E, 0x85, 0x28, 0x29, 0x00, 0xFF, 0x85, +0x8E, 0xA9, 0x7F, 0x00, 0x25, 0x28, 0x18, 0x90, 0x17, 0xE4, 0x56, 0x30, 0x03, 0x4C, 0xF9, 0xDB, +0xB5, 0x8C, 0x29, 0x01, 0x00, 0x85, 0x26, 0x64, 0x24, 0xE8, 0xE8, 0xB5, 0x8C, 0x0A, 0x66, 0x24, +0xA8, 0xD0, 0x0A, 0xE4, 0x56, 0x10, 0x06, 0xE8, 0xE8, 0x15, 0x8C, 0xF0, 0xF6, 0x85, 0x28, 0xA6, +0x2A, 0x86, 0x56, 0x05, 0x24, 0xF0, 0x6C, 0xA5, 0x1E, 0x09, 0x10, 0x00, 0xA6, 0x8C, 0x30, 0x0F, +0xA4, 0x32, 0xC0, 0x06, 0x00, 0x90, 0x05, 0xC0, 0x0C, 0x00, 0x90, 0x03, 0x09, 0x02, 0x00, 0x85, +0x1E, 0xA9, 0x00, 0xC0, 0x24, 0x1C, 0xF0, 0x10, 0x30, 0x06, 0xA5, 0x50, 0xF0, 0x14, 0xD0, 0x43, +0x70, 0x41, 0xA5, 0x50, 0xD0, 0x0C, 0xF0, 0x3B, 0xA5, 0x24, 0xF0, 0x37, 0xA5, 0x28, 0x05, 0x26, +0xF0, 0x31, 0xA4, 0x32, 0xBE, 0x42, 0xD3, 0x88, 0x30, 0x18, 0x88, 0xD0, 0x05, 0xA9, 0x00, 0x08, +0xD0, 0x07, 0x88, 0x88, 0xD0, 0x0C, 0xA9, 0x00, 0x01, 0x18, 0x75, 0x8C, 0x95, 0x8C, 0x90, 0x13, +0xB0, 0x04, 0xF6, 0x8C, 0xD0, 0x0D, 0xCA, 0xCA, 0x10, 0xF8, 0x38, 0x66, 0x8C, 0xE6, 0x52, 0xD0, +0x02, 0xE6, 0x54, 0xA6, 0x56, 0xB5, 0x8C, 0xD0, 0x10, 0xC6, 0x56, 0xC6, 0x56, 0x10, 0xF4, 0xA4, +0x2E, 0xB9, 0x70, 0xD3, 0x85, 0x52, 0x4C, 0x02, 0xD7, 0xA4, 0x32, 0xC0, 0x06, 0x00, 0x90, 0x38, +0xC0, 0x0C, 0x00, 0xB0, 0x2E, 0xA6, 0x8C, 0x10, 0x1C, 0xA5, 0x50, 0xF0, 0x19, 0xA5, 0x54, 0xD0, +0x15, 0xA5, 0x52, 0xD9, 0x8E, 0xD3, 0xD0, 0x0B, 0xA5, 0x56, 0xD0, 0x0A, 0xE0, 0x00, 0x80, 0xF0, +0x04, 0xD0, 0x03, 0xB0, 0x01, 0x60, 0xA9, 0x00, 0x80, 0x85, 0x8C, 0x64, 0x56, 0x20, 0x1E, 0xD7, +0x4C, 0x07, 0xD7, 0xC0, 0x0E, 0x00, 0xF0, 0xED, 0xA5, 0x54, 0x30, 0xE9, 0xD0, 0x07, 0xA5, 0x52, +0xD9, 0x8E, 0xD3, 0x90, 0xE0, 0xA5, 0x1E, 0x09, 0x14, 0x00, 0x85, 0x1E, 0x64, 0x54, 0xB9, 0x8E, +0xD3, 0x85, 0x52, 0xA9, 0x00, 0xC0, 0x24, 0x1C, 0xF0, 0x08, 0x50, 0x10, 0x30, 0x12, 0xA5, 0x50, +0xD0, 0x0E, 0xA4, 0x2E, 0xB9, 0x8E, 0xD3, 0x85, 0x52, 0x4C, 0x07, 0xD7, 0xA5, 0x50, 0xD0, 0xF2, +0xC6, 0x52, 0xBE, 0x42, 0xD3, 0x86, 0x56, 0xA9, 0xFF, 0xFF, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, +0x88, 0x88, 0xD0, 0x05, 0xA9, 0x00, 0xF8, 0x85, 0x92, 0x88, 0x88, 0xD0, 0x98, 0xA9, 0x00, 0xFF, +0x85, 0x8E, 0x60, 0xA9, 0x01, 0x00, 0x45, 0x46, 0x85, 0x46, 0x45, 0x3C, 0x85, 0x50, 0xA6, 0x3A, +0x30, 0x09, 0xA4, 0x44, 0x10, 0x27, 0xC8, 0xF0, 0x10, 0x30, 0x08, 0xA4, 0x44, 0xE8, 0x30, 0x06, +0xC8, 0xF0, 0x13, 0x4C, 0x8C, 0xD8, 0xC8, 0x30, 0x03, 0x4C, 0x4E, 0xD8, 0xA5, 0x50, 0xF0, 0xF9, +0xA9, 0x02, 0x40, 0x4C, 0x12, 0xD7, 0xA5, 0x50, 0xF0, 0xEF, 0x4C, 0xE5, 0xDD, 0x38, 0xA5, 0x3E, +0xE5, 0x48, 0x85, 0xBE, 0xA5, 0x40, 0xE5, 0x4A, 0x85, 0xC0, 0x30, 0x1F, 0xA5, 0x44, 0x85, 0x4E, +0xA5, 0x3C, 0x85, 0x50, 0xA5, 0x3E, 0x85, 0x52, 0xA5, 0x40, 0x85, 0x54, 0xA6, 0x4C, 0x86, 0x56, +0xB5, 0x72, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF8, 0x4C, 0x41, 0xDD, 0xA5, 0x3A, 0x85, 0x4E, 0xA5, +0x46, 0x85, 0x50, 0xA5, 0x48, 0x85, 0x52, 0xA5, 0x4A, 0x85, 0x54, 0xA6, 0x42, 0x86, 0x56, 0xB5, +0x58, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF8, 0xA5, 0x3C, 0x85, 0x46, 0xA6, 0x4C, 0x86, 0x42, 0xB5, +0x72, 0x95, 0x58, 0xCA, 0xCA, 0x10, 0xF8, 0xA6, 0x2E, 0xBC, 0x52, 0xD3, 0xC4, 0x42, 0x10, 0x02, +0xA4, 0x42, 0x84, 0x34, 0x38, 0xA5, 0x38, 0xE5, 0xBE, 0x85, 0xBE, 0xA5, 0x38, 0xE5, 0xC0, 0x85, +0xC0, 0x20, 0x8C, 0xE8, 0xA6, 0x56, 0xE4, 0x42, 0x10, 0x08, 0xE8, 0xE8, 0x86, 0x56, 0x74, 0x8C, +0x10, 0xF4, 0xA5, 0x46, 0x45, 0x50, 0xD0, 0x3D, 0xA6, 0x42, 0x18, 0xB5, 0x58, 0x75, 0x8C, 0x95, +0x8C, 0xCA, 0xCA, 0x10, 0xF6, 0x90, 0x2D, 0xA6, 0x56, 0x9B, 0xA6, 0x38, 0x76, 0x8C, 0xE8, 0x88, +0xE8, 0x88, 0x10, 0xF8, 0xE6, 0x52, 0xD0, 0x02, 0xE6, 0x54, 0x90, 0x18, 0xA6, 0x56, 0xE4, 0x34, +0x90, 0x07, 0xB5, 0x8C, 0x09, 0x01, 0x00, 0xD0, 0x09, 0xE8, 0xE8, 0x86, 0x56, 0xE6, 0x26, 0xA9, +0x00, 0x80, 0x95, 0x8C, 0x60, 0xA6, 0x42, 0xE4, 0x56, 0x10, 0x08, 0xE8, 0xE8, 0x86, 0x42, 0x74, +0x58, 0x10, 0xF4, 0x38, 0xB5, 0x58, 0xF5, 0x8C, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF6, 0xB0, 0x11, +0xA6, 0x56, 0x38, 0xA5, 0x38, 0xF5, 0x8C, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF6, 0xA5, 0x46, 0x85, +0x50, 0xA5, 0x8C, 0xD0, 0x44, 0xA2, 0xFE, 0xFF, 0xA5, 0x56, 0xF0, 0x19, 0x4A, 0xE8, 0xE8, 0xB4, +0x8E, 0x94, 0x8C, 0x3A, 0xD0, 0xF7, 0x86, 0x56, 0xA5, 0x52, 0xE9, 0x0F, 0x00, 0x85, 0x52, 0xB0, +0xE0, 0xC6, 0x54, 0x90, 0xDC, 0x64, 0x50, 0xA5, 0x1C, 0x29, 0x00, 0xC0, 0x0A, 0x90, 0x04, 0xD0, +0x02, 0x26, 0x50, 0x4C, 0x02, 0xD7, 0xA6, 0x56, 0x18, 0x36, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, 0xA5, +0x52, 0xD0, 0x02, 0xC6, 0x54, 0xC6, 0x52, 0xA5, 0x8C, 0x10, 0xEB, 0x60, 0xA6, 0x3A, 0x30, 0x10, +0xA4, 0x44, 0x10, 0x1C, 0xC8, 0x30, 0x10, 0xA9, 0x08, 0x00, 0x20, 0x21, 0xD7, 0x4C, 0x07, 0xD7, +0xE4, 0x44, 0xF0, 0x06, 0xE8, 0x30, 0xF6, 0x4C, 0x02, 0xD7, 0xA9, 0x04, 0x40, 0x4C, 0x12, 0xD7, +0x20, 0xEA, 0xDE, 0xA6, 0x30, 0xBD, 0x7E, 0xD3, 0x85, 0x26, 0x46, 0x26, 0x46, 0x26, 0x46, 0x26, +0x46, 0x26, 0x29, 0x0F, 0x00, 0x85, 0x28, 0x64, 0x56, 0x20, 0xB5, 0xDE, 0xA6, 0x56, 0xA5, 0x24, +0x95, 0x8C, 0xE6, 0x56, 0xE6, 0x56, 0xC6, 0x26, 0xD0, 0xEF, 0xA4, 0x28, 0x20, 0xB8, 0xDE, 0xA5, +0x24, 0x4A, 0x6A, 0xC6, 0x28, 0xD0, 0xFB, 0xA6, 0x56, 0x95, 0x8C, 0xA6, 0x42, 0xB5, 0x58, 0xD0, +0x06, 0xCA, 0xCA, 0x10, 0xF8, 0x30, 0x09, 0xA6, 0x56, 0xA9, 0x01, 0x00, 0x15, 0x8C, 0x95, 0x8C, +0x38, 0xA5, 0x3E, 0xE5, 0x48, 0x85, 0x52, 0xA5, 0x40, 0xE5, 0x4A, 0x85, 0x54, 0xA5, 0x8C, 0x0A, +0xB0, 0x09, 0xA6, 0x56, 0x18, 0x36, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, 0xA5, 0x52, 0x69, 0xFE, 0x3F, +0x85, 0x52, 0xA5, 0x54, 0x65, 0x38, 0x85, 0x54, 0xA6, 0x56, 0xB5, 0x8C, 0xD0, 0x06, 0xC6, 0x56, +0xC6, 0x56, 0x10, 0xF4, 0x60, 0xA0, 0x10, 0x00, 0x64, 0x24, 0xA5, 0x58, 0xC5, 0x72, 0x90, 0x1B, +0xA6, 0x4C, 0xB5, 0x58, 0xF5, 0x72, 0x95, 0x58, 0xCA, 0xCA, 0x10, 0xF6, 0xB0, 0x0D, 0xA6, 0x4C, +0xB5, 0x58, 0x75, 0x72, 0x95, 0x58, 0xCA, 0xCA, 0x10, 0xF6, 0x18, 0x26, 0x24, 0xA6, 0x42, 0x18, +0x36, 0x58, 0xCA, 0xCA, 0x10, 0xFA, 0x88, 0xD0, 0xD1, 0x60, 0xA6, 0x38, 0xA5, 0x42, 0x4A, 0x76, +0x58, 0xE8, 0xE8, 0x3A, 0x10, 0xF9, 0x90, 0x06, 0x86, 0x42, 0x74, 0x58, 0x76, 0x58, 0xA6, 0x38, +0xA5, 0x4C, 0x4A, 0x76, 0x72, 0xE8, 0xE8, 0x3A, 0x10, 0xF9, 0x90, 0x06, 0x86, 0x4C, 0x74, 0x72, +0x76, 0x72, 0xA6, 0x42, 0xE4, 0x4C, 0xB0, 0x08, 0xE8, 0xE8, 0x86, 0x42, 0x74, 0x58, 0x10, 0xF4, +0x60, 0xA5, 0x50, 0x4A, 0x64, 0x20, 0x66, 0x20, 0xEB, 0x05, 0x20, 0x85, 0x20, 0xA5, 0x3C, 0x85, +0x50, 0xA5, 0x3A, 0xA6, 0x44, 0x30, 0x03, 0xA8, 0x10, 0x13, 0xC9, 0xFE, 0xFF, 0xF0, 0x08, 0xE0, +0xFF, 0xFF, 0xF0, 0x03, 0x4C, 0x4E, 0xD8, 0xA9, 0x09, 0x40, 0x4C, 0x12, 0xD7, 0x20, 0xEA, 0xDE, +0x64, 0x24, 0x38, 0xA5, 0x3E, 0xE5, 0x48, 0x85, 0x52, 0xA5, 0x40, 0xE5, 0x4A, 0x85, 0x54, 0xE6, +0x52, 0xD0, 0x02, 0xE6, 0x54, 0x24, 0x54, 0x30, 0x7C, 0xA0, 0x01, 0x00, 0x20, 0xB8, 0xDE, 0xA4, +0x52, 0xF0, 0x03, 0x20, 0xBA, 0xDE, 0xC6, 0x54, 0x30, 0x07, 0xA4, 0x38, 0x20, 0xBA, 0xDE, 0x80, +0xF5, 0x18, 0xA5, 0x48, 0xE5, 0x38, 0x85, 0x52, 0xA5, 0x4A, 0xE5, 0x38, 0x85, 0x54, 0x46, 0x24, +0xA5, 0x24, 0x85, 0x2A, 0x90, 0x39, 0xA6, 0x42, 0xB5, 0x58, 0xD0, 0x08, 0xCA, 0xCA, 0x10, 0xF8, +0x46, 0x24, 0x90, 0x0D, 0xA5, 0x2A, 0x65, 0x38, 0x85, 0x2A, 0xA5, 0x50, 0x49, 0x01, 0x00, 0x85, +0x50, 0xA6, 0x4C, 0x36, 0x72, 0xCA, 0xCA, 0x10, 0xFA, 0xA6, 0x4C, 0xE4, 0x42, 0xB0, 0x06, 0xE8, +0xE8, 0x74, 0x72, 0x10, 0xF6, 0xB5, 0x72, 0xF5, 0x58, 0x95, 0x58, 0xCA, 0xCA, 0x10, 0xF6, 0xA5, +0x2A, 0x29, 0x7F, 0x00, 0x05, 0x20, 0x85, 0x20, 0xA6, 0x42, 0xB5, 0x58, 0xD0, 0x14, 0xCA, 0xCA, +0x10, 0xF8, 0x4C, 0x02, 0xD7, 0x38, 0xA5, 0x3E, 0x65, 0x38, 0x85, 0x52, 0xA5, 0x40, 0x65, 0x38, +0x85, 0x54, 0xA6, 0x42, 0x86, 0x56, 0xB5, 0x58, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF8, 0xAA, 0x30, +0x23, 0xA6, 0x56, 0x18, 0x36, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, 0xA5, 0x52, 0xD0, 0x02, 0xC6, 0x54, +0xC6, 0x52, 0xA5, 0x8C, 0x10, 0xEB, 0xA6, 0x56, 0x30, 0x0A, 0xB5, 0x8C, 0xD0, 0x06, 0xCA, 0xCA, +0x86, 0x56, 0x10, 0xF6, 0x60, 0xA5, 0x46, 0x85, 0x50, 0xF0, 0x12, 0xA5, 0x44, 0x10, 0x05, 0xC9, +0xFE, 0xFF, 0xD0, 0x06, 0xA9, 0x01, 0x40, 0x4C, 0x12, 0xD7, 0x4C, 0x8C, 0xD8, 0xA5, 0x44, 0x30, +0xF9, 0x20, 0xFE, 0xDE, 0x18, 0xA9, 0x01, 0x40, 0x65, 0x48, 0x85, 0x52, 0xA5, 0x38, 0x65, 0x4A, +0x85, 0x54, 0xA5, 0x54, 0x0A, 0x66, 0x54, 0x66, 0x52, 0xB0, 0x03, 0x20, 0xFE, 0xDE, 0xA6, 0x2E, +0xBC, 0x7E, 0xD3, 0xA9, 0x00, 0x20, 0x64, 0x56, 0xA6, 0x56, 0x85, 0x8C, 0x85, 0x24, 0xF0, 0x2E, +0x46, 0x24, 0x90, 0x1A, 0xA9, 0x00, 0x80, 0x85, 0x24, 0xE6, 0x56, 0xE6, 0x56, 0xA6, 0x56, 0x74, +0x8C, 0xA6, 0x4C, 0xE4, 0x56, 0xB0, 0x06, 0xE8, 0xE8, 0x86, 0x4C, 0x74, 0x72, 0x18, 0xA6, 0x4C, +0x36, 0x72, 0xCA, 0xCA, 0x10, 0xFA, 0xA6, 0x56, 0xB5, 0x8C, 0x05, 0x24, 0x95, 0x8C, 0xA5, 0x72, +0xC5, 0x8C, 0x90, 0x29, 0xA6, 0x56, 0xB5, 0x72, 0xF5, 0x8C, 0x95, 0x72, 0xCA, 0xCA, 0x10, 0xF6, +0xA6, 0x56, 0x90, 0x0F, 0x18, 0xA5, 0x24, 0x75, 0x8C, 0x95, 0x8C, 0x90, 0x18, 0xA5, 0x38, 0xCA, +0xCA, 0x10, 0xF4, 0xB5, 0x72, 0x75, 0x8C, 0x95, 0x72, 0xCA, 0xCA, 0x10, 0xF6, 0xA6, 0x56, 0xA5, +0x24, 0x55, 0x8C, 0x95, 0x8C, 0x88, 0x10, 0x98, 0xA6, 0x4C, 0xB5, 0x72, 0xD0, 0x06, 0xCA, 0xCA, +0x10, 0xF8, 0x30, 0x08, 0xA6, 0x56, 0xA5, 0x24, 0x15, 0x8C, 0x95, 0x8C, 0x4C, 0x01, 0xE0, 0x68, +0x85, 0x14, 0x68, 0x85, 0x16, 0x20, 0xAB, 0xD8, 0x68, 0x85, 0x0C, 0x68, 0x85, 0x0E, 0xA4, 0x38, +0xB7, 0x0C, 0x85, 0xAC, 0xA5, 0x46, 0x97, 0x14, 0xC8, 0xC8, 0xB7, 0x0C, 0x85, 0xAE, 0xA5, 0x44, +0x10, 0x5E, 0xE2, 0x30, 0x49, 0xFF, 0xAA, 0xBD, 0x9C, 0xD3, 0xA0, 0x05, 0x97, 0x14, 0xE0, 0x02, +0xA9, 0x01, 0x90, 0x31, 0xA6, 0x4C, 0xE8, 0xE8, 0x86, 0x24, 0xA2, 0x00, 0xB5, 0x73, 0x4A, 0x4A, +0x4A, 0x4A, 0x20, 0x60, 0xE1, 0xB5, 0x73, 0x29, 0x0F, 0x20, 0x60, 0xE1, 0xB5, 0x72, 0x4A, 0x4A, +0x4A, 0x4A, 0x20, 0x60, 0xE1, 0xB5, 0x72, 0x29, 0x0F, 0x20, 0x60, 0xE1, 0xE8, 0xE8, 0xE4, 0x24, +0x90, 0xDA, 0x98, 0xE9, 0x04, 0xA0, 0x04, 0x97, 0x14, 0xC2, 0x30, 0x4C, 0xFE, 0xD7, 0xE2, 0x30, +0xC9, 0x0A, 0xB0, 0x04, 0x09, 0x30, 0x90, 0x02, 0x69, 0x56, 0xC8, 0x97, 0x14, 0x60, 0xC2, 0x30, +0xA9, 0x0E, 0x00, 0x85, 0x30, 0xA5, 0xAC, 0xD0, 0x0A, 0xA5, 0xAE, 0x30, 0x02, 0xD0, 0x04, 0x64, +0xAE, 0xE6, 0xAE, 0x20, 0x7C, 0xE2, 0x20, 0xD2, 0xE3, 0x38, 0xA5, 0xAC, 0xD0, 0x06, 0xA5, 0xAE, +0x85, 0xA6, 0xB0, 0x06, 0xA5, 0xA8, 0x65, 0xAE, 0x85, 0xA6, 0x30, 0x0D, 0x38, 0xA9, 0x1C, 0x00, +0xE5, 0xA6, 0x10, 0x05, 0xA9, 0x1C, 0x00, 0x85, 0xA6, 0x18, 0xA5, 0xA6, 0xE5, 0xA8, 0x85, 0xAA, +0x85, 0x24, 0xA5, 0xA6, 0x30, 0x02, 0xD0, 0x04, 0x64, 0xA6, 0xE6, 0xA6, 0xA0, 0x02, 0x00, 0x38, +0xA5, 0x38, 0xE5, 0xAA, 0x97, 0x14, 0x20, 0x74, 0xE3, 0x20, 0x48, 0xE5, 0x64, 0x58, 0x64, 0x42, +0xA5, 0x4E, 0x30, 0x59, 0x64, 0x28, 0x38, 0xA5, 0x52, 0xE9, 0xFF, 0x3F, 0x85, 0x2C, 0x29, 0x0F, +0x00, 0x85, 0x2A, 0x46, 0x2C, 0x46, 0x2C, 0x46, 0x2C, 0x46, 0x2C, 0x64, 0xC2, 0xF8, 0xA6, 0xC2, +0xE4, 0x56, 0xF0, 0x02, 0x10, 0x04, 0xB5, 0x8C, 0x85, 0x24, 0xE6, 0xC2, 0xE6, 0xC2, 0xA9, 0x0F, +0x00, 0xC6, 0x2C, 0x10, 0x02, 0xA5, 0x2A, 0x85, 0x26, 0xA6, 0x38, 0xA4, 0x28, 0x06, 0x24, 0xB5, +0x58, 0x75, 0x58, 0x95, 0x58, 0xE8, 0xE8, 0x88, 0x10, 0xF5, 0x90, 0x08, 0x74, 0x58, 0x36, 0x58, +0x86, 0x42, 0xE6, 0x28, 0xC6, 0x26, 0x10, 0xE1, 0x24, 0x2C, 0x10, 0xC2, 0xD8, 0xE2, 0x30, 0xA0, +0x04, 0x38, 0x98, 0x65, 0xA6, 0x85, 0x24, 0xA6, 0x42, 0xB5, 0x59, 0xF0, 0x01, 0xE8, 0xA9, 0xF0, +0x35, 0x58, 0xF0, 0x0F, 0xB5, 0x58, 0x4A, 0x4A, 0x4A, 0x4A, 0x09, 0x30, 0xC8, 0xC4, 0x24, 0xB0, +0x1F, 0x97, 0x14, 0xB5, 0x58, 0x29, 0x0F, 0x09, 0x30, 0xC8, 0xC4, 0x24, 0xB0, 0x12, 0x97, 0x14, +0xCA, 0x10, 0xE1, 0x38, 0x98, 0xE9, 0x04, 0xA0, 0x04, 0x97, 0x14, 0xC2, 0x30, 0x4C, 0xFE, 0xD7, +0xC2, 0x30, 0x20, 0x17, 0xE3, 0x64, 0x1E, 0xE6, 0xA8, 0x4C, 0x89, 0xE1, 0xA5, 0x44, 0x85, 0xB0, +0xA5, 0x46, 0x85, 0xB2, 0xA5, 0x48, 0x85, 0xB4, 0xA5, 0x4A, 0x85, 0xB6, 0xA6, 0x4C, 0x86, 0xB8, +0x30, 0x08, 0xB5, 0x72, 0x95, 0xC4, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0x44, 0x85, 0xBA, 0xA5, +0x46, 0x85, 0xBC, 0xA5, 0x48, 0x85, 0xBE, 0xA5, 0x4A, 0x85, 0xC0, 0xA6, 0x4C, 0x86, 0xC2, 0x30, +0x08, 0xB5, 0x72, 0x95, 0xDE, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0x4E, 0x85, 0x44, 0xA5, 0x50, +0x85, 0x46, 0xA5, 0x52, 0x85, 0x48, 0xA5, 0x54, 0x85, 0x4A, 0xA6, 0x56, 0x86, 0x4C, 0x30, 0x08, +0xB5, 0x8C, 0x95, 0x72, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0x4E, 0x85, 0xBA, 0xA5, 0x50, 0x85, +0xBC, 0xA5, 0x52, 0x85, 0xBE, 0xA5, 0x54, 0x85, 0xC0, 0xA6, 0x56, 0x86, 0xC2, 0x30, 0x08, 0xB5, +0x8C, 0x95, 0xDE, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0xB0, 0x85, 0x3A, 0xA5, 0xB2, 0x85, 0x3C, +0xA5, 0xB4, 0x85, 0x3E, 0xA5, 0xB6, 0x85, 0x40, 0xA6, 0xB8, 0x86, 0x42, 0x30, 0x08, 0xB5, 0xC4, +0x95, 0x58, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0xB0, 0x85, 0x44, 0xA5, 0xB2, 0x85, 0x46, 0xA5, +0xB4, 0x85, 0x48, 0xA5, 0xB6, 0x85, 0x4A, 0xA6, 0xB8, 0x86, 0x4C, 0x30, 0x08, 0xB5, 0xC4, 0x95, +0x72, 0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0xBA, 0x85, 0x3A, 0xA5, 0xBC, 0x85, 0x3C, 0xA5, 0xBE, +0x85, 0x3E, 0xA5, 0xC0, 0x85, 0x40, 0xA6, 0xC2, 0x86, 0x42, 0x30, 0x08, 0xB5, 0xDE, 0x95, 0x58, +0xCA, 0xCA, 0x10, 0xF8, 0x60, 0xA5, 0xBA, 0x85, 0x44, 0xA5, 0xBC, 0x85, 0x46, 0xA5, 0xBE, 0x85, +0x48, 0xA5, 0xC0, 0x85, 0x4A, 0xA6, 0xC2, 0x86, 0x4C, 0x30, 0x08, 0xB5, 0xDE, 0x95, 0x72, 0xCA, +0xCA, 0x10, 0xF8, 0x60, 0xD0, 0x03, 0x4C, 0x8C, 0xD8, 0x85, 0x2C, 0x30, 0x02, 0x85, 0xAA, 0xA5, +0x1C, 0x29, 0x00, 0xC0, 0x48, 0x0A, 0x64, 0x32, 0x26, 0x32, 0x0A, 0x26, 0x32, 0xF0, 0x14, 0x06, +0x24, 0x26, 0x32, 0xA5, 0x46, 0x4A, 0x26, 0x32, 0x26, 0x32, 0xA6, 0x32, 0xBD, 0x98, 0xD3, 0x45, +0x1C, 0x85, 0x1C, 0x20, 0x11, 0xE4, 0xA5, 0xB2, 0x85, 0x50, 0x20, 0xF8, 0xE2, 0xA9, 0xFF, 0x3F, +0x25, 0x1C, 0x85, 0x1C, 0x68, 0x05, 0x1C, 0x85, 0x1C, 0xA6, 0x30, 0x86, 0x2E, 0xBC, 0x52, 0xD3, +0xC4, 0x42, 0x10, 0x02, 0xA4, 0x42, 0x84, 0x34, 0x24, 0x2C, 0x10, 0x03, 0x4C, 0xDD, 0xE7, 0x4C, +0x0C, 0xDE, 0xA9, 0x1F, 0x9A, 0x85, 0x24, 0x38, 0xA5, 0x48, 0xE9, 0xFF, 0x3F, 0xA8, 0x85, 0x26, +0x85, 0x28, 0x10, 0x02, 0xE6, 0x24, 0xA5, 0x72, 0x85, 0x2A, 0xA5, 0x38, 0xA2, 0x0F, 0x00, 0x46, +0x2A, 0x90, 0x02, 0x65, 0x24, 0x6A, 0xCA, 0xD0, 0xF6, 0xA2, 0x11, 0x00, 0x06, 0x28, 0x66, 0x26, +0x90, 0x02, 0x65, 0x24, 0x6A, 0xCA, 0xD0, 0xF6, 0xBB, 0x10, 0x03, 0x18, 0xE5, 0x24, 0x85, 0xA8, +0x60, 0xA5, 0xAA, 0x20, 0x62, 0xE4, 0x46, 0xAA, 0x46, 0xAA, 0x46, 0xAA, 0x46, 0xAA, 0xD0, 0x01, +0x60, 0xA2, 0x0E, 0x00, 0x86, 0x2E, 0xBD, 0x52, 0xD3, 0x85, 0x34, 0x20, 0x9B, 0xE2, 0x64, 0x50, +0xA9, 0x10, 0x00, 0x20, 0x65, 0xE4, 0x4C, 0x4B, 0xE4, 0x20, 0x55, 0xE3, 0x20, 0xD9, 0xE2, 0x20, +0x6D, 0xD8, 0x20, 0xDD, 0xE7, 0x20, 0xB8, 0xDA, 0x20, 0xBA, 0xE2, 0x46, 0xAA, 0x90, 0xF0, 0x20, +0x36, 0xE3, 0x20, 0x9B, 0xE2, 0x20, 0xDD, 0xE7, 0x20, 0xB8, 0xDA, 0xA5, 0xAA, 0xD0, 0xDA, 0x4C, +0xBA, 0xE2, 0x29, 0x0F, 0x00, 0x0A, 0x85, 0x24, 0x0A, 0x0A, 0x65, 0x24, 0xA8, 0x64, 0x44, 0x64, +0x46, 0x64, 0x4A, 0xB9, 0xA6, 0xE4, 0x0A, 0x26, 0x46, 0x4A, 0x85, 0x48, 0xA2, 0x06, 0x00, 0xB9, +0xA4, 0xE4, 0x85, 0x72, 0xB9, 0xA2, 0xE4, 0x85, 0x74, 0xB9, 0xA0, 0xE4, 0x85, 0x76, 0xB9, 0x9E, +0xE4, 0x85, 0x78, 0xD0, 0x06, 0xCA, 0xCA, 0xB5, 0x72, 0xF0, 0xFA, 0x86, 0x4C, 0x60, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, +0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xFA, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9C, 0x0C, 0x40, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xC3, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x24, 0xF4, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, 0x98, 0x16, 0x40, 0x00, 0x00, +0x00, 0x00, 0x00, 0x20, 0xBC, 0xBE, 0x19, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6B, 0xEE, +0x1C, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0x02, 0x95, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, +0x40, 0xB7, 0x43, 0xBA, 0x23, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA5, 0xD4, 0xE8, 0x26, 0x40, +0x00, 0x00, 0x00, 0x00, 0x2A, 0xE7, 0x84, 0x91, 0x2A, 0x40, 0x00, 0x00, 0x00, 0x80, 0xF4, 0x20, +0xE6, 0xB5, 0x2D, 0x40, 0x00, 0x00, 0x00, 0xA0, 0x31, 0xA9, 0x5F, 0xE3, 0x30, 0x40, 0x00, 0x00, +0x00, 0x04, 0xBF, 0xC9, 0x1B, 0x8E, 0x34, 0x40, 0x64, 0x26, 0x64, 0x24, 0x38, 0xA5, 0x52, 0xE9, +0xFF, 0x3F, 0x85, 0xBE, 0xA5, 0x54, 0xE5, 0x38, 0x85, 0xC0, 0x10, 0x13, 0xA6, 0x38, 0xA9, 0xFF, +0xFF, 0xC5, 0xBE, 0xD0, 0x5E, 0xC5, 0xC0, 0xD0, 0x5A, 0xA9, 0x00, 0x80, 0xD0, 0x3C, 0x60, 0xA5, +0xBE, 0x29, 0x0F, 0x00, 0xAA, 0x38, 0xA5, 0x38, 0x6A, 0xCA, 0x10, 0xFC, 0x85, 0x2A, 0xA8, 0x46, +0xC0, 0x66, 0xBE, 0x46, 0xC0, 0x66, 0xBE, 0x46, 0xC0, 0x66, 0xBE, 0x66, 0xBE, 0x06, 0xBE, 0xA6, +0xC0, 0xD0, 0xDB, 0xA6, 0xBE, 0xE4, 0x56, 0xF0, 0x02, 0xB0, 0xD3, 0x35, 0x8C, 0x85, 0x26, 0x98, +0x4A, 0xD0, 0x07, 0x6A, 0xE4, 0x56, 0x10, 0xC6, 0xE8, 0xE8, 0xA8, 0x35, 0x8C, 0x85, 0x24, 0x55, +0x8C, 0x95, 0x8C, 0x98, 0xA4, 0x38, 0x3A, 0xF0, 0x04, 0x35, 0x8C, 0xD0, 0x0A, 0xE4, 0x56, 0x10, +0x0C, 0xE8, 0xE8, 0xB5, 0x8C, 0xF0, 0xF6, 0xA8, 0x55, 0x8C, 0x95, 0x8C, 0x98, 0x05, 0x24, 0xF0, +0x4B, 0xA5, 0x1E, 0x09, 0x10, 0x00, 0x85, 0x1E, 0x86, 0x56, 0xA9, 0x00, 0xC0, 0x24, 0x1C, 0xF0, +0x10, 0x30, 0x06, 0xA5, 0x50, 0xF0, 0x13, 0xD0, 0x43, 0x70, 0x41, 0xA5, 0x50, 0xD0, 0x0B, 0xF0, +0x3B, 0xA5, 0x24, 0xF0, 0x37, 0x98, 0x05, 0x26, 0xF0, 0x32, 0xA6, 0xC0, 0x30, 0x1F, 0xA6, 0xBE, +0x18, 0xA5, 0x2A, 0x75, 0x8C, 0x95, 0x8C, 0x90, 0x13, 0xB0, 0x04, 0xF6, 0x8C, 0xD0, 0x0D, 0xCA, +0xCA, 0x10, 0xF8, 0x38, 0x66, 0x8C, 0xE6, 0x52, 0xD0, 0x02, 0xE6, 0x54, 0x60, 0x64, 0x54, 0xA9, +0xFF, 0x3F, 0x85, 0x52, 0x64, 0x56, 0xA9, 0x00, 0x80, 0x85, 0x8C, 0x60, 0xA6, 0xC0, 0x10, 0xEC, +0x4C, 0x02, 0xD7, 0x86, 0x30, 0x68, 0x85, 0x0C, 0x68, 0x85, 0x0E, 0x68, 0x85, 0x14, 0x68, 0x85, +0x16, 0xAD, 0xA9, 0xD4, 0x48, 0x64, 0x46, 0x64, 0x50, 0xA4, 0x38, 0xB7, 0x14, 0xF0, 0x04, 0xE6, +0x46, 0xE6, 0x50, 0xA0, 0x04, 0x00, 0xB7, 0x14, 0x29, 0xFF, 0x00, 0xF0, 0x1D, 0x85, 0xA6, 0xC8, +0x84, 0x24, 0xC9, 0x1D, 0x00, 0x90, 0x04, 0xA9, 0x1C, 0x00, 0x18, 0x69, 0x04, 0x00, 0x85, 0x26, +0xB7, 0x14, 0x29, 0xFF, 0x00, 0xC9, 0x30, 0x00, 0xD0, 0x03, 0x4C, 0x02, 0xD7, 0x29, 0xDF, 0x00, +0xC9, 0x49, 0x00, 0xD0, 0x03, 0x4C, 0x07, 0xD7, 0xC9, 0x4E, 0x00, 0xD0, 0x71, 0xA9, 0xFD, 0xFF, +0x85, 0x4E, 0x64, 0x56, 0x64, 0x8C, 0xA6, 0x56, 0xE6, 0x26, 0x64, 0x28, 0xC8, 0xC4, 0x26, 0xB0, +0x37, 0xE2, 0x30, 0xB7, 0x14, 0xC2, 0x30, 0x29, 0xFF, 0x00, 0xC9, 0x41, 0x00, 0x90, 0x03, 0x69, +0x08, 0x00, 0x29, 0x0F, 0x00, 0xC0, 0x0A, 0x00, 0xF0, 0x14, 0x06, 0x28, 0xB0, 0x10, 0x16, 0x8C, +0x16, 0x8C, 0x16, 0x8C, 0x16, 0x8C, 0x66, 0x28, 0x15, 0x8C, 0x95, 0x8C, 0x80, 0xCE, 0xE8, 0xE8, +0x86, 0x56, 0x74, 0x8C, 0xF6, 0x8C, 0x80, 0xE6, 0x8A, 0xF0, 0x08, 0x24, 0x28, 0x30, 0x04, 0x16, +0x8C, 0x90, 0xFC, 0xA9, 0x00, 0x40, 0x24, 0x8C, 0xD0, 0x05, 0xA5, 0x8C, 0x4C, 0x14, 0xD7, 0xA5, +0x8C, 0x29, 0xFF, 0x00, 0xD0, 0x07, 0xA9, 0x17, 0x40, 0x05, 0x8C, 0x85, 0x8C, 0x60, 0x64, 0x4C, +0x64, 0x72, 0x64, 0x44, 0xA0, 0x02, 0x00, 0xB7, 0x14, 0x85, 0xAA, 0x10, 0x5C, 0xA4, 0x26, 0xE2, +0x30, 0xB7, 0x14, 0xC2, 0x30, 0x29, 0x0F, 0x00, 0xD0, 0x4F, 0xC6, 0x26, 0xE6, 0xAA, 0x30, 0xED, +0x10, 0x47, 0xC6, 0xAA, 0xA5, 0x72, 0x29, 0x00, 0xE0, 0xF0, 0x05, 0x20, 0xBD, 0xE7, 0x64, 0x72, +0xA6, 0x4C, 0x18, 0xB5, 0x72, 0x2A, 0x95, 0x58, 0x95, 0x72, 0xCA, 0xCA, 0x10, 0xF5, 0xA0, 0x02, +0x00, 0xA6, 0x4C, 0x36, 0x72, 0xCA, 0xCA, 0x10, 0xFA, 0x88, 0xD0, 0xF5, 0xA6, 0x4C, 0xB5, 0x58, +0x75, 0x72, 0x95, 0x72, 0xCA, 0xCA, 0x10, 0xF6, 0x90, 0x03, 0x20, 0xBD, 0xE7, 0xA4, 0x24, 0xC4, +0x26, 0xE6, 0x24, 0x90, 0x04, 0xA4, 0x24, 0xB0, 0x1D, 0xA4, 0x24, 0xE2, 0x30, 0xB7, 0x14, 0xC2, +0x30, 0x29, 0x0F, 0x00, 0xA6, 0x4C, 0x18, 0x75, 0x72, 0x95, 0x72, 0x90, 0x09, 0xA5, 0x38, 0xCA, +0xCA, 0x10, 0xF4, 0x20, 0xBD, 0xE7, 0xC4, 0x26, 0x90, 0x9A, 0xA5, 0xAA, 0xF0, 0x07, 0x30, 0x05, +0xC0, 0x20, 0x00, 0x90, 0x8D, 0xA5, 0x72, 0xD0, 0x03, 0x4C, 0x02, 0xD7, 0xA5, 0x4C, 0x0A, 0x0A, +0x0A, 0x69, 0x0E, 0x40, 0x85, 0x48, 0x64, 0x4A, 0x24, 0x72, 0x30, 0x03, 0x20, 0xD2, 0xD9, 0x20, +0x7C, 0xE2, 0xA5, 0xAA, 0x85, 0x24, 0x49, 0xFF, 0xFF, 0x1A, 0x4C, 0x74, 0xE3, 0xA6, 0x4C, 0xE0, +0x1A, 0x00, 0xB0, 0x12, 0xE6, 0x4C, 0xE6, 0x4C, 0xB5, 0x72, 0x95, 0x74, 0xCA, 0xCA, 0x10, 0xF8, +0xA9, 0x01, 0x00, 0x85, 0x72, 0x60, 0xA9, 0x11, 0x40, 0x68, 0x4C, 0x12, 0xD7, 0xA6, 0x3A, 0x30, +0x09, 0xA4, 0x44, 0x10, 0x1C, 0xC8, 0xF0, 0x0A, 0x30, 0x0E, 0xA4, 0x44, 0xE8, 0x30, 0x06, 0xC8, +0x30, 0x09, 0x4C, 0x02, 0xD7, 0xC8, 0xF0, 0x03, 0x4C, 0x07, 0xD7, 0xA9, 0x08, 0x40, 0x4C, 0x12, +0xD7, 0xA6, 0x42, 0x86, 0x56, 0x86, 0x26, 0x46, 0x26, 0x74, 0x8C, 0xCA, 0xCA, 0x10, 0xFA, 0xA6, +0x4C, 0xB5, 0x72, 0x85, 0x24, 0xA0, 0x0F, 0x00, 0x46, 0x24, 0x90, 0x0D, 0x18, 0xA6, 0x42, 0xB5, +0x8C, 0x75, 0x58, 0x95, 0x8C, 0xCA, 0xCA, 0x10, 0xF6, 0xA5, 0x26, 0xA6, 0x38, 0x76, 0x8C, 0xE8, +0xE8, 0x3A, 0x10, 0xF9, 0x90, 0x18, 0xA6, 0x56, 0xE4, 0x34, 0x90, 0x07, 0xB5, 0x8C, 0x09, 0x01, +0x00, 0xD0, 0x09, 0xE8, 0xE8, 0x86, 0x56, 0xE6, 0x26, 0xA9, 0x00, 0x80, 0x95, 0x8C, 0x88, 0x10, +0xC7, 0xC6, 0x4C, 0xC6, 0x4C, 0x10, 0xB8, 0x18, 0xA5, 0x3E, 0x65, 0x48, 0x85, 0x52, 0xA5, 0x40, +0x65, 0x4A, 0x85, 0x54, 0xA5, 0x8C, 0x0A, 0xB0, 0x09, 0xA6, 0x56, 0x18, 0x36, 0x8C, 0xCA, 0xCA, +0x10, 0xFA, 0xA5, 0x52, 0xE9, 0xFE, 0x3F, 0x85, 0x52, 0xA5, 0x54, 0xE5, 0x38, 0x85, 0x54, 0xA6, +0x56, 0xB5, 0x8C, 0xD0, 0x06, 0xC6, 0x56, 0xC6, 0x56, 0x10, 0xF4, 0x60, 0xA6, 0x2E, 0xA5, 0xC0, +0xD0, 0x0A, 0xA5, 0xBE, 0xD0, 0x01, 0x60, 0xDD, 0x7E, 0xD3, 0x90, 0x05, 0xBD, 0x7E, 0xD3, 0x85, +0xBE, 0xBC, 0x52, 0xD3, 0xC4, 0x56, 0x10, 0x02, 0xA4, 0x56, 0x84, 0x26, 0x64, 0x28, 0xA5, 0xBE, +0x29, 0x0F, 0x00, 0xF0, 0x48, 0xC9, 0x09, 0x00, 0x90, 0x16, 0xA6, 0x56, 0x18, 0x36, 0x8C, 0xCA, +0xCA, 0x10, 0xFA, 0x26, 0x28, 0xE6, 0xBE, 0xA5, 0xBE, 0x29, 0x0F, 0x00, 0xD0, 0xEC, 0xF0, 0x2D, +0xA6, 0x38, 0x18, 0x76, 0x8C, 0x8A, 0x45, 0x56, 0xF0, 0x04, 0xE8, 0xE8, 0xD0, 0xF5, 0x90, 0x14, +0xE4, 0x26, 0x10, 0x09, 0xE8, 0xE8, 0x86, 0x56, 0xA9, 0x00, 0x80, 0xD0, 0x05, 0xB5, 0x8C, 0x09, +0x01, 0x00, 0x95, 0x8C, 0xC6, 0xBE, 0xA5, 0xBE, 0x29, 0x0F, 0x00, 0xD0, 0xD3, 0x64, 0x2A, 0xA5, +0xBE, 0x4A, 0x4A, 0x4A, 0x4A, 0xF0, 0x24, 0xA8, 0xA6, 0x56, 0xE4, 0x26, 0x30, 0x08, 0xB5, 0x8C, +0xF0, 0x0C, 0x85, 0x2A, 0xD0, 0x08, 0xE6, 0x56, 0xE6, 0x56, 0xB5, 0x8C, 0x95, 0x8E, 0xCA, 0xCA, +0x10, 0xF8, 0xA5, 0x28, 0x85, 0x8C, 0x64, 0x28, 0x88, 0xD0, 0xDD, 0xA5, 0x2A, 0xF0, 0x0B, 0xA6, +0x56, 0xB5, 0x8C, 0x09, 0x01, 0x00, 0x95, 0x8C, 0xD0, 0x0C, 0xA6, 0x56, 0xB5, 0x8C, 0xD0, 0x06, +0xC6, 0x56, 0xC6, 0x56, 0x10, 0xF4, 0x60, 0x22, 0x64, 0x00, 0xE1, 0x0B, 0x5B, 0x68, 0x85, 0x06, +0x8B, 0x8B, 0x68, 0x85, 0x08, 0x4B, 0xAB, 0x68, 0x85, 0x00, 0x68, 0x85, 0x02, 0x68, 0x85, 0x04, +0xFA, 0xAD, 0xAB, 0xD4, 0x48, 0xE0, 0x01, 0x00, 0x10, 0x03, 0x4C, 0x22, 0xEC, 0xD0, 0x03, 0x4C, +0x75, 0xE9, 0x4C, 0x1C, 0xEC, 0xA2, 0x00, 0x00, 0x68, 0x95, 0x80, 0xE8, 0xE8, 0xE0, 0x0E, 0x00, +0xD0, 0xF6, 0xA5, 0x80, 0x48, 0xE2, 0x30, 0xA0, 0x00, 0xB7, 0x8A, 0x85, 0x80, 0xA0, 0x02, 0xB7, +0x8A, 0x85, 0x81, 0xC8, 0xB7, 0x8A, 0x30, 0x08, 0xD0, 0x75, 0xA5, 0x81, 0x10, 0x0A, 0x30, 0x6F, +0x49, 0xFF, 0xD0, 0x6B, 0xA5, 0x81, 0x10, 0x67, 0xA0, 0x05, 0xB7, 0x86, 0xBB, 0x95, 0x8A, 0x88, +0x10, 0xF8, 0xA5, 0x8E, 0xF0, 0x59, 0xC9, 0x1D, 0xB0, 0x55, 0xA0, 0x00, 0x38, 0xA9, 0x2D, 0x24, +0x8A, 0xD0, 0x06, 0xA5, 0x80, 0xD0, 0x06, 0xA9, 0x20, 0x18, 0xC8, 0x97, 0x82, 0xA9, 0x03, 0x65, +0x86, 0x85, 0x86, 0x90, 0x0A, 0xE6, 0x87, 0xD0, 0x06, 0xE6, 0x88, 0xD0, 0x02, 0xE6, 0x89, 0xA5, +0x8F, 0xC9, 0x3F, 0xF0, 0x2A, 0xC9, 0x30, 0xD0, 0x0B, 0xA2, 0x00, 0x86, 0x8C, 0x86, 0x8D, 0xE8, +0x86, 0x8E, 0xD0, 0x2D, 0x29, 0xDF, 0xC9, 0x4E, 0xF0, 0x5A, 0xC9, 0x49, 0xD0, 0x23, 0xA9, 0x49, +0xC8, 0x97, 0x82, 0xA9, 0x4E, 0xC8, 0x97, 0x82, 0xA9, 0x46, 0xC8, 0x97, 0x82, 0xD0, 0x0D, 0xA9, +0x3F, 0xA0, 0x01, 0x97, 0x82, 0x98, 0x88, 0x97, 0x82, 0xC2, 0x30, 0x60, 0x98, 0xA0, 0x00, 0xF0, +0xF6, 0xA6, 0x80, 0xD0, 0x31, 0xC8, 0xB7, 0x86, 0x97, 0x82, 0xC6, 0x8E, 0xA5, 0x81, 0xC9, 0x02, +0x10, 0x08, 0xA9, 0x01, 0x85, 0x81, 0xA6, 0x8E, 0xF0, 0x11, 0xA9, 0x2E, 0xC8, 0x97, 0x82, 0xA6, +0x8E, 0xF0, 0x08, 0xB7, 0x86, 0xC8, 0x97, 0x82, 0xCA, 0xD0, 0xF8, 0xA9, 0xFF, 0x45, 0x8E, 0x30, +0x75, 0x18, 0x90, 0xBB, 0xF0, 0x72, 0xA5, 0x8D, 0x30, 0x08, 0xD0, 0xB3, 0xA5, 0x8C, 0x10, 0x0A, +0x30, 0xAD, 0x49, 0xFF, 0xD0, 0xA9, 0xA5, 0x8C, 0x10, 0xA5, 0xA5, 0x8C, 0x18, 0x65, 0x8E, 0x70, +0x9E, 0xAA, 0x30, 0x56, 0xF0, 0x54, 0xA5, 0x8C, 0x18, 0x10, 0x1B, 0x65, 0x8E, 0xC8, 0xB7, 0x86, +0x97, 0x82, 0xCA, 0xD0, 0xF8, 0xA9, 0x2E, 0xC8, 0x97, 0x82, 0xA6, 0x8C, 0xB7, 0x86, 0xC8, 0x97, +0x82, 0xE8, 0x30, 0xF8, 0x10, 0x6D, 0xA6, 0x8E, 0xC8, 0xB7, 0x86, 0x97, 0x82, 0xCA, 0xD0, 0xF8, +0x98, 0x65, 0x8C, 0x70, 0xAC, 0xC9, 0x51, 0x10, 0xA8, 0xA6, 0x8C, 0xF0, 0x0A, 0xA9, 0x30, 0xC8, +0x97, 0x82, 0xCA, 0xD0, 0xFA, 0x86, 0x8C, 0xE4, 0x81, 0x10, 0x48, 0xC0, 0x50, 0xB0, 0x6D, 0xA9, +0x2E, 0xC8, 0x97, 0x82, 0xD0, 0x3D, 0x30, 0x3D, 0xF0, 0x6A, 0xCA, 0x8A, 0xE8, 0x18, 0x65, 0x86, +0x85, 0x86, 0xA9, 0xFF, 0x65, 0x87, 0x85, 0x87, 0xA9, 0x30, 0xC8, 0x97, 0x82, 0xA9, 0x2E, 0xC8, +0x97, 0x82, 0x8A, 0xF0, 0x0C, 0xA9, 0x30, 0xC8, 0xC0, 0x51, 0xB0, 0x40, 0x97, 0x82, 0xE8, 0xD0, +0xF6, 0x98, 0x18, 0x65, 0x8E, 0xC9, 0x51, 0x10, 0x33, 0xA6, 0x8E, 0xB7, 0x86, 0xC8, 0x97, 0x82, +0xCA, 0xD0, 0xF8, 0xA5, 0x8C, 0x18, 0x65, 0x81, 0x70, 0x22, 0x30, 0x14, 0xF0, 0x12, 0xAA, 0x84, +0x81, 0x18, 0x65, 0x81, 0xC9, 0x51, 0x10, 0x14, 0xA9, 0x30, 0xC8, 0x97, 0x82, 0xCA, 0xD0, 0xFA, +0xA6, 0x80, 0xF0, 0x5E, 0x98, 0xA0, 0x00, 0x97, 0x82, 0xC2, 0x30, 0x60, 0xA9, 0x3F, 0xA0, 0x01, +0x97, 0x82, 0xD0, 0xF0, 0x85, 0x8F, 0xC8, 0x97, 0x82, 0xA9, 0x41, 0xC8, 0x97, 0x82, 0x84, 0x8B, +0xA9, 0x4E, 0xC8, 0x97, 0x82, 0xA9, 0x28, 0xC8, 0x97, 0x82, 0x84, 0x81, 0xC8, 0xC8, 0xC8, 0xA9, +0x29, 0xC8, 0x97, 0x82, 0x98, 0xA0, 0x00, 0x97, 0x82, 0x98, 0xA4, 0x8B, 0xA6, 0x8E, 0xE0, 0x06, +0x90, 0x02, 0xA2, 0x05, 0xCA, 0xF0, 0x15, 0x0A, 0x0A, 0x0A, 0x0A, 0x85, 0x8C, 0xB7, 0x86, 0xC9, +0x40, 0x90, 0x02, 0x69, 0x08, 0x29, 0x0F, 0x05, 0x8C, 0xC8, 0xD0, 0xE8, 0x85, 0x8C, 0xA9, 0xFC, +0xD0, 0x31, 0xC0, 0x54, 0xB0, 0xA6, 0xA9, 0x65, 0xC8, 0x97, 0x82, 0xA5, 0x8E, 0x65, 0x8C, 0x85, +0x8C, 0x8A, 0x65, 0x8D, 0x85, 0x8D, 0x70, 0x94, 0x30, 0x04, 0xA9, 0x2B, 0xD0, 0x0D, 0x38, 0x8A, +0xE5, 0x8C, 0x85, 0x8C, 0x8A, 0xE5, 0x8D, 0x85, 0x8D, 0xA9, 0x2D, 0xC8, 0x97, 0x82, 0xA9, 0xFA, +0xE8, 0x84, 0x81, 0x85, 0x8B, 0xA9, 0x00, 0x85, 0x86, 0x85, 0x87, 0x85, 0x88, 0xF8, 0xA0, 0x08, +0x16, 0x8C, 0xA5, 0x86, 0x65, 0x86, 0x85, 0x86, 0xA5, 0x87, 0x65, 0x87, 0x85, 0x87, 0xA5, 0x88, +0x65, 0x88, 0x85, 0x88, 0x88, 0xD0, 0xE9, 0xCA, 0x10, 0xE4, 0xD8, 0xA4, 0x81, 0xA2, 0x02, 0xB5, +0x86, 0x4A, 0x4A, 0x4A, 0x4A, 0xF0, 0x02, 0x85, 0x8B, 0xE6, 0x8B, 0x30, 0x09, 0x09, 0x30, 0xC8, +0xC0, 0x51, 0xB0, 0x90, 0x97, 0x82, 0xB5, 0x86, 0x29, 0x0F, 0xF0, 0x02, 0x85, 0x8B, 0xE6, 0x8B, +0x30, 0x09, 0x09, 0x30, 0xC8, 0xC0, 0x51, 0xB0, 0xE9, 0x97, 0x82, 0xCA, 0x10, 0xD1, 0xA5, 0x8F, +0xC9, 0x4E, 0xF0, 0x05, 0x98, 0xA0, 0x00, 0x97, 0x82, 0xC2, 0x30, 0x60, 0xA2, 0x00, 0x00, 0x4C, +0x25, 0xEC, 0xA2, 0x01, 0x00, 0x86, 0xB0, 0x7A, 0xA2, 0x00, 0x00, 0x68, 0x95, 0x80, 0xE8, 0xE8, +0xE0, 0x10, 0x00, 0x90, 0xF6, 0x5A, 0xA2, 0x10, 0x00, 0xCA, 0xCA, 0x74, 0xA0, 0xD0, 0xFA, 0x9B, +0xE2, 0x30, 0xB7, 0x88, 0x85, 0xA0, 0x85, 0xA2, 0xA6, 0xB0, 0xF0, 0x0C, 0xB7, 0x8C, 0x85, 0xA4, +0xC8, 0xB7, 0x88, 0xF0, 0x0F, 0x4C, 0x0F, 0xEE, 0xC8, 0xB7, 0x88, 0x85, 0xA1, 0x85, 0xA3, 0x18, +0x65, 0x8D, 0x85, 0x8D, 0x18, 0xA5, 0x84, 0x69, 0x04, 0x85, 0x90, 0xA5, 0x85, 0x69, 0x00, 0x85, +0x91, 0xA5, 0x86, 0x69, 0x00, 0x85, 0x92, 0xA5, 0x87, 0x69, 0x00, 0x85, 0x93, 0xA0, 0x09, 0xB9, +0x0B, 0xEF, 0x97, 0x84, 0x88, 0x10, 0xF8, 0x20, 0x02, 0xED, 0xC9, 0x20, 0xF0, 0xF9, 0xC9, 0x09, +0xF0, 0xF5, 0xC9, 0x2B, 0xF0, 0x0E, 0xC9, 0x2D, 0xD0, 0x0D, 0xA9, 0x01, 0xA0, 0x00, 0x97, 0x84, +0x98, 0xC8, 0x97, 0x84, 0x20, 0x02, 0xED, 0xC9, 0x30, 0x90, 0x0D, 0xD0, 0x19, 0x38, 0x26, 0xA6, +0x20, 0xE9, 0xEE, 0x20, 0x02, 0xED, 0xB0, 0xF3, 0xC9, 0x2E, 0xF0, 0x70, 0xA5, 0xA6, 0xF0, 0x03, +0x4C, 0xCF, 0xED, 0x4C, 0x9F, 0xEE, 0xC9, 0x3A, 0x90, 0x0A, 0xA4, 0xA6, 0xD0, 0x03, 0x4C, 0x24, +0xEE, 0x4C, 0x68, 0xED, 0x20, 0xE9, 0xEE, 0x20, 0xEF, 0xEC, 0x90, 0x04, 0xC9, 0x3A, 0x90, 0xF7, +0xC9, 0x2E, 0xD0, 0xED, 0x20, 0x02, 0xED, 0xB0, 0x03, 0x4C, 0xCF, 0xED, 0x4C, 0x64, 0xED, 0xA4, +0xAA, 0xC0, 0x1C, 0xB0, 0x07, 0xC8, 0x84, 0xAA, 0x97, 0x90, 0xD0, 0x06, 0xE6, 0xAD, 0xD0, 0x02, +0xE6, 0xAE, 0xA9, 0x02, 0x85, 0xA9, 0x20, 0xF9, 0xEE, 0x90, 0x0F, 0xA4, 0xA0, 0xB7, 0x8C, 0xE6, +0xA0, 0xD0, 0x04, 0xE6, 0xA1, 0xE6, 0x8D, 0xC9, 0x30, 0x60, 0xE6, 0xA7, 0xA4, 0xA9, 0x68, 0x88, +0xD0, 0xFC, 0xA4, 0xA3, 0x30, 0x03, 0x4C, 0x9F, 0xEE, 0x4C, 0xD7, 0xED, 0x20, 0x02, 0xED, 0xF0, +0x10, 0x90, 0x04, 0xC9, 0x3A, 0x90, 0x1A, 0xA6, 0xA6, 0xD0, 0x2D, 0x4C, 0x9F, 0xEE, 0x4C, 0xCF, +0xED, 0x38, 0x26, 0xA6, 0x20, 0xE9, 0xEE, 0xA6, 0xAD, 0xD0, 0x02, 0xC6, 0xAE, 0xC6, 0xAD, 0xD0, +0xDB, 0x20, 0xE9, 0xEE, 0xA6, 0xAD, 0xD0, 0x02, 0xC6, 0xAE, 0xC6, 0xAD, 0x20, 0xEF, 0xEC, 0xB0, +0x03, 0x4C, 0xCF, 0xED, 0xC9, 0x3A, 0x90, 0xE9, 0x20, 0xF0, 0xEE, 0xA6, 0xA2, 0xD0, 0x02, 0xC6, +0xA3, 0xC6, 0xA2, 0xC9, 0x45, 0xF0, 0x04, 0xC9, 0x65, 0xD0, 0x4D, 0x20, 0x02, 0xED, 0xC9, 0x2B, +0xF0, 0x06, 0xC9, 0x2D, 0xD0, 0x05, 0xE6, 0xA8, 0x20, 0x02, 0xED, 0xC9, 0x30, 0x90, 0x39, 0xC9, +0x3A, 0xB0, 0x35, 0x20, 0xE9, 0xEE, 0x29, 0x0F, 0xAA, 0x06, 0xAB, 0x26, 0xAC, 0xA5, 0xAC, 0x85, +0xAF, 0xA5, 0xAB, 0x0A, 0x26, 0xAF, 0x0A, 0x26, 0xAF, 0x65, 0xAB, 0x85, 0xAB, 0xA5, 0xAF, 0x65, +0xAC, 0x85, 0xAC, 0x18, 0x8A, 0x65, 0xAB, 0x85, 0xAB, 0x90, 0x02, 0xE6, 0xAC, 0xA9, 0x14, 0xC5, +0xAC, 0xB0, 0x02, 0x85, 0xAC, 0x4C, 0x88, 0xED, 0xA4, 0xA3, 0x30, 0x03, 0x4C, 0x9F, 0xEE, 0xA6, +0xA0, 0xD0, 0x02, 0xC6, 0xA1, 0xC6, 0xA0, 0xA0, 0x00, 0xA5, 0xAA, 0xD0, 0x0F, 0xA5, 0xA6, 0xF0, +0x2E, 0xA9, 0x01, 0x97, 0x90, 0xC8, 0xA9, 0x30, 0x97, 0x90, 0xD0, 0x23, 0x97, 0x90, 0xA5, 0xA8, +0xF0, 0x0D, 0x38, 0xA9, 0x00, 0xE5, 0xAB, 0x85, 0xAB, 0xA9, 0x00, 0xE5, 0xAC, 0x85, 0xAC, 0xA0, +0x02, 0x18, 0xA5, 0xAB, 0x65, 0xAD, 0x97, 0x84, 0xC8, 0xA5, 0xAC, 0x65, 0xAE, 0x97, 0x84, 0xA0, +0x00, 0xA5, 0xA0, 0x97, 0x88, 0xA5, 0xA7, 0x97, 0x80, 0x98, 0xC8, 0x97, 0x80, 0xA5, 0xA1, 0x97, +0x88, 0xC2, 0x30, 0x60, 0xA6, 0xA0, 0xD0, 0x02, 0xC6, 0xA1, 0xC6, 0xA0, 0x20, 0xD0, 0xEE, 0xC9, +0x49, 0xD0, 0x03, 0x4C, 0xAA, 0xEE, 0xC9, 0x4E, 0xD0, 0x65, 0x20, 0xD0, 0xEE, 0xC9, 0x41, 0xD0, +0x5E, 0x20, 0xD0, 0xEE, 0xC9, 0x4E, 0xD0, 0x57, 0xA0, 0x02, 0xA9, 0x34, 0x97, 0x90, 0xA9, 0x30, +0xC8, 0xC8, 0x97, 0x90, 0xC8, 0x97, 0x90, 0x20, 0xF0, 0xEE, 0x20, 0x02, 0xED, 0xC9, 0x28, 0xD0, +0x3E, 0x20, 0x02, 0xED, 0x90, 0x1C, 0xC9, 0x3A, 0xB0, 0x35, 0x29, 0x0F, 0x85, 0xAF, 0x06, 0xA5, +0xA5, 0xA5, 0x0A, 0x0A, 0x18, 0x65, 0xA5, 0x18, 0x65, 0xAF, 0x85, 0xA5, 0x4C, 0x61, 0xEE, 0x20, +0x02, 0xED, 0xC9, 0x29, 0xD0, 0x19, 0xA5, 0xA5, 0x4A, 0x4A, 0x4A, 0x4A, 0x20, 0xE0, 0xEE, 0xA0, +0x04, 0x97, 0x90, 0xA5, 0xA5, 0x29, 0x0F, 0x20, 0xE0, 0xEE, 0xC8, 0x97, 0x90, 0xD0, 0x24, 0xA6, +0xA2, 0x86, 0xA0, 0xA6, 0xA3, 0x86, 0xA1, 0x4C, 0xD7, 0xED, 0x20, 0xD0, 0xEE, 0xC9, 0x4E, 0xD0, +0xEE, 0x20, 0xD0, 0xEE, 0xC9, 0x46, 0xD0, 0xE7, 0xA0, 0x00, 0xA9, 0x01, 0x97, 0x90, 0xA9, 0x49, +0xC8, 0x97, 0x90, 0x20, 0xE9, 0xEE, 0x20, 0xF9, 0xEE, 0xB0, 0x02, 0xE6, 0xA7, 0x4C, 0x0F, 0xEE, +0xA9, 0x04, 0x20, 0x04, 0xED, 0xC9, 0x61, 0x90, 0x06, 0xC9, 0x7B, 0xB0, 0x02, 0x29, 0xDF, 0x60, +0xC9, 0x0A, 0x90, 0x02, 0x69, 0x06, 0x69, 0x30, 0x60, 0xA2, 0xFF, 0x86, 0xA2, 0x86, 0xA3, 0x60, +0xA6, 0xA0, 0x86, 0xA2, 0xA6, 0xA1, 0x86, 0xA3, 0x60, 0xA6, 0xB0, 0xF0, 0x05, 0xA6, 0xA4, 0xE4, +0xA0, 0x60, 0x38, 0xA4, 0xA0, 0xB7, 0x8C, 0xD0, 0x01, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x05, +0x4E, 0x30, 0x30, 0x31, 0x31, 0x22, 0x64, 0x00, 0xE1, 0x0B, 0x5B, 0x68, 0x85, 0x06, 0x8B, 0x8B, +0x68, 0x85, 0x08, 0x4B, 0xAB, 0x80, 0x04, 0x22, 0x64, 0x00, 0xE1, 0x68, 0x85, 0xF3, 0x68, 0x85, +0xF1, 0x68, 0x85, 0xEF, 0xE2, 0x30, 0x68, 0x85, 0x62, 0x68, 0x18, 0x66, 0x62, 0xA6, 0x62, 0xBD, +0xCE, 0xEF, 0x85, 0x63, 0x68, 0x85, 0xAA, 0x68, 0x85, 0xAB, 0x68, 0x85, 0xAC, 0x68, 0xDA, 0xA0, +0x09, 0xBB, 0xB7, 0xAA, 0x95, 0x82, 0x88, 0xCA, 0x10, 0xF8, 0xFA, 0xA5, 0x6A, 0x85, 0xB0, 0xA5, +0x6B, 0x85, 0xB1, 0xA5, 0x6C, 0x85, 0xB2, 0xA5, 0x6D, 0x85, 0xB3, 0xA5, 0x63, 0x30, 0x03, 0x4C, +0xF6, 0xEF, 0xA5, 0x62, 0xC9, 0x08, 0xF0, 0x2E, 0x68, 0x85, 0xAD, 0x68, 0x85, 0xAE, 0x68, 0x85, +0xAF, 0x68, 0xDA, 0xA0, 0x09, 0xBB, 0xB7, 0xAD, 0x95, 0x96, 0x88, 0xCA, 0x10, 0xF8, 0xFA, 0xA5, +0xAD, 0x85, 0x7C, 0xA5, 0xAE, 0x85, 0x7D, 0xA5, 0xAF, 0x85, 0x7E, 0x20, 0xDF, 0xEF, 0x86, 0x6A, +0x29, 0x80, 0x85, 0x6B, 0x80, 0x06, 0x68, 0x85, 0x70, 0x68, 0x85, 0x71, 0xA9, 0xC0, 0x25, 0x63, +0x49, 0xC0, 0xD0, 0x46, 0x68, 0x85, 0xAD, 0x68, 0x85, 0xAE, 0x68, 0x85, 0xAF, 0x68, 0xDA, 0xA0, +0x09, 0xBB, 0xB7, 0xAD, 0x95, 0xA0, 0x88, 0xCA, 0x10, 0xF8, 0xFA, 0x4C, 0x0F, 0xF0, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, +0x30, 0xA6, 0x7C, 0x0B, 0x8B, 0xA5, 0x7E, 0x48, 0x80, 0x05, 0x0B, 0x8B, 0xF4, 0x00, 0x00, 0xDA, +0xA9, 0x1C, 0x00, 0x4C, 0xF2, 0xF0, 0xA9, 0x00, 0x85, 0x6A, 0xA2, 0x0A, 0xB5, 0x81, 0x95, 0x9F, +0xCA, 0xD0, 0xF9, 0xA5, 0xAA, 0x85, 0xAD, 0xA5, 0xAB, 0x85, 0xAE, 0xA5, 0xAC, 0x85, 0xAF, 0xA5, +0xAD, 0x85, 0x7C, 0xA5, 0xAE, 0x85, 0x7D, 0xA5, 0xAF, 0x85, 0x7E, 0x20, 0xDF, 0xEF, 0x86, 0x6C, +0x29, 0x80, 0x85, 0x6D, 0xC2, 0x30, 0xA5, 0xEF, 0x48, 0xA5, 0xF1, 0x48, 0xA5, 0xF3, 0x48, 0x20, +0x72, 0xF0, 0xA5, 0xAC, 0x48, 0xA5, 0xAB, 0x48, 0xA5, 0xAA, 0x48, 0xA5, 0x69, 0x48, 0xA5, 0x68, +0x48, 0xA5, 0xB0, 0x48, 0xA5, 0xB1, 0x48, 0xA5, 0xB2, 0x48, 0xA5, 0xB3, 0x48, 0xA5, 0x6A, 0xC9, +0xFE, 0x10, 0x0D, 0xA2, 0x04, 0x20, 0x63, 0xF2, 0xA2, 0x02, 0x20, 0xD4, 0xF0, 0x4C, 0x6F, 0xF0, +0xA5, 0x6C, 0xC9, 0xFE, 0x10, 0x1D, 0xA2, 0x04, 0xA0, 0x00, 0xA9, 0x0E, 0x20, 0xD8, 0xF0, 0x4C, +0x56, 0xF3, 0x0B, 0x8B, 0xF4, 0x00, 0x00, 0x18, 0x7B, 0x69, 0x68, 0x00, 0x48, 0xA9, 0x17, 0x00, +0x4C, 0xF2, 0xF0, 0xA5, 0x62, 0x0A, 0xA8, 0xB9, 0x91, 0xF0, 0x48, 0xB9, 0x90, 0xF0, 0x48, 0x60, +0xA8, 0xF3, 0xA8, 0xF3, 0xA8, 0xF3, 0xA8, 0xF3, 0xD5, 0xF4, 0xD5, 0xF4, 0x52, 0xF5, 0x52, 0xF5, +0x13, 0xF6, 0x0D, 0xF7, 0x02, 0xF8, 0x6C, 0xF8, 0x47, 0xFE, 0xA7, 0xFC, 0xFA, 0xFC, 0xBD, 0xFD, +0x07, 0xFF, 0xA2, 0x0E, 0xA0, 0x00, 0xA9, 0x04, 0xD0, 0x1E, 0xA2, 0x0C, 0xA0, 0x0E, 0xD0, 0xF6, +0xA2, 0x28, 0xA0, 0x0C, 0xD0, 0xF0, 0xA2, 0x02, 0xA0, 0x62, 0xD0, 0xEA, 0xA0, 0x00, 0xA9, 0x0C, +0xD0, 0x06, 0xA2, 0x1C, 0xA0, 0x00, 0xA9, 0x00, 0x85, 0x7C, 0xC2, 0x30, 0x0B, 0x8B, 0x20, 0x5B, +0xF1, 0xDA, 0x48, 0xBB, 0xA0, 0x00, 0x00, 0x20, 0x5B, 0xF1, 0xDA, 0x48, 0xE2, 0x30, 0x98, 0x48, +0xA5, 0x7C, 0x48, 0xC2, 0x30, 0x22, 0xA4, 0xF3, 0xFE, 0xE2, 0x30, 0x08, 0x68, 0xAB, 0x2B, 0x48, +0x28, 0x60, 0x85, 0x7C, 0xC2, 0x30, 0x0B, 0x8B, 0x20, 0x5B, 0xF1, 0xDA, 0x48, 0xBB, 0xA0, 0x04, +0x00, 0x80, 0xD4, 0xC2, 0x30, 0x0B, 0x8B, 0x20, 0x5B, 0xF1, 0xDA, 0x48, 0xE2, 0x30, 0xA9, 0x00, +0x48, 0x98, 0xD0, 0xCE, 0x64, 0x7E, 0xC2, 0x30, 0x0B, 0x8B, 0x18, 0x7B, 0x79, 0x42, 0xFC, 0x85, +0x7C, 0xA7, 0x7C, 0x48, 0xE2, 0x30, 0xA9, 0x04, 0x48, 0x8A, 0x4C, 0xF2, 0xF0, 0x0B, 0x8B, 0x98, +0x80, 0xB0, 0xA2, 0x62, 0xC2, 0x30, 0x0B, 0x8B, 0x20, 0x5B, 0xF1, 0xDA, 0x48, 0x5A, 0xE2, 0x30, +0xC2, 0x30, 0x22, 0x9F, 0xF3, 0xFE, 0xAB, 0x2B, 0xE2, 0x30, 0x60, 0x08, 0xE2, 0x30, 0xE0, 0x14, +0x90, 0x10, 0xE0, 0x5C, 0xB0, 0x0C, 0xA9, 0x00, 0x48, 0xC2, 0x30, 0xBD, 0x42, 0xFC, 0x8B, 0xFA, +0x80, 0x0A, 0xC2, 0x30, 0x18, 0x7B, 0x7D, 0x42, 0xFC, 0xA2, 0x00, 0x00, 0x28, 0x60, 0xA9, 0x0E, +0xD0, 0x0A, 0xA2, 0x0E, 0xA9, 0x10, 0xD0, 0x04, 0xA9, 0x0C, 0xA4, 0xC3, 0xC2, 0x30, 0x29, 0xFF, +0x00, 0x85, 0x7C, 0x18, 0x7B, 0x7D, 0x42, 0xFC, 0x85, 0xEF, 0xB9, 0x42, 0xFC, 0x85, 0x7F, 0xA6, +0x7C, 0x18, 0x7B, 0x7D, 0x42, 0xFC, 0x85, 0x7C, 0xE2, 0x30, 0xA0, 0x00, 0xB1, 0x7F, 0x85, 0xF2, +0xA2, 0x02, 0xA0, 0x0E, 0x20, 0xC8, 0xF1, 0xA0, 0x04, 0x20, 0xEE, 0xF1, 0xA2, 0x0A, 0xA0, 0x00, +0x20, 0xC8, 0xF1, 0xC6, 0xF2, 0xD0, 0xF0, 0x60, 0x18, 0x8A, 0x65, 0x7F, 0x85, 0x7F, 0xA5, 0x80, +0x69, 0x00, 0x85, 0x80, 0xA2, 0x00, 0x0B, 0x8B, 0xDA, 0x8B, 0x48, 0xA5, 0x7F, 0x48, 0xF4, 0x00, +0x00, 0xA5, 0xF0, 0x48, 0xA5, 0xEF, 0x48, 0xA9, 0x00, 0x48, 0x98, 0x4C, 0xF2, 0xF0, 0x0B, 0x8B, +0xF4, 0x00, 0x00, 0xA5, 0x7D, 0x48, 0xA5, 0x7C, 0x80, 0xE3, 0xA9, 0x02, 0xD0, 0x0A, 0xA9, 0x04, +0xD0, 0x06, 0xA9, 0x01, 0xD0, 0x02, 0xA9, 0x10, 0x85, 0x64, 0xC2, 0x30, 0xA0, 0x03, 0x00, 0x20, +0x3D, 0xF1, 0x86, 0xC5, 0x84, 0xC6, 0xA5, 0x64, 0x49, 0xFF, 0x25, 0xC6, 0x85, 0xC6, 0x0B, 0x8B, +0xA5, 0xC6, 0x48, 0xA5, 0xC5, 0x48, 0x48, 0xA9, 0x01, 0x4C, 0xF2, 0xF0, 0xA9, 0x04, 0xD0, 0x0E, +0xA9, 0x02, 0xD0, 0x0A, 0xA9, 0x08, 0xD0, 0x06, 0xA9, 0x01, 0xD0, 0x02, 0xA9, 0x10, 0x85, 0x64, +0xA2, 0x15, 0xD0, 0x16, 0xA9, 0x02, 0xD0, 0x0E, 0xA9, 0x04, 0xD0, 0x0A, 0xA9, 0x08, 0xD0, 0x06, +0xA9, 0x01, 0xD0, 0x02, 0xA9, 0x10, 0x85, 0x64, 0xA2, 0x1B, 0xA9, 0x00, 0x85, 0x65, 0xA0, 0x5C, +0x4C, 0x24, 0xF1, 0xA0, 0x00, 0x20, 0x5B, 0xF1, 0x85, 0x7C, 0xEB, 0x85, 0x7D, 0x86, 0x7E, 0x64, +0x81, 0xC2, 0x30, 0x18, 0x7B, 0x79, 0x42, 0xFC, 0x85, 0x7F, 0xA0, 0x08, 0x00, 0xB7, 0x7C, 0x97, +0x7F, 0x88, 0x88, 0x10, 0xF8, 0xE2, 0x30, 0x60, 0x38, 0xA9, 0x00, 0xE5, 0xC5, 0x85, 0xC5, 0xA9, +0x00, 0xE5, 0xC6, 0x85, 0xC6, 0x60, 0xAD, 0xA8, 0xFA, 0x85, 0xC5, 0xAD, 0xA9, 0xFA, 0x85, 0xC6, +0xDA, 0xA0, 0x09, 0xBB, 0xB7, 0x7F, 0x95, 0xDB, 0x88, 0xCA, 0x10, 0xF8, 0xFA, 0xA2, 0x10, 0x20, +0x8E, 0xF6, 0x20, 0x06, 0xF3, 0x70, 0x0C, 0xF0, 0x0A, 0xA2, 0x24, 0xA0, 0x10, 0x20, 0x2D, 0xF5, +0x20, 0xF7, 0xF2, 0x20, 0x06, 0xF3, 0x70, 0x07, 0xF0, 0x05, 0xA2, 0x24, 0x4C, 0xD1, 0xF2, 0xA2, +0x10, 0xA0, 0x0A, 0xA9, 0x10, 0x20, 0x02, 0xF1, 0x4C, 0xF7, 0xF2, 0x0B, 0x8B, 0xA5, 0xC6, 0x48, +0xA5, 0xC5, 0x48, 0xA9, 0x00, 0x48, 0xA5, 0xF1, 0x48, 0xA5, 0xF0, 0x48, 0xA5, 0xEF, 0x48, 0xA9, +0x00, 0x48, 0xA9, 0x18, 0x4C, 0xF2, 0xF0, 0xC2, 0x30, 0xA6, 0x7F, 0x20, 0xEA, 0xEF, 0x10, 0x03, +0x20, 0x88, 0xF2, 0x4C, 0xDB, 0xF2, 0xA2, 0x24, 0xA0, 0x10, 0xA9, 0x08, 0x4C, 0xD8, 0xF0, 0xA2, +0x3A, 0xD0, 0x18, 0xA2, 0x3C, 0xD0, 0x14, 0xA2, 0x1C, 0xD0, 0x10, 0xA2, 0x1E, 0xD0, 0x0C, 0x20, +0x34, 0xF2, 0xA2, 0x3E, 0xD0, 0x05, 0x20, 0x34, 0xF2, 0xA2, 0x40, 0x20, 0x63, 0xF2, 0x4C, 0x56, +0xF3, 0xA5, 0x6F, 0xD0, 0x05, 0xA9, 0x7F, 0x4C, 0x3C, 0xF3, 0xA9, 0xFF, 0x85, 0x8B, 0xA9, 0xFF, +0x85, 0x8A, 0xA9, 0x40, 0x85, 0x89, 0xA5, 0x6E, 0x85, 0x88, 0xA9, 0x00, 0xA2, 0x05, 0x95, 0x82, +0xCA, 0x10, 0xFB, 0x20, 0x38, 0xF2, 0x68, 0x85, 0x6D, 0x68, 0x85, 0x6C, 0x68, 0x85, 0x6B, 0x68, +0x85, 0x6A, 0x68, 0x85, 0x66, 0x68, 0x85, 0x67, 0x68, 0x85, 0xAA, 0x68, 0x85, 0xAB, 0x68, 0x85, +0xAC, 0xA0, 0x09, 0xDA, 0xBB, 0xB5, 0x82, 0x97, 0xAA, 0x88, 0xCA, 0x10, 0xF8, 0xFA, 0xC2, 0x30, +0x68, 0x85, 0xEF, 0x68, 0x85, 0xF1, 0x68, 0x85, 0xF3, 0xA5, 0x66, 0x48, 0xF4, 0x19, 0x00, 0xA5, +0xF3, 0x48, 0xA5, 0xF1, 0x48, 0xA5, 0xEF, 0x48, 0x22, 0x68, 0x00, 0xE1, 0x4C, 0xCA, 0xD3, 0x22, +0x27, 0xEF, 0xFE, 0x6B, 0x22, 0xCA, 0xD3, 0xFE, 0x6B, 0xA5, 0x6C, 0xC9, 0xFE, 0xF0, 0x11, 0xA9, +0x02, 0x24, 0x62, 0xD0, 0x1D, 0xA5, 0x6C, 0x30, 0x2F, 0xA5, 0x6D, 0x30, 0x0A, 0x4C, 0x2C, 0xF4, +0xA5, 0x6D, 0xD0, 0x03, 0x4C, 0x22, 0xF3, 0xA5, 0x6D, 0x85, 0x6F, 0xA9, 0x24, 0x85, 0x6E, 0x4C, +0x31, 0xF3, 0xA5, 0x6C, 0x10, 0x03, 0x4C, 0x56, 0xF3, 0xA2, 0x1E, 0xA0, 0x00, 0x20, 0x0A, 0xF3, +0x70, 0xE5, 0x30, 0x02, 0xD0, 0xE1, 0x30, 0x03, 0x4C, 0x26, 0xF3, 0x20, 0x17, 0xF4, 0x20, 0xD2, +0xF0, 0xA2, 0x00, 0xA0, 0x2A, 0x20, 0x0A, 0xF3, 0x30, 0x32, 0xF0, 0x30, 0x50, 0x2E, 0xA2, 0x26, +0xA0, 0x00, 0x20, 0x0A, 0xF3, 0x30, 0x25, 0xF0, 0x23, 0x20, 0x12, 0xF4, 0x20, 0x8C, 0xF4, 0x4C, +0x67, 0xF4, 0xA2, 0x0C, 0x4C, 0x63, 0xF2, 0xA2, 0x00, 0xA0, 0x0C, 0x4C, 0x65, 0xF2, 0xA2, 0x00, +0xA0, 0x0E, 0x4C, 0x65, 0xF2, 0xA2, 0x00, 0xA0, 0x10, 0x4C, 0x65, 0xF2, 0x20, 0x17, 0xF4, 0xA2, +0x0C, 0xA0, 0x1A, 0x20, 0x13, 0xF1, 0xA2, 0x0C, 0x20, 0x88, 0xF6, 0x20, 0xB2, 0xF5, 0xA2, 0x0C, +0x20, 0x88, 0xF6, 0xA2, 0x00, 0xA0, 0x26, 0x20, 0x0A, 0xF3, 0x30, 0x0E, 0xF0, 0x0C, 0x50, 0x0A, +0xA2, 0x1C, 0xA0, 0x0C, 0x20, 0xD6, 0xF0, 0x20, 0x75, 0xF4, 0xA2, 0x1C, 0x20, 0x2B, 0xF5, 0x20, +0x8C, 0xF4, 0xA2, 0x0C, 0x20, 0xD4, 0xF0, 0xA9, 0x01, 0x24, 0x62, 0xD0, 0x05, 0xA2, 0x38, 0x20, +0xB4, 0xF0, 0x4C, 0x56, 0xF3, 0xC2, 0x30, 0x0B, 0x8B, 0xA9, 0xFF, 0xFF, 0x48, 0xF4, 0x00, 0x00, +0x18, 0x7B, 0x69, 0x82, 0x00, 0x48, 0xA9, 0x18, 0x00, 0x4C, 0xF2, 0xF0, 0x20, 0x7F, 0xF6, 0xE0, +0xFF, 0xD0, 0x01, 0x60, 0xE0, 0x00, 0xF0, 0x05, 0xA2, 0x38, 0x4C, 0xD0, 0xF4, 0x20, 0x1E, 0xF4, +0xA2, 0x20, 0x20, 0xD4, 0xF0, 0xA2, 0x00, 0xA0, 0x0E, 0x20, 0xBC, 0xF6, 0xA2, 0x0E, 0xA0, 0x10, +0x20, 0x65, 0xF2, 0xA2, 0x0E, 0x20, 0xBC, 0xF0, 0xA2, 0x00, 0xA0, 0x14, 0x20, 0x7E, 0xF1, 0xA2, +0x10, 0x20, 0xB4, 0xF0, 0xA2, 0x10, 0xA0, 0x16, 0x20, 0x7E, 0xF1, 0x20, 0xFA, 0xF1, 0xA2, 0x10, +0x20, 0xBA, 0xF6, 0x4C, 0x3C, 0xF2, 0xA5, 0x6C, 0x10, 0x11, 0xC9, 0xFF, 0xF0, 0x07, 0xA5, 0x6D, +0x30, 0x06, 0x4C, 0x56, 0xF3, 0x4C, 0x17, 0xF3, 0x4C, 0x0F, 0xF3, 0xA9, 0x01, 0x24, 0x62, 0xF0, +0x06, 0x20, 0x20, 0xF5, 0x4C, 0x17, 0xF5, 0x20, 0x32, 0xF5, 0x20, 0x48, 0xF2, 0xF0, 0x18, 0x20, +0x08, 0xF5, 0x20, 0x30, 0xF2, 0x4C, 0x0F, 0xF3, 0x20, 0x3C, 0xF2, 0xA5, 0x6D, 0x30, 0x05, 0x68, +0x68, 0x4C, 0x22, 0xF3, 0x4C, 0xFE, 0xF1, 0x20, 0xCF, 0xF5, 0x20, 0xAF, 0xF5, 0x4C, 0x56, 0xF3, +0x20, 0x17, 0xF4, 0x20, 0x92, 0xF6, 0x20, 0x06, 0xF2, 0xA2, 0x0C, 0xA0, 0x00, 0xA9, 0x02, 0x4C, +0xD8, 0xF0, 0x20, 0x17, 0xF4, 0xA2, 0x38, 0x20, 0xCC, 0xF0, 0xA2, 0x00, 0xA0, 0x0C, 0x20, 0x2D, +0xF5, 0xA2, 0x38, 0xA0, 0x0C, 0x20, 0xBC, 0xF6, 0x20, 0x92, 0xF6, 0xA2, 0x38, 0x20, 0xBA, 0xF6, +0x4C, 0x06, 0xF2, 0xA5, 0x6C, 0x10, 0x0E, 0xC9, 0xFF, 0xF0, 0x07, 0xA5, 0x6D, 0x10, 0x03, 0x4C, +0x1B, 0xF3, 0x4C, 0x56, 0xF3, 0xA9, 0x01, 0x24, 0x62, 0xF0, 0x18, 0xA5, 0x6C, 0xF0, 0x0E, 0xA2, +0x38, 0x20, 0xB4, 0xF0, 0x20, 0x30, 0xF2, 0x20, 0x3C, 0xF2, 0x4C, 0xAC, 0xF5, 0x20, 0x20, 0xF5, +0x4C, 0x95, 0xF5, 0xA5, 0x6C, 0xD0, 0xED, 0x20, 0x32, 0xF5, 0x20, 0x48, 0xF2, 0xF0, 0x06, 0x20, +0x08, 0xF5, 0x4C, 0x1B, 0xF3, 0x20, 0xCF, 0xF5, 0xA2, 0x0C, 0xA0, 0x3A, 0x20, 0x0A, 0xF3, 0xF0, +0x0B, 0x20, 0xAF, 0xF5, 0xA2, 0x1C, 0x20, 0x2B, 0xF5, 0x20, 0xFA, 0xF1, 0x4C, 0x56, 0xF3, 0x20, +0xD2, 0xF0, 0xC2, 0x30, 0x18, 0x7B, 0x69, 0x82, 0x00, 0x85, 0xEF, 0xE2, 0x30, 0x64, 0xF1, 0xC2, +0x30, 0x18, 0x7B, 0x69, 0xC7, 0x00, 0x85, 0x7F, 0xE2, 0x30, 0x64, 0x81, 0x4C, 0x96, 0xF2, 0xA2, +0x00, 0xA0, 0x3A, 0x20, 0x0A, 0xF3, 0x30, 0x05, 0x70, 0x03, 0xD0, 0x01, 0x60, 0x20, 0x25, 0xF4, +0xA2, 0x10, 0xA0, 0x10, 0x20, 0xB6, 0xF0, 0xA0, 0x18, 0x20, 0x82, 0xF1, 0x20, 0xB2, 0xF0, 0xA0, +0x1A, 0x20, 0x82, 0xF1, 0xA2, 0x00, 0xA0, 0x0E, 0x20, 0x2D, 0xF5, 0xA2, 0x20, 0x20, 0xB4, 0xF0, +0xA2, 0x0E, 0x20, 0xBA, 0xF6, 0x20, 0x3C, 0xF2, 0x4C, 0xFA, 0xF1, 0xA5, 0x70, 0x85, 0xC5, 0xA5, +0x71, 0x85, 0xC6, 0x60, 0xA5, 0x70, 0x05, 0x71, 0xD0, 0x03, 0x4C, 0x17, 0xF3, 0xA5, 0x6C, 0x10, +0x2F, 0x20, 0x0B, 0xF6, 0x46, 0xC6, 0x66, 0xC5, 0xB0, 0x03, 0x20, 0x8C, 0xF6, 0xA5, 0x71, 0x30, +0x03, 0x4C, 0x56, 0xF3, 0xA5, 0x6C, 0xC9, 0xFF, 0xF0, 0x0B, 0x20, 0x7F, 0xF6, 0x30, 0x03, 0x4C, +0x0F, 0xF3, 0x4C, 0x13, 0xF3, 0x20, 0x7F, 0xF6, 0x30, 0x03, 0x4C, 0x1F, 0xF3, 0x4C, 0x26, 0xF3, +0x20, 0xD4, 0xF7, 0xA5, 0xF3, 0xD0, 0x06, 0x20, 0x98, 0xF6, 0x4C, 0x56, 0xF3, 0x20, 0x7F, 0xF6, +0x29, 0x80, 0x48, 0x20, 0x8C, 0xF6, 0xA2, 0x06, 0xA0, 0x02, 0xA9, 0x0E, 0x20, 0x02, 0xF1, 0x20, +0xF0, 0xF6, 0x68, 0x10, 0x07, 0x46, 0x70, 0x90, 0x03, 0x20, 0x86, 0xF6, 0x4C, 0x56, 0xF3, 0xA2, +0x00, 0xA0, 0x1C, 0x4C, 0x13, 0xF1, 0xA2, 0x00, 0xA0, 0x0D, 0xD0, 0xF7, 0xA2, 0x00, 0xA0, 0x0F, +0xD0, 0xF1, 0xA2, 0x0C, 0xA0, 0x14, 0xD0, 0xEB, 0x20, 0x1E, 0xF4, 0x20, 0xD5, 0xF6, 0xA5, 0x71, +0x30, 0x07, 0xA2, 0x0C, 0xA0, 0x00, 0x4C, 0x12, 0xF4, 0xA2, 0x1C, 0x20, 0x63, 0xF2, 0x20, 0x44, +0xF2, 0xD0, 0x0E, 0x20, 0x48, 0xF2, 0xD0, 0x09, 0xA2, 0x0C, 0xA0, 0x00, 0xA9, 0x06, 0x4C, 0xD8, +0xF0, 0x20, 0xFE, 0xF1, 0x20, 0xFA, 0xF1, 0xA2, 0x0E, 0x20, 0xBA, 0xF6, 0x20, 0xD4, 0xF7, 0x20, +0xD5, 0xF6, 0x4C, 0xA2, 0xF6, 0xA2, 0x1C, 0x20, 0x19, 0xF4, 0x4C, 0xE2, 0xF6, 0xA2, 0x00, 0x20, +0xB4, 0xF0, 0x46, 0xF2, 0x90, 0x05, 0xA2, 0x00, 0x20, 0xC2, 0xF0, 0xA5, 0xF2, 0xD0, 0xEE, 0x60, +0xA2, 0x00, 0x20, 0x09, 0xF7, 0xA0, 0x02, 0x20, 0x42, 0xF1, 0x20, 0xC6, 0xF0, 0xA0, 0x0A, 0x20, +0x42, 0xF1, 0xA2, 0x62, 0x4C, 0x63, 0xF2, 0xA2, 0x04, 0xA0, 0x62, 0x4C, 0x65, 0xF2, 0xA5, 0x6D, +0x30, 0x16, 0x20, 0x6D, 0xF7, 0x4C, 0x56, 0xF3, 0x68, 0x68, 0x20, 0x06, 0xF2, 0xA9, 0x25, 0x85, +0x6E, 0xA5, 0x6B, 0x85, 0x6F, 0x4C, 0x31, 0xF3, 0xA5, 0x6A, 0xC9, 0xFE, 0xF0, 0xEC, 0xA2, 0x02, +0x20, 0x19, 0xF4, 0xA2, 0x02, 0x20, 0x94, 0xF6, 0xA2, 0x02, 0x20, 0x94, 0xF6, 0x20, 0x54, 0xF2, +0xD0, 0xD8, 0xA2, 0x20, 0xA0, 0x0C, 0x20, 0xBC, 0xF6, 0x20, 0x92, 0xF6, 0xC2, 0x30, 0xA0, 0x03, +0x00, 0x20, 0x3D, 0xF1, 0x86, 0xC3, 0x84, 0xC4, 0x20, 0x06, 0xF2, 0x20, 0x8C, 0xF6, 0x20, 0x6D, +0xF7, 0xA9, 0x10, 0x24, 0xC4, 0xF0, 0x03, 0x20, 0x86, 0xF6, 0x4C, 0x56, 0xF3, 0xA5, 0x6C, 0xC9, +0xFF, 0xD0, 0x19, 0xA5, 0x6A, 0xC9, 0xFF, 0xD0, 0x03, 0x4C, 0x18, 0xF7, 0xA5, 0x6B, 0x10, 0x07, +0x20, 0x34, 0xF2, 0xA2, 0x3E, 0xD0, 0x02, 0xA2, 0x3A, 0x4C, 0x63, 0xF2, 0x10, 0x09, 0xA5, 0x6A, +0xC9, 0xFF, 0xD0, 0x19, 0x4C, 0x18, 0xF7, 0xA5, 0x6A, 0xC9, 0xFE, 0xD0, 0x10, 0xA2, 0x00, 0xA0, +0x1C, 0x20, 0x0A, 0xF3, 0x30, 0x07, 0x70, 0x05, 0xD0, 0x03, 0x4C, 0x18, 0xF7, 0xA2, 0x02, 0xA0, +0x06, 0xA9, 0x10, 0x20, 0x02, 0xF1, 0xA9, 0x11, 0x85, 0x64, 0xA2, 0x1B, 0x20, 0x5E, 0xF2, 0xF0, +0x06, 0x20, 0x02, 0xF2, 0x4C, 0xEF, 0xF7, 0x20, 0x02, 0xF2, 0x20, 0xD4, 0xF7, 0xA5, 0xF3, 0xD0, +0x1E, 0x4C, 0x98, 0xF6, 0xA5, 0x70, 0x85, 0xF2, 0xA5, 0x71, 0x85, 0xF3, 0xA5, 0x71, 0x10, 0x0E, +0x20, 0x0B, 0xF6, 0x20, 0x88, 0xF2, 0xA5, 0xC5, 0x85, 0xF2, 0xA5, 0xC6, 0x85, 0xF3, 0x60, 0x20, +0x06, 0xF2, 0x18, 0xA5, 0x6A, 0x20, 0xF0, 0xF6, 0xA5, 0x6A, 0x18, 0xA5, 0x6A, 0x10, 0x03, 0x4C, +0x06, 0xF2, 0x60, 0xA2, 0x04, 0xA0, 0x1E, 0x20, 0x0A, 0xF3, 0xF0, 0x05, 0x70, 0x16, 0x4C, 0x68, +0xF8, 0xA5, 0x6A, 0xC9, 0xFF, 0xD0, 0x03, 0x4C, 0x17, 0xF3, 0xA5, 0x6B, 0x10, 0x03, 0x4C, 0x1F, +0xF3, 0x4C, 0x0F, 0xF3, 0xA5, 0x6A, 0xC9, 0xFF, 0xF0, 0xED, 0x10, 0x12, 0xA5, 0x6C, 0xC9, 0xFF, +0xD0, 0x03, 0x4C, 0x68, 0xF8, 0xA5, 0x6B, 0x45, 0x6D, 0xD0, 0xE6, 0x4C, 0x22, 0xF3, 0x20, 0x07, +0xF7, 0xA0, 0x06, 0x20, 0xF7, 0xF6, 0x20, 0xFE, 0xF1, 0x20, 0xFA, 0xF1, 0x20, 0x54, 0xF2, 0xF0, +0x14, 0x20, 0x7F, 0xF6, 0xE0, 0x00, 0xF0, 0x0D, 0xE0, 0xFE, 0xD0, 0x06, 0x20, 0x2C, 0xF2, 0x4C, +0x56, 0xF3, 0x20, 0x30, 0xF2, 0x4C, 0x56, 0xF3, 0xA9, 0x26, 0x4C, 0x1F, 0xF7, 0xA2, 0x04, 0xA0, +0x1E, 0x20, 0x0A, 0xF3, 0x30, 0xF2, 0x70, 0x02, 0xD0, 0xEE, 0x30, 0x14, 0x70, 0x12, 0xD0, 0x10, +0xA5, 0x6A, 0xC9, 0xFF, 0xF0, 0x10, 0xA5, 0x6B, 0x30, 0x03, 0x4C, 0x1F, 0xF3, 0x4C, 0x1B, 0xF3, +0xA5, 0x6A, 0xC9, 0xFF, 0xD0, 0x03, 0x4C, 0x0F, 0xF3, 0xA5, 0x6C, 0xC9, 0xFF, 0xF0, 0x05, 0x10, +0x1D, 0x4C, 0xA9, 0xF8, 0xA2, 0x02, 0x4C, 0x2B, 0xF3, 0xA5, 0x6B, 0x10, 0xE9, 0xA2, 0x02, 0xA0, +0x1E, 0x20, 0x0A, 0xF3, 0xF0, 0xD7, 0x30, 0x03, 0x4C, 0x13, 0xF3, 0x4C, 0x29, 0xF3, 0xA5, 0x6A, +0x10, 0x17, 0xA5, 0x6B, 0x45, 0x6D, 0xD0, 0xDC, 0xA2, 0x1C, 0x20, 0x20, 0xF4, 0xA2, 0x04, 0xA0, +0x0E, 0x20, 0xBC, 0xF6, 0xA2, 0x0E, 0x4C, 0x2B, 0xF3, 0x20, 0x07, 0xF7, 0xA2, 0x04, 0xA0, 0x12, +0x20, 0x65, 0xF2, 0xA5, 0x6C, 0xD0, 0x05, 0xA0, 0x06, 0x20, 0x42, 0xF1, 0x20, 0xC6, 0xF0, 0xA2, +0x62, 0x20, 0x88, 0xF6, 0xA5, 0x6C, 0xF0, 0x0B, 0xA0, 0x0C, 0x20, 0x42, 0xF1, 0x20, 0x3C, 0xF2, +0x4C, 0x08, 0xF9, 0xA0, 0x0E, 0x20, 0x42, 0xF1, 0xA2, 0x62, 0x20, 0x88, 0xF6, 0xA2, 0x12, 0xA0, +0x62, 0x20, 0xBC, 0xF6, 0x20, 0xFA, 0xF1, 0x20, 0xFE, 0xF1, 0x20, 0x02, 0xF7, 0xC2, 0x30, 0x18, +0x7B, 0x69, 0x82, 0x00, 0x85, 0x7C, 0xE2, 0x30, 0x64, 0x7E, 0x20, 0xDF, 0xEF, 0x8A, 0xC9, 0xFE, +0xD0, 0x06, 0x20, 0x2C, 0xF2, 0x4C, 0x3F, 0xF9, 0xC9, 0x00, 0xF0, 0x03, 0x20, 0x30, 0xF2, 0x4C, +0x56, 0xF3, 0x05, 0x00, 0xFF, 0x3B, 0xCE, 0xF6, 0xAF, 0x46, 0x46, 0xB9, 0xF6, 0x3F, 0xEB, 0xFB, +0x61, 0x4D, 0x21, 0x32, 0xF4, 0x94, 0xF9, 0x3F, 0x93, 0x78, 0x44, 0xD9, 0x03, 0x89, 0x97, 0xDC, +0xFB, 0x3F, 0x05, 0x1D, 0xCA, 0x57, 0x46, 0x39, 0x9E, 0x9F, 0xFF, 0x3F, 0x9A, 0xDC, 0xEC, 0x46, +0x3A, 0xC5, 0x6B, 0xCD, 0x01, 0xC0, 0xE0, 0xFC, 0xE6, 0xBA, 0xE7, 0x97, 0x83, 0xB4, 0x01, 0x40, +0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0x1D, 0x5E, 0x0A, 0xCE, +0xC3, 0x35, 0x18, 0xB8, 0x00, 0xC0, 0x96, 0x1A, 0xF4, 0xDD, 0x0E, 0xDF, 0x3E, 0xFA, 0xFF, 0x3F, +0x03, 0x00, 0x79, 0x9B, 0x20, 0x1B, 0xC8, 0x90, 0x88, 0xFF, 0xEE, 0xBF, 0x2F, 0x27, 0x13, 0xB8, +0xEF, 0x84, 0x5C, 0xDA, 0xF9, 0x3F, 0x45, 0xFD, 0x0F, 0xF8, 0xEA, 0xBA, 0xD3, 0x97, 0x03, 0x40, +0x0C, 0xFF, 0xBE, 0x95, 0xA1, 0x71, 0x86, 0xAB, 0x09, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0xB4, 0x5A, 0x4B, 0x98, 0x02, 0x70, 0x48, 0xD5, 0x06, 0x40, +0x80, 0x07, 0xB7, 0x96, 0x2E, 0x61, 0x75, 0xF7, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xBF, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, +0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x0D, 0x40, 0x84, 0x64, 0xDE, 0xF9, +0x33, 0xF3, 0x04, 0xB5, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x3F, +0x84, 0x64, 0xDE, 0xF9, 0x33, 0xF3, 0x04, 0xB5, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0xFD, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0x3F, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x3F, 0x35, 0xC2, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, +0xFF, 0x3F, 0x35, 0xC2, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0xFE, 0x3F, 0x9B, 0x4A, 0xBB, 0xA2, +0x58, 0x54, 0xF8, 0xAD, 0x00, 0x40, 0xAC, 0x79, 0xCF, 0xD1, 0xF7, 0x17, 0x72, 0xB1, 0xFE, 0x3F, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0x30, 0x5A, 0xA8, 0xA6, 0x44, 0xB8, 0xD8, 0x88, +0x07, 0x40, 0x20, 0x23, 0x79, 0x09, 0x49, 0x8A, 0x15, 0x8A, 0x0E, 0x40, 0x2B, 0xF2, 0x63, 0xFE, +0x26, 0xFE, 0xA9, 0xFA, 0x13, 0x40, 0x03, 0x00, 0xF5, 0xCB, 0xF5, 0x43, 0xAE, 0x86, 0x50, 0xC2, +0xFE, 0xBF, 0xA2, 0x6B, 0xE7, 0xBE, 0x66, 0xEC, 0x76, 0x9E, 0x06, 0x40, 0x01, 0xAA, 0xC4, 0xC4, +0xD6, 0xA1, 0x51, 0xAF, 0x0C, 0xC0, 0xCE, 0xF6, 0x97, 0xA9, 0xC4, 0xFE, 0x1B, 0xA7, 0x11, 0x40, +0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0x85, 0x96, 0xDF, 0xFB, +0x95, 0x6A, 0xD9, 0xA6, 0x07, 0x40, 0x6B, 0x15, 0x5D, 0xE8, 0x65, 0xEA, 0xA7, 0xC7, 0x0E, 0x40, +0xB2, 0x52, 0x17, 0x7B, 0x1C, 0x87, 0x6E, 0xD2, 0x14, 0x40, 0x03, 0x00, 0x58, 0xD7, 0xF6, 0xA6, +0xD7, 0x18, 0x7E, 0xD5, 0xFB, 0xBF, 0x72, 0xD0, 0xB3, 0x32, 0x7E, 0x93, 0x64, 0xE3, 0x03, 0x40, +0x45, 0xC0, 0x6B, 0x58, 0x56, 0x40, 0x2D, 0xA6, 0x0A, 0xC0, 0x7A, 0x8C, 0x0F, 0x52, 0x68, 0xAF, +0x49, 0x8C, 0x10, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xBF, +0x55, 0x09, 0xC0, 0x83, 0x24, 0x03, 0x13, 0xB5, 0x05, 0x40, 0xCF, 0xE0, 0x62, 0x57, 0x42, 0xB2, +0xFF, 0xD1, 0x09, 0xC0, 0xAB, 0x66, 0x76, 0x93, 0x09, 0x93, 0x90, 0xE1, 0x0A, 0x40, 0x03, 0x00, +0x38, 0x28, 0x9B, 0xD7, 0x63, 0x33, 0xFC, 0xB1, 0xE9, 0xBF, 0xD1, 0x4C, 0xC7, 0x3E, 0xD8, 0x71, +0x9D, 0xAA, 0xFD, 0x3F, 0xBB, 0x7D, 0x65, 0xB9, 0x24, 0x8E, 0xCD, 0xE9, 0x03, 0xC0, 0x36, 0x18, +0x4B, 0x9D, 0x70, 0x36, 0x9A, 0xF0, 0x07, 0x40, 0x04, 0x00, 0xAD, 0x5D, 0xFA, 0x2A, 0xAE, 0x1E, +0xD3, 0x98, 0xFF, 0x3F, 0xD9, 0xEF, 0xCD, 0xB3, 0xD8, 0x4C, 0x79, 0x8F, 0x03, 0x40, 0x68, 0xB3, +0xB8, 0x70, 0x85, 0xED, 0x37, 0x8E, 0x05, 0x40, 0xB8, 0xF3, 0x59, 0xAC, 0xA1, 0xBE, 0xA4, 0xCD, +0x05, 0x40, 0x56, 0xC6, 0xF0, 0x4C, 0x55, 0x9C, 0x05, 0xC4, 0x04, 0x40, 0x04, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0x30, 0x0E, 0x92, 0x1F, 0x13, 0x6C, 0x3B, 0xA2, +0x02, 0x40, 0x6F, 0x48, 0x3A, 0xFA, 0x3D, 0x59, 0xC8, 0xC3, 0x03, 0x40, 0x45, 0xD9, 0xF5, 0xDD, +0x38, 0x68, 0xAE, 0x82, 0x03, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x6A, 0xE2, 0x98, 0x81, 0x2C, 0x3A, 0xCD, 0x93, 0xFE, 0x3F, 0x62, 0x64, 0xDB, 0x5F, 0xB1, 0x86, +0x2A, 0xDC, 0xFA, 0x3F, 0x8A, 0xB1, 0x6A, 0xF6, 0xF4, 0xA2, 0x30, 0x89, 0xFD, 0x3F, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x4E, 0x83, 0x0D, 0x40, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, +0x1D, 0x40, 0x82, 0x00, 0x96, 0x00, 0xA0, 0x00, 0x70, 0x00, 0xC3, 0x00, 0xC5, 0x00, 0xC7, 0x00, +0xD1, 0x00, 0xDB, 0x00, 0xE5, 0x00, 0x42, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xCA, 0xF9, 0xEA, 0xF9, +0xF4, 0xF9, 0xFE, 0xF9, 0x08, 0xFA, 0x12, 0xFA, 0x1C, 0xFA, 0x26, 0xFA, 0x30, 0xFA, 0x3A, 0xFA, +0x44, 0xFA, 0x4E, 0xFA, 0x58, 0xFA, 0x62, 0xFA, 0x6C, 0xFA, 0x76, 0xFA, 0x80, 0xFA, 0x8A, 0xFA, +0x94, 0xFA, 0x9E, 0xFA, 0xAC, 0xFA, 0xD6, 0xFA, 0x00, 0xFB, 0x2A, 0xFB, 0x54, 0xFB, 0x7E, 0xFB, +0xA8, 0xFB, 0xDC, 0xFB, 0x10, 0xFC, 0x1A, 0xFC, 0x24, 0xFC, 0x2E, 0xFC, 0x38, 0xFC, 0x64, 0x00, +0x66, 0x00, 0x68, 0x00, 0xB4, 0x00, 0xA8, 0xFA, 0x20, 0xE6, 0xFD, 0xD0, 0x03, 0x4C, 0x56, 0xF3, +0x10, 0x03, 0x4C, 0x31, 0xF3, 0x20, 0x0E, 0xFD, 0xA9, 0x01, 0x24, 0xF4, 0xD0, 0x06, 0x20, 0x2F, +0xFD, 0x4C, 0xC7, 0xFC, 0x20, 0x74, 0xFD, 0xA9, 0x00, 0x85, 0xF5, 0xA5, 0xF4, 0x29, 0x03, 0x38, +0xE9, 0x02, 0x85, 0xF4, 0xA5, 0xF5, 0xE9, 0x00, 0x85, 0xF5, 0x30, 0x03, 0x20, 0x86, 0xF6, 0x20, +0xFA, 0xF1, 0x20, 0x3C, 0xF2, 0x20, 0x7F, 0xF6, 0xE0, 0x01, 0xD0, 0x03, 0x20, 0x30, 0xF2, 0x4C, +0x56, 0xF3, 0xA5, 0x6D, 0x85, 0x6F, 0xA9, 0x21, 0x85, 0x6E, 0x60, 0x20, 0xF2, 0xFC, 0xA0, 0x00, +0x84, 0xF5, 0xC8, 0x84, 0xF4, 0xA5, 0x6C, 0xC9, 0xFF, 0xD0, 0xA5, 0x4C, 0x17, 0xF3, 0xA2, 0x32, +0x20, 0xCC, 0xF0, 0x64, 0xC6, 0x8A, 0x29, 0x7F, 0x85, 0xC5, 0xC0, 0x00, 0xF0, 0x03, 0x20, 0x88, +0xF2, 0x18, 0xA5, 0xF4, 0x65, 0xC5, 0x85, 0xF4, 0xA5, 0xF5, 0x65, 0xC6, 0x85, 0xF5, 0x60, 0xA9, +0x42, 0x20, 0x4B, 0xFD, 0xA2, 0x62, 0x20, 0xBC, 0xF0, 0xA2, 0x0E, 0x4C, 0x2B, 0xF5, 0x20, 0x4B, +0xFD, 0x20, 0xBA, 0xF0, 0xA2, 0x62, 0xA0, 0x12, 0x4C, 0x65, 0xF2, 0x85, 0xC3, 0x20, 0x17, 0xF4, +0xA2, 0x0C, 0x20, 0xC2, 0xF0, 0xA2, 0x0C, 0x20, 0x09, 0xF7, 0xA2, 0x00, 0x20, 0xC8, 0xF0, 0xA2, +0x10, 0x20, 0x88, 0xF1, 0xE6, 0xC3, 0xE6, 0xC3, 0xA2, 0x0E, 0x20, 0x88, 0xF1, 0xA2, 0x10, 0xA0, +0x0E, 0x4C, 0xBC, 0xF6, 0xA9, 0x46, 0x20, 0x3E, 0xFD, 0x20, 0xBA, 0xF0, 0xA2, 0x0C, 0xA0, 0x2C, +0x20, 0x0A, 0xF3, 0x70, 0x14, 0x20, 0xC0, 0xF0, 0xA2, 0x0C, 0xA0, 0x0E, 0x20, 0x2D, 0xF5, 0xA2, +0x0E, 0x20, 0x63, 0xF2, 0xA2, 0x1C, 0x4C, 0xD4, 0xF0, 0x20, 0x8C, 0xF6, 0xA2, 0x28, 0x20, 0x2B, +0xF5, 0x20, 0x17, 0xF4, 0x20, 0xC0, 0xF0, 0xA2, 0x0C, 0x20, 0xB4, 0xF0, 0xA2, 0x0E, 0x20, 0x2B, +0xF5, 0xA2, 0x0C, 0x20, 0xD4, 0xF0, 0x20, 0x86, 0xF6, 0xA2, 0x30, 0x4C, 0xD4, 0xF0, 0x20, 0xE6, +0xFD, 0x10, 0x03, 0x4C, 0x31, 0xF3, 0xD0, 0x03, 0x4C, 0x56, 0xF3, 0x20, 0x0E, 0xFD, 0x20, 0xF2, +0xFD, 0x66, 0xF4, 0x90, 0x0E, 0x20, 0x86, 0xF6, 0x20, 0xA3, 0xFE, 0x20, 0x4C, 0xF2, 0xF0, 0x03, +0x20, 0x86, 0xF6, 0x4C, 0xDF, 0xFC, 0x20, 0xF2, 0xFC, 0x64, 0xF5, 0x64, 0xF4, 0xA5, 0x6C, 0xC9, +0xFF, 0x60, 0xA9, 0x4A, 0x20, 0x3E, 0xFD, 0xA2, 0x12, 0x20, 0xBC, 0xF0, 0xA2, 0x0C, 0xA0, 0x2C, +0x20, 0x0A, 0xF3, 0x70, 0x13, 0xA2, 0x22, 0xA0, 0x12, 0x20, 0xBC, 0xF6, 0xA2, 0x12, 0xA0, 0x0E, +0x20, 0xD6, 0xF0, 0xA2, 0x0E, 0x4C, 0xD4, 0xF0, 0x20, 0x25, 0xF4, 0xA2, 0x2E, 0xA0, 0x10, 0x20, +0x2D, 0xF5, 0xA2, 0x22, 0xA0, 0x10, 0x20, 0xBC, 0xF6, 0xA2, 0x0C, 0xA0, 0x10, 0x20, 0xB6, 0xF0, +0xA2, 0x0E, 0xA0, 0x10, 0x20, 0xD6, 0xF0, 0xA2, 0x2C, 0x20, 0xC2, 0xF0, 0xA2, 0x0C, 0xA0, 0x10, +0x20, 0xD6, 0xF0, 0xA2, 0x10, 0x4C, 0xD4, 0xF0, 0xA5, 0x6C, 0xC9, 0xFF, 0x10, 0x0F, 0xA2, 0x32, +0x20, 0x63, 0xF2, 0xA5, 0x6D, 0x10, 0x03, 0x20, 0x86, 0xF6, 0x4C, 0x5F, 0xFE, 0xD0, 0x03, 0x4C, +0x56, 0xF3, 0x20, 0x8C, 0xF6, 0x20, 0x72, 0xFE, 0xA5, 0x6D, 0x10, 0x03, 0x20, 0x86, 0xF6, 0x4C, +0xDF, 0xFC, 0xA9, 0x00, 0x85, 0xF4, 0xA2, 0x00, 0xA0, 0x1C, 0x20, 0x0A, 0xF3, 0x30, 0x09, 0xF0, +0x07, 0xA9, 0x01, 0x85, 0xF4, 0x20, 0xA3, 0xFE, 0xA2, 0x00, 0xA0, 0x02, 0x20, 0x65, 0xF2, 0xA2, +0x00, 0xA0, 0x56, 0x20, 0x0A, 0xF3, 0x70, 0x17, 0xA9, 0x4E, 0x20, 0x4B, 0xFD, 0x20, 0xB2, 0xF0, +0x4C, 0xF7, 0xFE, 0x20, 0x17, 0xF4, 0xA2, 0x1C, 0x20, 0x63, 0xF2, 0x20, 0xB8, 0xF6, 0x60, 0x20, +0x17, 0xF4, 0xA2, 0x52, 0x20, 0xC2, 0xF0, 0xA2, 0x1C, 0x20, 0x27, 0xF4, 0xA2, 0x0C, 0xA0, 0x10, +0x20, 0xBC, 0xF6, 0xA2, 0x1C, 0xA0, 0x10, 0x20, 0xD6, 0xF0, 0xA2, 0x1C, 0xA0, 0x0C, 0x20, 0xD6, +0xF0, 0xA2, 0x52, 0x20, 0x2B, 0xF5, 0xA2, 0x00, 0x20, 0x46, 0xFD, 0x20, 0xB8, 0xF6, 0xA2, 0x10, +0xA0, 0x12, 0x20, 0xBC, 0xF6, 0xA9, 0x4E, 0x20, 0x4B, 0xFD, 0x20, 0xB2, 0xF0, 0xA2, 0x54, 0x20, +0xD4, 0xF0, 0xA2, 0x12, 0x20, 0xD4, 0xF0, 0xA2, 0x02, 0x20, 0x2B, 0xF5, 0xA5, 0xF4, 0xD0, 0x03, +0x4C, 0x86, 0xF6, 0xA2, 0x32, 0x4C, 0xD4, 0xF0, 0xA2, 0x58, 0x20, 0xB4, 0xF0, 0xA2, 0x5A, 0x20, +0xCC, 0xF0, 0x20, 0x7F, 0xF6, 0x10, 0x05, 0xA2, 0x5A, 0x20, 0xD4, 0xF0, 0x4C, 0x56, 0xF3, 0xA2, +0x00, 0x00, 0x22, 0x68, 0x00, 0xE1, 0x80, 0x03, 0xA2, 0x00, 0x00, 0x2B, 0x5C, 0x0B, 0xBF, 0xFF, +0xA2, 0x00, 0x00, 0x22, 0x68, 0x00, 0xE1, 0x80, 0xF3, 0xA2, 0x00, 0x00, 0x80, 0xEE, 0x0B, 0xA2, +0x00, 0x00, 0x2B, 0xA0, 0x00, 0x00, 0x4C, 0x33, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x0A, +0x00, 0x4C, 0x33, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x0C, 0x00, 0x4C, 0x33, 0xFF, 0x0B, +0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x02, 0x00, 0x4C, 0x33, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, +0x04, 0x00, 0x4C, 0x33, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x06, 0x00, 0x4C, 0x33, 0xFF, +0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x08, 0x00, 0x4C, 0x33, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, +0xA0, 0x00, 0x00, 0x4C, 0x2C, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x0A, 0x00, 0x4C, 0x2C, +0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x0C, 0x00, 0x4C, 0x2C, 0xFF, 0x0B, 0xA2, 0x00, 0x00, +0x2B, 0xA0, 0x0E, 0x00, 0x4C, 0x2C, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x02, 0x00, 0x4C, +0x2C, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x04, 0x00, 0x4C, 0x2C, 0xFF, 0x0B, 0xA2, 0x00, +0x00, 0x2B, 0xA0, 0x06, 0x00, 0x4C, 0x2C, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x08, 0x00, +0x4C, 0x2C, 0xFF, 0xA2, 0xFF, 0xFF, 0x4C, 0x90, 0xFF, 0x0B, 0xA2, 0x00, 0x00, 0x2B, 0xA0, 0x10, +0x00, 0x4C, 0x2C, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x30, 0x00, 0x00, 0x00, 0xED, 0x01, 0xFF, 0x00, 0x82, 0x04, 0xFF, 0x00, 0xCE, 0x04, 0xFF, 0x00, +0xE4, 0x04, 0xFF, 0x00, 0xEC, 0x04, 0xFF, 0x00, 0xFE, 0x04, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, +0x06, 0x01, 0xFF, 0x00, 0x06, 0x05, 0xFF, 0x00, 0x66, 0x05, 0xFF, 0x00, 0xC4, 0x05, 0xFF, 0x00, +0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, +0xFA, 0x05, 0xFF, 0x00, 0x0B, 0x06, 0xFF, 0x00, 0x37, 0x06, 0xFF, 0x00, 0x45, 0x06, 0xFF, 0x00, +0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, +0x7F, 0x06, 0xFF, 0x00, 0x97, 0x06, 0xFF, 0x00, 0xB1, 0x07, 0xFF, 0x00, 0xE3, 0x07, 0xFF, 0x00, +0x0F, 0x08, 0xFF, 0x00, 0x3A, 0x08, 0xFF, 0x00, 0x4B, 0x08, 0xFF, 0x00, 0x56, 0x08, 0xFF, 0x00, +0x6C, 0x08, 0xFF, 0x00, 0x81, 0x08, 0xFF, 0x00, 0xCF, 0x08, 0xFF, 0x00, 0xE4, 0x08, 0xFF, 0x00, +0x04, 0x09, 0xFF, 0x00, 0x23, 0x09, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, +0x4D, 0x09, 0xFF, 0x00, 0x8A, 0x09, 0xFF, 0x00, 0xC7, 0x09, 0xFF, 0x00, 0x13, 0x0A, 0xFF, 0x00, +0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, 0x06, 0x01, 0xFF, 0x00, +0x10, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, +0xE4, 0x04, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFE, 0x04, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, +0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x78, 0x13, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, +0xA3, 0x11, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, +0x22, 0x89, 0x01, 0xFF, 0x4C, 0xC4, 0x01, 0x22, 0x88, 0x16, 0xE1, 0x5C, 0x8C, 0x16, 0xE1, 0x00, +0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, +0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x02, +0x04, 0x02, 0x06, 0x04, 0x04, 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x81, 0x04, +0xFF, 0x5C, 0x82, 0x04, 0xFF, 0x5C, 0x99, 0x01, 0xFF, 0x5C, 0xC4, 0x01, 0xFF, 0x5C, 0x38, 0x0A, +0xFF, 0x5C, 0x27, 0x0B, 0xFF, 0x5C, 0x8C, 0x0C, 0xFF, 0x5C, 0x16, 0x0D, 0xFF, 0x5C, 0x27, 0x0E, +0xFF, 0x5C, 0xEA, 0x0E, 0xFF, 0x5C, 0xD2, 0x0F, 0xFF, 0x5C, 0xFC, 0x0F, 0xFF, 0x5C, 0x74, 0x10, +0xFF, 0x5C, 0x72, 0x10, 0xFF, 0x5C, 0x32, 0x03, 0xFF, 0x8A, 0xEB, 0xE2, 0x30, 0x29, 0xFF, 0xAA, +0xA9, 0xE1, 0x48, 0xBF, 0x3D, 0x01, 0xFF, 0x80, 0x0E, 0x8A, 0xEB, 0xE2, 0x30, 0x29, 0xFF, 0xAA, +0xA9, 0xE1, 0x48, 0xBF, 0x0E, 0x01, 0xFF, 0xC2, 0x30, 0xFA, 0x7A, 0x29, 0xFF, 0x00, 0x48, 0x3B, +0x38, 0xE9, 0x24, 0x00, 0x1B, 0x8B, 0x0B, 0x5B, 0x64, 0x23, 0x64, 0x01, 0x5A, 0xDA, 0x22, 0x64, +0x00, 0xE1, 0xAB, 0x6B, 0x22, 0x68, 0x00, 0xE1, 0xA6, 0x25, 0xA5, 0x2B, 0x95, 0x2B, 0xA5, 0x29, +0x95, 0x29, 0xA5, 0x27, 0x95, 0x27, 0x3B, 0x18, 0x65, 0x25, 0x69, 0x29, 0x00, 0xAA, 0x2B, 0xAB, +0x68, 0xC9, 0x01, 0x00, 0x9A, 0xB0, 0x01, 0x6B, 0x6B, 0xA9, 0x00, 0x00, 0x18, 0x6B, 0xAF, 0xFE, +0x15, 0xE1, 0x10, 0x0E, 0x22, 0x88, 0x16, 0xE1, 0x22, 0xB8, 0x16, 0xE1, 0xB0, 0x08, 0x5C, 0x8C, +0x16, 0xE1, 0x22, 0x99, 0x01, 0xFF, 0xA9, 0x00, 0x00, 0xA2, 0x00, 0x05, 0x9D, 0xFE, 0x15, 0xCA, +0xCA, 0x10, 0xF9, 0xA9, 0xE8, 0x1A, 0xAA, 0x9F, 0xFC, 0xFF, 0xE0, 0xA9, 0xE1, 0x00, 0x9F, 0xFE, +0xFF, 0xE0, 0x8A, 0x38, 0xE9, 0x14, 0x00, 0xAA, 0x9D, 0x20, 0x00, 0xA9, 0xE1, 0x00, 0x9D, 0x22, +0x00, 0x8A, 0xC9, 0x00, 0x17, 0xD0, 0xE0, 0xA9, 0x00, 0x00, 0x8D, 0x74, 0x17, 0x8D, 0x76, 0x17, +0x8D, 0x84, 0x17, 0x8D, 0x86, 0x17, 0xA2, 0x1E, 0x00, 0xBF, 0xDC, 0x02, 0xFF, 0x9D, 0x00, 0x16, +0xCA, 0xCA, 0x10, 0xF5, 0xA2, 0x00, 0x00, 0x9B, 0xBF, 0xAC, 0x02, 0xFF, 0x99, 0x00, 0x17, 0xBF, +0xAE, 0x02, 0xFF, 0x99, 0x02, 0x17, 0xBF, 0xB0, 0x02, 0xFF, 0x99, 0x08, 0x17, 0xBF, 0xB2, 0x02, +0xFF, 0x99, 0x0A, 0x17, 0xA9, 0x00, 0xC0, 0x99, 0x04, 0x17, 0x8A, 0x18, 0x69, 0x08, 0x00, 0xAA, +0x98, 0x69, 0x14, 0x00, 0xA8, 0xC9, 0x78, 0x00, 0x90, 0xCE, 0x20, 0xFC, 0x02, 0x8D, 0x3E, 0x17, +0x8A, 0x8D, 0x46, 0x17, 0xA2, 0x3A, 0x00, 0xBF, 0x4D, 0x01, 0xFF, 0x9D, 0x80, 0x16, 0xCA, 0xCA, +0x10, 0xF5, 0xA9, 0xFF, 0xFF, 0x8D, 0xFE, 0x15, 0x5C, 0x8C, 0x16, 0xE1, 0x00, 0x00, 0x00, 0x00, +0x00, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0xDE, 0x00, 0x00, 0xC0, 0xE0, 0x00, +0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0xE1, 0x00, 0x00, 0x40, 0x1E, 0xFF, 0x00, 0x17, 0xE1, 0x00, +0x00, 0x00, 0x00, 0x00, 0x78, 0x17, 0xE1, 0x00, 0x14, 0x17, 0xE1, 0x00, 0x28, 0x17, 0xE1, 0x00, +0x3C, 0x17, 0xE1, 0x00, 0x50, 0x17, 0xE1, 0x00, 0x64, 0x17, 0xE1, 0x00, 0xA9, 0x00, 0x00, 0x85, +0x03, 0xA9, 0x7F, 0x00, 0x85, 0x05, 0x49, 0xFF, 0xFF, 0x87, 0x03, 0xC6, 0x05, 0x1A, 0xC9, 0xFE, +0xFF, 0xD0, 0xF6, 0xA9, 0x7F, 0x00, 0x85, 0x05, 0x49, 0xFF, 0xFF, 0xA2, 0x60, 0x00, 0xC7, 0x03, +0xF0, 0x09, 0xE8, 0xC6, 0x05, 0x1A, 0xC9, 0xFE, 0xFF, 0xD0, 0xF3, 0xA5, 0x05, 0x1A, 0x8D, 0x24, +0x16, 0x60, 0x20, 0x9E, 0x03, 0xD0, 0x65, 0x20, 0xDB, 0x03, 0xA2, 0x04, 0x00, 0x20, 0x3F, 0x04, +0xA2, 0x08, 0x00, 0x20, 0x3F, 0x04, 0x20, 0xF5, 0x0A, 0x20, 0xD6, 0x0D, 0xF0, 0x4C, 0xA0, 0x06, +0x00, 0xB7, 0x0F, 0x89, 0x00, 0xFF, 0xD0, 0x0E, 0xC9, 0xFF, 0x00, 0xD0, 0xEC, 0x88, 0x88, 0xB7, +0x0F, 0x89, 0x00, 0x10, 0xD0, 0xE3, 0xA5, 0x0F, 0x85, 0x17, 0xA5, 0x11, 0x85, 0x19, 0xA5, 0x15, +0x48, 0xA5, 0x13, 0x48, 0x20, 0xA8, 0x0C, 0xA0, 0x06, 0x00, 0xB7, 0x17, 0x29, 0x00, 0xFF, 0xF0, +0x0E, 0xA5, 0x19, 0xC9, 0xE1, 0x00, 0xD0, 0x0A, 0xA5, 0x17, 0xC9, 0x00, 0x1B, 0xB0, 0x03, 0x20, +0x57, 0x0D, 0x68, 0x85, 0x13, 0x68, 0x85, 0x15, 0x80, 0xAF, 0x18, 0x6B, 0x38, 0x6B, 0xA2, 0x00, +0x00, 0x20, 0xBF, 0x03, 0xD0, 0x34, 0xA5, 0x1F, 0xC9, 0x00, 0xC0, 0xD0, 0x2D, 0xA5, 0x21, 0xC9, +0xE1, 0x00, 0xD0, 0x26, 0xA2, 0x04, 0x00, 0x20, 0xBF, 0x03, 0xD0, 0x1E, 0xA2, 0x08, 0x00, 0x20, +0xF8, 0x0A, 0xF0, 0x16, 0x20, 0xD6, 0x0D, 0xF0, 0x11, 0xA0, 0x0C, 0x00, 0xB7, 0x13, 0xC5, 0x0F, +0xD0, 0x08, 0xC8, 0xC8, 0xB7, 0x13, 0xC5, 0x11, 0xF0, 0xEA, 0x60, 0xAF, 0x00, 0x16, 0xE1, 0x85, +0x17, 0xAF, 0x02, 0x16, 0xE1, 0x85, 0x19, 0xA0, 0x10, 0x00, 0xB7, 0x17, 0xAA, 0xC8, 0xC8, 0xB7, +0x17, 0x85, 0x19, 0x86, 0x17, 0x05, 0x19, 0xF0, 0x2E, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x89, 0x00, +0x10, 0xF0, 0xE4, 0xA0, 0x08, 0x00, 0xB7, 0x17, 0x38, 0xE9, 0x0E, 0x00, 0xAA, 0xA8, 0xB7, 0x17, +0x29, 0x00, 0xFF, 0xF0, 0x13, 0x98, 0x38, 0xE9, 0x14, 0x00, 0xC9, 0x14, 0x00, 0xB0, 0xEE, 0xA8, +0xA9, 0xFF, 0xFF, 0x97, 0x17, 0x80, 0xC0, 0x60, 0x8A, 0xA8, 0xB7, 0x17, 0x29, 0x00, 0xFF, 0xF0, +0x05, 0xA9, 0xFF, 0x00, 0x97, 0x17, 0x98, 0x38, 0xE9, 0x14, 0x00, 0x10, 0xEC, 0x80, 0xA8, 0xBF, +0x02, 0x16, 0xE1, 0x48, 0xBF, 0x00, 0x16, 0xE1, 0x48, 0x68, 0x85, 0x17, 0x68, 0x85, 0x19, 0x05, +0x17, 0xF0, 0x2D, 0xA0, 0x12, 0x00, 0xB7, 0x17, 0x48, 0x88, 0x88, 0xB7, 0x17, 0x48, 0xA0, 0x06, +0x00, 0xB7, 0x17, 0xC9, 0xFF, 0x00, 0x90, 0xE1, 0x08, 0x20, 0xA8, 0x0C, 0x28, 0xF0, 0x0C, 0xA5, +0x18, 0xC9, 0x17, 0xE1, 0x90, 0xD3, 0xC9, 0x1B, 0xE1, 0xB0, 0xCE, 0x20, 0x57, 0x0D, 0x80, 0xC9, +0x60, 0x6B, 0x6B, 0x22, 0x88, 0x16, 0xE1, 0xA5, 0x2A, 0x18, 0x69, 0x01, 0x00, 0x85, 0x03, 0xA5, +0x2C, 0x69, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x85, 0x05, 0x20, 0xF5, 0x0A, 0x20, 0xD6, 0x0D, 0xF0, +0x19, 0xA5, 0x03, 0xC5, 0x1B, 0xA5, 0x05, 0xE5, 0x1D, 0x90, 0x0F, 0xA5, 0x03, 0xC5, 0x1F, 0xA5, +0x05, 0xE5, 0x21, 0xB0, 0xE7, 0xA9, 0x00, 0x00, 0x80, 0x05, 0xA0, 0x06, 0x00, 0xB7, 0x0F, 0x85, +0x2D, 0x89, 0x00, 0xF0, 0xD0, 0x05, 0xA9, 0x07, 0x02, 0x85, 0x01, 0x5C, 0x8C, 0x16, 0xE1, 0x22, +0x88, 0x16, 0xE1, 0xAF, 0x81, 0x01, 0xFF, 0x8D, 0xB4, 0x16, 0xAF, 0x83, 0x01, 0xFF, 0x8D, 0xB6, +0x16, 0x5C, 0x8C, 0x16, 0xE1, 0xA9, 0x00, 0x02, 0x83, 0x07, 0x4C, 0xE9, 0x01, 0x22, 0x88, 0x16, +0xE1, 0x20, 0x9E, 0x03, 0xF0, 0x05, 0xA9, 0x01, 0x02, 0x85, 0x01, 0x5C, 0x8C, 0x16, 0xE1, 0xA9, +0xFF, 0xFF, 0x83, 0x07, 0x4C, 0xE9, 0x01, 0x22, 0x88, 0x16, 0xE1, 0xA9, 0xFF, 0xFF, 0x85, 0x09, +0x22, 0x9C, 0x16, 0xE1, 0x90, 0x25, 0xA2, 0x0A, 0x00, 0xB5, 0x2D, 0x95, 0x03, 0xCA, 0xCA, 0x10, +0xF8, 0xA5, 0x09, 0xF0, 0x11, 0xA5, 0x0B, 0x05, 0x0D, 0xF0, 0x28, 0x22, 0x90, 0x16, 0xE1, 0x90, +0x0A, 0x20, 0x50, 0x0C, 0x80, 0x11, 0xA9, 0x07, 0x02, 0x80, 0x03, 0xA9, 0x01, 0x02, 0x85, 0x01, +0x20, 0x57, 0x0D, 0x64, 0x17, 0x64, 0x19, 0xA5, 0x17, 0x85, 0x39, 0xA5, 0x19, 0x85, 0x3B, 0x5C, +0x8C, 0x16, 0xE1, 0xA5, 0x07, 0x89, 0x03, 0xC0, 0xF0, 0x05, 0xA9, 0x04, 0x02, 0x80, 0xDF, 0x20, +0x72, 0x0C, 0x20, 0xCE, 0x0D, 0x80, 0xE0, 0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0xA7, 0x17, +0xA0, 0x02, 0x00, 0x17, 0x17, 0xF0, 0x09, 0xA9, 0x03, 0x02, 0x85, 0x01, 0x5C, 0x8C, 0x16, 0xE1, +0x20, 0xA8, 0x0C, 0xA2, 0x0A, 0x00, 0xB5, 0x31, 0x95, 0x03, 0xCA, 0xCA, 0x10, 0xF8, 0xA5, 0x09, +0xF0, 0x11, 0xA5, 0x0B, 0x05, 0x0D, 0xF0, 0x1C, 0x22, 0x90, 0x16, 0xE1, 0x90, 0x0A, 0x20, 0x50, +0x0C, 0x80, 0x0D, 0xA9, 0x07, 0x02, 0x80, 0x03, 0xA9, 0x01, 0x02, 0x85, 0x01, 0x20, 0xCE, 0x0D, +0x5C, 0x8C, 0x16, 0xE1, 0xA5, 0x07, 0x89, 0x03, 0xC0, 0xF0, 0x05, 0xA9, 0x04, 0x02, 0x80, 0xEB, +0x20, 0x72, 0x0C, 0x80, 0xE8, 0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0x20, 0x7F, 0x0C, 0xA5, +0x03, 0x05, 0x05, 0xF0, 0x05, 0xA9, 0x03, 0x02, 0x80, 0x1B, 0xA5, 0x07, 0x89, 0x03, 0x00, 0xF0, +0x05, 0xA9, 0x08, 0x02, 0x80, 0x0F, 0xA5, 0x0B, 0x05, 0x0D, 0xF0, 0x0B, 0x22, 0x98, 0x16, 0xE1, +0x90, 0x05, 0xA9, 0x01, 0x02, 0x85, 0x01, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x20, +0x9A, 0x0E, 0x20, 0xA8, 0x0C, 0x20, 0x57, 0x0D, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, +0x20, 0xA2, 0x08, 0xB0, 0x0D, 0x20, 0x26, 0x06, 0xAD, 0x06, 0x16, 0xAA, 0xAD, 0x04, 0x16, 0x20, +0x26, 0x06, 0x5C, 0x8C, 0x16, 0xE1, 0x20, 0x2E, 0x0C, 0x90, 0x0C, 0x48, 0xDA, 0x20, 0xA8, 0x0C, +0x20, 0x57, 0x0D, 0xFA, 0x68, 0x80, 0xEF, 0x60, 0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0x20, +0x61, 0x06, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x20, 0xA2, 0x08, 0xB0, 0x0E, 0x20, +0x2E, 0x0C, 0x90, 0x09, 0x48, 0xDA, 0x20, 0x61, 0x06, 0xFA, 0x68, 0x80, 0xF2, 0x5C, 0x8C, 0x16, +0xE1, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x30, 0x0D, 0x89, 0x00, 0x03, 0xF0, 0x0D, 0x20, 0xA8, 0x0C, +0x20, 0xCE, 0x0D, 0x80, 0x0A, 0xA9, 0x04, 0x02, 0x80, 0x03, 0xA9, 0x05, 0x02, 0x85, 0x01, 0x60, +0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0xA0, 0x08, 0x00, 0xB7, 0x17, 0x85, 0x31, 0xC8, 0xC8, +0xB7, 0x17, 0x85, 0x33, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0x20, +0x7F, 0x0C, 0xA5, 0x03, 0x05, 0x05, 0xD0, 0x06, 0xA5, 0x0B, 0x05, 0x0D, 0xD0, 0x42, 0xA6, 0x0D, +0xA5, 0x33, 0x86, 0x33, 0x85, 0x0D, 0xA6, 0x0B, 0xA5, 0x31, 0x86, 0x31, 0x85, 0x0B, 0x38, 0xE5, +0x31, 0xAA, 0xA5, 0x0D, 0xE5, 0x33, 0xD0, 0x03, 0x8A, 0xF0, 0x22, 0xB0, 0x35, 0xA5, 0x0B, 0x05, +0x0D, 0xD0, 0x0D, 0xA5, 0x07, 0x89, 0x03, 0xC0, 0xD0, 0x1B, 0x20, 0xA8, 0x0C, 0x20, 0xCE, 0x0D, +0xA0, 0x08, 0x00, 0xA5, 0x0B, 0x97, 0x17, 0xC8, 0xC8, 0xA5, 0x0D, 0x97, 0x17, 0x4C, 0xAE, 0x07, +0xA9, 0x02, 0x02, 0x80, 0x08, 0xA9, 0x04, 0x02, 0x80, 0x03, 0xA9, 0x01, 0x02, 0x85, 0x01, 0x4C, +0xAE, 0x07, 0xA5, 0x03, 0x85, 0x1B, 0x85, 0x2D, 0xA5, 0x05, 0x85, 0x1D, 0x85, 0x2F, 0x05, 0x03, +0xF0, 0x4A, 0xA0, 0x00, 0x00, 0xB7, 0x13, 0x85, 0x1F, 0xC8, 0xC8, 0xB7, 0x13, 0x85, 0x21, 0xA5, +0x07, 0x48, 0x09, 0x00, 0x40, 0x85, 0x07, 0x22, 0x94, 0x16, 0xE1, 0x68, 0x85, 0x07, 0x90, 0x26, +0xA0, 0x08, 0x00, 0xA5, 0x0B, 0x97, 0x17, 0xC8, 0xC8, 0xA5, 0x0D, 0x97, 0x17, 0xA0, 0x00, 0x00, +0xA5, 0x1B, 0x97, 0x17, 0xC8, 0xC8, 0xA5, 0x1D, 0x97, 0x17, 0xC5, 0x05, 0xD0, 0x44, 0xA5, 0x1B, +0xC5, 0x03, 0xF0, 0x99, 0x80, 0x3C, 0x24, 0x07, 0x30, 0x9B, 0x70, 0x99, 0xA0, 0x04, 0x00, 0xA5, +0x07, 0x29, 0xFF, 0xFC, 0x97, 0x17, 0x22, 0x90, 0x16, 0xE1, 0xA0, 0x04, 0x00, 0xA5, 0x07, 0x97, +0x17, 0x90, 0x87, 0xA5, 0x11, 0x48, 0xA5, 0x0F, 0x48, 0x20, 0xA8, 0x0C, 0x68, 0x85, 0x0F, 0x68, +0x85, 0x11, 0xA0, 0x10, 0x00, 0xB7, 0x0F, 0x85, 0x13, 0xC8, 0xC8, 0xB7, 0x0F, 0x85, 0x15, 0x20, +0x50, 0x0C, 0xA5, 0x1B, 0x85, 0x07, 0xA5, 0x1D, 0x85, 0x09, 0xA5, 0x2D, 0x85, 0x03, 0xA5, 0x2F, +0x85, 0x05, 0xA5, 0x31, 0x85, 0x0B, 0xA5, 0x33, 0x85, 0x0D, 0x22, 0xA4, 0x16, 0xE1, 0x5C, 0x8C, +0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x64, 0x31, 0x64, 0x33, 0x20, 0xF5, 0x0A, 0x20, 0xD6, 0x0D, +0xF0, 0x16, 0xA5, 0x2D, 0xC5, 0x1B, 0xA5, 0x2F, 0xE5, 0x1D, 0x90, 0x0C, 0xA5, 0x2D, 0xC5, 0x1F, +0xA5, 0x2F, 0xE5, 0x21, 0x90, 0x0A, 0x80, 0xE5, 0xA5, 0x0F, 0x85, 0x31, 0xA5, 0x11, 0x85, 0x33, +0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x64, 0x2D, 0x64, 0x2F, 0x20, 0xF5, 0x0A, 0x20, +0xD6, 0x0D, 0xF0, 0x18, 0x38, 0xA5, 0x1F, 0xE5, 0x1B, 0xAA, 0xA5, 0x21, 0xE5, 0x1D, 0xA8, 0x18, +0x8A, 0x65, 0x2D, 0x85, 0x2D, 0x98, 0x65, 0x2F, 0x85, 0x2F, 0x80, 0xE3, 0x5C, 0x8C, 0x16, 0xE1, +0x22, 0x88, 0x16, 0xE1, 0x64, 0x2D, 0x64, 0x2F, 0x20, 0xF5, 0x0A, 0x20, 0xD6, 0x0D, 0xF0, 0x17, +0x38, 0xA5, 0x1F, 0xE5, 0x1B, 0xAA, 0xA5, 0x21, 0xE5, 0x1D, 0xA8, 0xE4, 0x2D, 0xE5, 0x2F, 0x90, +0xEA, 0x86, 0x2D, 0x84, 0x2F, 0x80, 0xE4, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x64, +0x2D, 0xAD, 0x24, 0x16, 0x1A, 0x1A, 0x85, 0x2F, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, +0x20, 0x9A, 0x0E, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0xAD, 0xCB, 0x00, 0x29, 0xFF, +0x00, 0xD0, 0x06, 0x64, 0x07, 0x22, 0xAC, 0x16, 0xE1, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, +0xE1, 0x20, 0x9A, 0x0E, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x09, 0x00, 0x80, 0x97, 0x17, 0x5C, 0x8C, +0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x20, 0xA2, 0x08, 0xB0, 0x13, 0x20, 0x2E, 0x0C, 0x90, 0x0E, +0x48, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x09, 0x00, 0x80, 0x97, 0x17, 0x68, 0x80, 0xED, 0x5C, 0x8C, +0x16, 0xE1, 0xA5, 0x2D, 0x89, 0x00, 0xF0, 0xF0, 0x20, 0x85, 0x09, 0x09, 0x00, 0xF0, 0x89, 0x00, +0x0F, 0xF0, 0x03, 0x09, 0x00, 0x0F, 0x89, 0xFF, 0x00, 0xF0, 0x03, 0x09, 0xFF, 0x00, 0x85, 0x2D, +0xAD, 0x02, 0x16, 0xAA, 0xAD, 0x00, 0x16, 0x18, 0x60, 0xA9, 0x07, 0x02, 0x85, 0x01, 0x38, 0x60, +0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x29, 0xFF, 0x7F, 0x97, +0x17, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x20, 0xA2, 0x08, 0xB0, 0x13, 0x20, 0x2E, +0x0C, 0x90, 0x0E, 0x48, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x29, 0xFF, 0x7F, 0x97, 0x17, 0x68, 0x80, +0xED, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0x20, 0x9A, 0x0E, 0xA5, 0x31, 0x29, 0x03, +0x00, 0xEB, 0x85, 0x31, 0xA0, 0x04, 0x00, 0xB7, 0x17, 0x29, 0xFF, 0xFC, 0x05, 0x31, 0x97, 0x17, +0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, 0x16, 0xE1, 0xA5, 0x2F, 0x29, 0x03, 0x00, 0xEB, 0x85, 0x2F, +0x20, 0xA2, 0x08, 0xB0, 0x15, 0x20, 0x2E, 0x0C, 0x90, 0x10, 0x48, 0xA0, 0x04, 0x00, 0xB7, 0x17, +0x29, 0xFF, 0xFC, 0x05, 0x2F, 0x97, 0x17, 0x68, 0x80, 0xEB, 0x5C, 0x8C, 0x16, 0xE1, 0x22, 0x88, +0x16, 0xE1, 0xA5, 0x31, 0x85, 0x17, 0xA5, 0x33, 0x85, 0x19, 0x20, 0xA2, 0x0E, 0xA5, 0x2D, 0x85, +0x0B, 0xA5, 0x2F, 0x85, 0x0D, 0xA7, 0x31, 0x85, 0x07, 0xA0, 0x02, 0x00, 0xB7, 0x31, 0x85, 0x09, +0x05, 0x07, 0xF0, 0x10, 0xA5, 0x35, 0x85, 0x03, 0xA5, 0x37, 0x85, 0x05, 0x22, 0xA4, 0x16, 0xE1, +0x5C, 0x8C, 0x16, 0xE1, 0xA9, 0x02, 0x02, 0x85, 0x01, 0x80, 0xF5, 0x22, 0x88, 0x16, 0xE1, 0xA5, +0x35, 0x85, 0x17, 0xA5, 0x37, 0x85, 0x19, 0x20, 0xA2, 0x0E, 0xA5, 0x2D, 0x85, 0x0B, 0xA5, 0x2F, +0x85, 0x0D, 0xA5, 0x31, 0x85, 0x07, 0xA5, 0x33, 0x85, 0x09, 0xA7, 0x35, 0x85, 0x03, 0xA0, 0x02, +0x00, 0xB7, 0x35, 0x85, 0x05, 0x05, 0x03, 0xF0, 0x08, 0x22, 0xA4, 0x16, 0xE1, 0x5C, 0x8C, 0x16, +0xE1, 0xA9, 0x02, 0x02, 0x85, 0x01, 0x80, 0xF5, 0x22, 0x88, 0x16, 0xE1, 0xA5, 0x31, 0x85, 0x17, +0xA5, 0x33, 0x85, 0x19, 0x20, 0xA2, 0x0E, 0xA5, 0x35, 0x85, 0x17, 0xA5, 0x37, 0x85, 0x19, 0x20, +0xA2, 0x0E, 0xA5, 0x2D, 0x85, 0x0B, 0xA5, 0x2F, 0x85, 0x0D, 0xA7, 0x31, 0x85, 0x07, 0xA0, 0x02, +0x00, 0xB7, 0x31, 0x85, 0x09, 0x05, 0x07, 0xF0, 0x14, 0xA7, 0x35, 0x85, 0x03, 0xB7, 0x35, 0x85, +0x05, 0x05, 0x03, 0xF0, 0x08, 0x22, 0xA4, 0x16, 0xE1, 0x5C, 0x8C, 0x16, 0xE1, 0xA9, 0x02, 0x02, +0x85, 0x01, 0x80, 0xF5, 0x22, 0x88, 0x16, 0xE1, 0xA5, 0x2D, 0x85, 0x0B, 0xA5, 0x2F, 0x85, 0x0D, +0xA5, 0x31, 0x85, 0x07, 0xA5, 0x33, 0x85, 0x09, 0xA5, 0x35, 0x85, 0x03, 0xA5, 0x37, 0x85, 0x05, +0x22, 0xA4, 0x16, 0xE1, 0x5C, 0x8C, 0x16, 0xE1, 0xA5, 0x07, 0x89, 0x02, 0x00, 0xF0, 0x05, 0x09, +0x01, 0x40, 0x85, 0x07, 0x89, 0x00, 0x40, 0xF0, 0x57, 0x89, 0x00, 0x10, 0xF0, 0x14, 0xA2, 0x14, +0x00, 0x20, 0xF8, 0x0A, 0x20, 0xD6, 0x0D, 0xF0, 0x07, 0x22, 0x94, 0x16, 0xE1, 0x90, 0xF5, 0x6B, +0xA5, 0x07, 0xA2, 0x0C, 0x00, 0x89, 0x01, 0x00, 0xF0, 0x0C, 0xA5, 0x05, 0xF0, 0x17, 0xC9, 0xE0, +0x00, 0x90, 0x03, 0xA2, 0x14, 0x00, 0x20, 0xF8, 0x0A, 0x20, 0xD6, 0x0D, 0xF0, 0x07, 0x22, 0x94, +0x16, 0xE1, 0x90, 0xF5, 0x6B, 0x20, 0xF5, 0x0A, 0x20, 0xD6, 0x0D, 0xA5, 0x1D, 0xD0, 0x07, 0x22, +0x94, 0x16, 0xE1, 0x90, 0xF3, 0x6B, 0x22, 0xA8, 0x16, 0xE1, 0x90, 0x03, 0x4C, 0x38, 0x0A, 0x6B, +0x89, 0x01, 0x00, 0xF0, 0x09, 0xA5, 0x05, 0xF0, 0x30, 0xC9, 0xE0, 0x00, 0xB0, 0x14, 0xA2, 0x14, +0x00, 0x20, 0x03, 0x0B, 0x20, 0xF0, 0x0D, 0xA5, 0x1D, 0xF0, 0x07, 0x22, 0x94, 0x16, 0xE1, 0x90, +0xF3, 0x6B, 0xA2, 0x1C, 0x00, 0x20, 0x03, 0x0B, 0x20, 0xF0, 0x0D, 0xA5, 0x1D, 0xC9, 0xE0, 0x00, +0x90, 0x07, 0x22, 0x94, 0x16, 0xE1, 0x90, 0xF0, 0x6B, 0xA2, 0x0C, 0x00, 0x20, 0x03, 0x0B, 0x20, +0xF0, 0x0D, 0xF0, 0x07, 0x22, 0x94, 0x16, 0xE1, 0x90, 0xF5, 0x6B, 0x22, 0xA8, 0x16, 0xE1, 0x90, +0x03, 0x4C, 0x38, 0x0A, 0x6B, 0xA2, 0x00, 0x00, 0xBD, 0x00, 0x16, 0x85, 0x13, 0xBD, 0x02, 0x16, +0x85, 0x15, 0x60, 0xBD, 0x00, 0x16, 0x85, 0x0F, 0xBD, 0x02, 0x16, 0x85, 0x11, 0x60, 0xA2, 0x1C, +0x00, 0xA5, 0x07, 0x89, 0x01, 0x00, 0xF0, 0x0A, 0xA5, 0x05, 0xF0, 0x07, 0x4A, 0xD0, 0x03, 0xA2, +0x10, 0x00, 0x60, 0xA2, 0x0C, 0x00, 0x60, 0xA5, 0x1B, 0xC5, 0x1F, 0xD0, 0x08, 0xA5, 0x1D, 0xC5, +0x21, 0xD0, 0x02, 0x18, 0x6B, 0xA5, 0x07, 0x4A, 0x90, 0x14, 0xA8, 0xA5, 0x21, 0xC5, 0x05, 0x90, +0x39, 0xA5, 0x05, 0xC5, 0x1D, 0x90, 0x33, 0xF0, 0x04, 0x85, 0x1D, 0x64, 0x1B, 0x98, 0x4A, 0x90, +0x14, 0xA8, 0xA5, 0x1F, 0xC5, 0x03, 0xA5, 0x21, 0xE5, 0x05, 0x90, 0xD7, 0xA5, 0x03, 0xC5, 0x1B, +0x90, 0xD1, 0x85, 0x1B, 0x98, 0x4A, 0x24, 0x07, 0x50, 0x13, 0x90, 0x11, 0xA8, 0xA9, 0xFF, 0x00, +0x14, 0x1B, 0xF0, 0x08, 0xE6, 0x1C, 0xA5, 0x20, 0xC5, 0x1C, 0x90, 0xB7, 0x98, 0x4A, 0x90, 0x1F, +0xA4, 0x21, 0xC0, 0x02, 0x00, 0x90, 0xAC, 0xA2, 0xFF, 0x5F, 0xC0, 0xE0, 0x00, 0x90, 0x10, 0xF0, +0x03, 0xA2, 0xFF, 0x9F, 0xE4, 0x1B, 0x90, 0x07, 0xE4, 0x1F, 0xB0, 0x97, 0xE8, 0x86, 0x1B, 0x4A, +0x24, 0x07, 0x50, 0x3B, 0x90, 0x2A, 0xA5, 0x21, 0xC5, 0x1D, 0xF0, 0x24, 0x48, 0xA5, 0x1F, 0x48, +0x64, 0x1F, 0xA5, 0x1D, 0x1A, 0x85, 0x21, 0x22, 0xD0, 0x0B, 0xFF, 0xB0, 0x10, 0xA5, 0x1F, 0x85, +0x1B, 0xA5, 0x21, 0x85, 0x1D, 0x68, 0x85, 0x1F, 0x68, 0x85, 0x21, 0x80, 0xD9, 0x68, 0x68, 0x6B, +0x38, 0xA5, 0x1F, 0xE5, 0x1B, 0xA8, 0xA5, 0x21, 0xE5, 0x1D, 0xC4, 0x0B, 0xE5, 0x0D, 0x6B, 0x90, +0x29, 0xA5, 0x1D, 0xC5, 0x21, 0xF0, 0x23, 0x48, 0xA5, 0x1B, 0x48, 0x64, 0x1B, 0xA5, 0x21, 0x85, +0x1D, 0x22, 0x0A, 0x0C, 0xFF, 0xB0, 0xD6, 0xA5, 0x1B, 0x85, 0x1F, 0xA5, 0x1D, 0x85, 0x21, 0x3A, +0xC3, 0x03, 0xD0, 0xEB, 0x68, 0x85, 0x1B, 0x68, 0x85, 0x1D, 0x38, 0xA5, 0x1F, 0xE5, 0x0B, 0xAA, +0xA5, 0x07, 0x29, 0x04, 0x00, 0xF0, 0x05, 0x8A, 0x29, 0x00, 0xFF, 0xAA, 0xA5, 0x21, 0xE5, 0x0D, +0x90, 0x0B, 0xA8, 0xE4, 0x1B, 0xE5, 0x1D, 0x90, 0x04, 0x86, 0x1B, 0x84, 0x1D, 0x6B, 0x18, 0x85, +0x17, 0x86, 0x19, 0x05, 0x19, 0xF0, 0x18, 0xA0, 0x06, 0x00, 0xB7, 0x17, 0x25, 0x2D, 0xC5, 0x09, +0xF0, 0x01, 0x18, 0xA0, 0x12, 0x00, 0xB7, 0x17, 0xAA, 0x88, 0x88, 0xB7, 0x17, 0x90, 0xE0, 0x60, +0xA0, 0x10, 0x00, 0xA5, 0x17, 0x97, 0x0F, 0xC8, 0xC8, 0xA5, 0x19, 0x97, 0x0F, 0xA0, 0x0C, 0x00, +0xA5, 0x17, 0x97, 0x13, 0xC8, 0xC8, 0xA5, 0x19, 0x97, 0x13, 0xA5, 0x1B, 0x85, 0x03, 0xA5, 0x1D, +0x85, 0x05, 0xA0, 0x12, 0x00, 0xBB, 0xB5, 0x03, 0x97, 0x17, 0x88, 0x88, 0x10, 0xF7, 0x60, 0xA0, +0x12, 0x00, 0xBB, 0xB7, 0x17, 0x95, 0x03, 0x88, 0x88, 0x10, 0xF7, 0x60, 0x20, 0x7F, 0x0C, 0xA5, +0x03, 0x05, 0x05, 0xD0, 0x11, 0x20, 0xA8, 0x0C, 0x22, 0x90, 0x16, 0xE1, 0x90, 0x05, 0x20, 0x50, +0x0C, 0x18, 0x6B, 0x20, 0xCE, 0x0D, 0x38, 0x6B, 0xA0, 0x0C, 0x00, 0xB7, 0x17, 0x85, 0x0F, 0xC8, +0xC8, 0xB7, 0x17, 0x85, 0x11, 0xA0, 0x10, 0x00, 0xB7, 0x17, 0x85, 0x13, 0xC8, 0xC8, 0xB7, 0x17, +0x85, 0x15, 0xA5, 0x13, 0x05, 0x15, 0xF0, 0x0D, 0xA0, 0x0C, 0x00, 0xA5, 0x0F, 0x97, 0x13, 0xC8, +0xC8, 0xA5, 0x11, 0x97, 0x13, 0xA5, 0x0F, 0x05, 0x11, 0xF0, 0x0E, 0xA0, 0x10, 0x00, 0xA5, 0x13, +0x97, 0x0F, 0xC8, 0xC8, 0xA5, 0x15, 0x97, 0x0F, 0x60, 0xA2, 0x08, 0x00, 0xA5, 0x17, 0xCD, 0x08, +0x16, 0xD0, 0x07, 0xA5, 0x19, 0xCD, 0x0A, 0x16, 0xF0, 0x11, 0xA5, 0x17, 0xCD, 0x04, 0x16, 0xD0, +0x14, 0xA5, 0x19, 0xCD, 0x06, 0x16, 0xD0, 0x0D, 0xA2, 0x04, 0x00, 0xA5, 0x13, 0x9D, 0x00, 0x16, +0xA5, 0x15, 0x9D, 0x02, 0x16, 0x60, 0xAD, 0x08, 0x16, 0x85, 0x17, 0xAD, 0x0A, 0x16, 0x85, 0x19, +0x05, 0x17, 0xD0, 0x0E, 0xA9, 0x32, 0x00, 0x22, 0xA0, 0x16, 0xE1, 0x90, 0x29, 0x20, 0xAE, 0x0D, +0x80, 0xE4, 0xA0, 0x10, 0x00, 0xB7, 0x17, 0x85, 0x0F, 0x8D, 0x08, 0x16, 0xC8, 0xC8, 0xB7, 0x17, +0x8D, 0x0A, 0x16, 0x85, 0x11, 0x05, 0x0F, 0xF0, 0x0C, 0xA9, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x97, +0x0F, 0xC8, 0xC8, 0x97, 0x0F, 0x38, 0x6B, 0xA0, 0x14, 0x00, 0xA2, 0x08, 0x00, 0xA5, 0x19, 0xF0, +0x4C, 0x5A, 0x88, 0x88, 0xBD, 0x02, 0x16, 0x97, 0x17, 0x85, 0x15, 0x88, 0x88, 0xBD, 0x00, 0x16, +0x97, 0x17, 0x85, 0x13, 0xA5, 0x17, 0x9D, 0x00, 0x16, 0xA5, 0x19, 0x9D, 0x02, 0x16, 0xA9, 0x00, +0x00, 0xA0, 0x0E, 0x00, 0x97, 0x17, 0x88, 0x88, 0x97, 0x17, 0xA0, 0x00, 0x00, 0x97, 0x17, 0xC8, +0xC8, 0x97, 0x17, 0x68, 0xA4, 0x15, 0xF0, 0x15, 0xA0, 0x0C, 0x00, 0x38, 0xE9, 0x14, 0x00, 0x18, +0x65, 0x17, 0x97, 0x13, 0xC8, 0xC8, 0xA5, 0x19, 0x69, 0x00, 0x00, 0x97, 0x13, 0x60, 0xA2, 0x08, +0x00, 0x98, 0x38, 0xE9, 0x14, 0x00, 0xA8, 0xA5, 0x17, 0x18, 0x69, 0x14, 0x00, 0x85, 0x17, 0xA5, +0x19, 0x69, 0x00, 0x00, 0x85, 0x19, 0x4C, 0x5D, 0x0D, 0xA2, 0x04, 0x00, 0x80, 0xE3, 0xA0, 0x14, +0x00, 0xA2, 0x04, 0x00, 0x80, 0x87, 0xE2, 0x10, 0xA5, 0x13, 0x85, 0x0F, 0xA5, 0x15, 0x85, 0x11, +0xA0, 0x10, 0xB7, 0x0F, 0x85, 0x13, 0xA0, 0x12, 0xB7, 0x0F, 0x85, 0x15, 0xF0, 0x36, 0x80, 0x18, +0xE2, 0x10, 0xA5, 0x0F, 0x85, 0x13, 0xA5, 0x11, 0x85, 0x15, 0xA0, 0x0C, 0xB7, 0x13, 0x85, 0x0F, +0xA0, 0x0E, 0xB7, 0x13, 0x85, 0x11, 0xF0, 0x1C, 0xA0, 0x08, 0x18, 0xB7, 0x0F, 0x67, 0x0F, 0x85, +0x1B, 0xA0, 0x0A, 0xB7, 0x0F, 0xA0, 0x02, 0x77, 0x0F, 0x85, 0x1D, 0xB7, 0x13, 0x85, 0x21, 0xA7, +0x13, 0x85, 0x1F, 0xC8, 0xC2, 0x10, 0x60, 0x1A, 0x0A, 0x0A, 0x85, 0x0B, 0x0A, 0x0A, 0x65, 0x0B, +0x85, 0x0B, 0x64, 0x0D, 0xA9, 0x08, 0xD0, 0x85, 0x07, 0x22, 0x90, 0x16, 0xE1, 0x90, 0x5A, 0xA5, +0x1B, 0x85, 0x17, 0xA5, 0x1D, 0x85, 0x19, 0x20, 0x50, 0x0C, 0xA9, 0xFF, 0x00, 0xA0, 0x06, 0x00, +0x97, 0x17, 0xA5, 0x0B, 0x85, 0x1B, 0x64, 0x03, 0x64, 0x05, 0x64, 0x07, 0x64, 0x0B, 0x64, 0x0D, +0xA0, 0x14, 0x00, 0x98, 0x38, 0xE9, 0x14, 0x00, 0x18, 0x65, 0x17, 0x85, 0x0F, 0xA5, 0x19, 0x69, +0x00, 0x00, 0x85, 0x11, 0x98, 0x18, 0x69, 0x14, 0x00, 0x18, 0x65, 0x17, 0x85, 0x13, 0xA5, 0x19, +0x69, 0x00, 0x00, 0x85, 0x15, 0xA2, 0x00, 0x00, 0xB5, 0x03, 0x97, 0x17, 0xC8, 0xC8, 0xE8, 0xE8, +0xE0, 0x14, 0x00, 0x90, 0xF3, 0xC4, 0x1B, 0x90, 0xCA, 0x6B, 0xA5, 0x2D, 0x85, 0x17, 0xA5, 0x2F, +0x85, 0x19, 0xF0, 0x3C, 0xA0, 0x0C, 0x00, 0xB7, 0x17, 0x85, 0x0F, 0xC8, 0xC8, 0xB7, 0x17, 0x85, +0x11, 0x05, 0x0F, 0xF0, 0x12, 0xA0, 0x10, 0x00, 0xB7, 0x0F, 0xC5, 0x17, 0xD0, 0x22, 0xC8, 0xC8, +0xB7, 0x0F, 0xC5, 0x19, 0xD0, 0x1A, 0x60, 0xA2, 0x08, 0x00, 0xA5, 0x17, 0xDF, 0x00, 0x16, 0xE1, +0xD0, 0x08, 0xA5, 0x19, 0xDF, 0x02, 0x16, 0xE1, 0xF0, 0xEC, 0xCA, 0xCA, 0xCA, 0xCA, 0x10, 0xEA, +0xA9, 0x06, 0x02, 0x85, 0x01, 0x68, 0x5C, 0x8C, 0x16, 0xE1, 0xA5, 0x0B, 0xD0, 0x05, 0xC6, 0x0D, +0x10, 0x01, 0x6B, 0xC6, 0x0B, 0xA6, 0x03, 0xE4, 0x07, 0xA5, 0x05, 0xE5, 0x09, 0xB0, 0x6A, 0x8A, +0x65, 0x0B, 0xAA, 0xA5, 0x05, 0x65, 0x0D, 0x29, 0xFF, 0x00, 0x09, 0x00, 0x6B, 0x48, 0xA5, 0x0B, +0x85, 0x13, 0x65, 0x07, 0xA8, 0xA5, 0x0D, 0x65, 0x09, 0xEB, 0x09, 0x44, 0x00, 0x48, 0x80, 0x14, +0x85, 0x0D, 0xA3, 0x02, 0xE0, 0xFF, 0xFF, 0xD0, 0x03, 0xE9, 0x00, 0x01, 0xC0, 0xFF, 0xFF, 0xD0, +0x01, 0x3A, 0x83, 0x02, 0xE4, 0x13, 0xB0, 0x02, 0x86, 0x13, 0xC4, 0x13, 0xB0, 0x02, 0x84, 0x13, +0xA9, 0x0F, 0xFF, 0x48, 0xA9, 0x00, 0x50, 0x48, 0x3B, 0x18, 0x69, 0x04, 0x00, 0x48, 0xA5, 0x13, +0x6B, 0xA5, 0x0B, 0x18, 0xE5, 0x13, 0x85, 0x0B, 0x85, 0x13, 0xA5, 0x0D, 0xE9, 0x00, 0x00, 0x10, +0xBF, 0x68, 0x68, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0x6B, 0xA4, 0x07, 0xA5, 0x05, 0x29, 0xFF, 0x00, +0x09, 0x00, 0x6B, 0x48, 0xA5, 0x09, 0xEB, 0x09, 0x54, 0x00, 0x48, 0xA5, 0x0B, 0x85, 0x13, 0x80, +0x14, 0x85, 0x0D, 0xA3, 0x02, 0xE0, 0x01, 0x00, 0xB0, 0x03, 0x69, 0x00, 0x01, 0xC0, 0x00, 0x00, +0xD0, 0x01, 0x1A, 0x83, 0x02, 0x8A, 0x49, 0xFF, 0xFF, 0xC5, 0x13, 0xB0, 0x02, 0x85, 0x13, 0x98, +0x49, 0xFF, 0xFF, 0xC5, 0x13, 0xB0, 0x02, 0x85, 0x13, 0xA9, 0x0F, 0xFF, 0x48, 0xA9, 0x00, 0xB9, +0x48, 0x3B, 0x18, 0x69, 0x04, 0x00, 0x48, 0xA5, 0x13, 0x6B, 0xA5, 0x0B, 0x18, 0xE5, 0x13, 0x85, +0x0B, 0x85, 0x13, 0xA5, 0x0D, 0xE9, 0x00, 0x00, 0x10, 0xB7, 0x68, 0x68, 0xF4, 0xE1, 0xE1, 0xAB, +0xAB, 0x6B, 0x18, 0xAD, 0xCB, 0x00, 0x29, 0xFF, 0x00, 0xD0, 0x20, 0xE6, 0x23, 0xA5, 0x23, 0xC9, +0x01, 0x00, 0xF0, 0x12, 0x22, 0xB0, 0x16, 0xE1, 0xB0, 0x0C, 0xA5, 0x23, 0x22, 0xB4, 0x16, 0xE1, +0x90, 0x09, 0x22, 0xB0, 0x16, 0xE1, 0x22, 0xAC, 0x16, 0xE1, 0x38, 0x6B, 0x20, 0x0E, 0x0B, 0x0B, +0x3B, 0x38, 0xE9, 0x24, 0x00, 0x1B, 0x5B, 0x20, 0x03, 0x0B, 0xA5, 0x0F, 0x85, 0x13, 0xA5, 0x11, +0x85, 0x15, 0xA0, 0x0E, 0x00, 0xB7, 0x13, 0x85, 0x11, 0x88, 0x88, 0xB7, 0x13, 0x85, 0x0F, 0x05, +0x11, 0xF0, 0x47, 0x88, 0x88, 0xB7, 0x0F, 0xBB, 0x95, 0x03, 0x88, 0x88, 0xC0, 0x04, 0x00, 0xB0, +0xF4, 0x89, 0x00, 0xC0, 0xD0, 0xD4, 0xBB, 0xB7, 0x0F, 0x95, 0x03, 0x95, 0x1B, 0xB7, 0x13, 0x95, +0x1F, 0x88, 0x88, 0x10, 0xF1, 0x22, 0x94, 0x16, 0xE1, 0xA5, 0x1B, 0xC5, 0x03, 0xD0, 0x06, 0xA5, +0x1D, 0xC5, 0x05, 0xF0, 0xB5, 0xA5, 0x1B, 0x87, 0x0F, 0x85, 0x07, 0xA0, 0x02, 0x00, 0xA5, 0x1D, +0x97, 0x0F, 0x85, 0x09, 0x22, 0xA4, 0x16, 0xE1, 0x80, 0xA0, 0x3B, 0x18, 0x69, 0x24, 0x00, 0x1B, +0x2B, 0x6B, 0x18, 0x6B, 0xC9, 0x05, 0x00, 0x90, 0x02, 0x18, 0x6B, 0xA6, 0x0B, 0x86, 0x1F, 0xA6, +0x0D, 0x86, 0x21, 0xC2, 0x10, 0x20, 0x0E, 0x0B, 0xE2, 0x10, 0xBD, 0x00, 0x16, 0x85, 0x1B, 0xBD, +0x02, 0x16, 0x85, 0x1D, 0xA0, 0x0E, 0xB7, 0x1B, 0x85, 0x11, 0xA0, 0x0C, 0xB7, 0x1B, 0x85, 0x0F, +0x20, 0xF8, 0x10, 0x90, 0x48, 0x20, 0x46, 0x11, 0xA5, 0x23, 0xC9, 0x02, 0x00, 0xF0, 0x0E, 0xA5, +0x13, 0x85, 0x1B, 0xA5, 0x15, 0x85, 0x1D, 0xA5, 0x21, 0x10, 0xE5, 0x80, 0x2A, 0xA0, 0x06, 0xB7, +0x1B, 0x29, 0xFF, 0xF0, 0x48, 0xA5, 0x13, 0x85, 0x1B, 0xA5, 0x15, 0x85, 0x1D, 0x20, 0xF8, 0x10, +0x90, 0x10, 0xA0, 0x06, 0xB7, 0x1B, 0x29, 0xFF, 0xF0, 0xC3, 0x01, 0xD0, 0xF0, 0x20, 0x46, 0x11, +0x80, 0xE3, 0x68, 0xA5, 0x1F, 0x10, 0x9C, 0xC6, 0x23, 0xC2, 0x10, 0x38, 0x6B, 0xE6, 0x23, 0xA5, +0x23, 0xC9, 0x05, 0x00, 0x90, 0x8D, 0x80, 0xEF, 0xA6, 0x23, 0xBF, 0x40, 0x11, 0xFF, 0x29, 0x00, +0xFF, 0x48, 0xA5, 0x1B, 0x85, 0x13, 0xA5, 0x1D, 0x85, 0x15, 0xA5, 0x0F, 0x85, 0x1B, 0xA5, 0x11, +0x85, 0x1D, 0xA0, 0x0E, 0xB7, 0x1B, 0x85, 0x11, 0xA0, 0x0C, 0xB7, 0x1B, 0x85, 0x0F, 0x05, 0x11, +0xF0, 0x1E, 0xA5, 0x07, 0x89, 0x08, 0x00, 0xF0, 0x07, 0xA0, 0x02, 0xB7, 0x1B, 0x4A, 0xF0, 0x10, +0xA0, 0x04, 0xB7, 0x1B, 0x30, 0xCC, 0x29, 0x00, 0x03, 0xC3, 0x01, 0x90, 0xC5, 0x38, 0x68, 0x60, +0x18, 0x68, 0x60, 0x03, 0x02, 0x01, 0x8B, 0xA0, 0x10, 0xA5, 0x13, 0x97, 0x0F, 0xAD, 0x04, 0x16, +0x48, 0x97, 0x1B, 0xA0, 0x12, 0xA5, 0x15, 0x97, 0x0F, 0xAD, 0x06, 0x16, 0x97, 0x1B, 0xA8, 0x5A, +0xA0, 0x0E, 0xA5, 0x11, 0x97, 0x13, 0xA0, 0x0C, 0xA5, 0x0F, 0x97, 0x13, 0xA9, 0x00, 0x00, 0x97, +0x1B, 0xA0, 0x0E, 0x97, 0x1B, 0xA0, 0x02, 0x97, 0x1B, 0x87, 0x1B, 0xA5, 0x1D, 0x8D, 0x06, 0x16, +0xA5, 0x1B, 0x8D, 0x04, 0x16, 0xAB, 0xA0, 0x0C, 0x93, 0x01, 0xA5, 0x1D, 0xA0, 0x0E, 0x93, 0x01, +0x68, 0xAB, 0xA0, 0x08, 0xA5, 0x1F, 0x18, 0xF7, 0x1B, 0x85, 0x1F, 0xA0, 0x0A, 0xA5, 0x21, 0xF7, +0x1B, 0x85, 0x21, 0x60, 0xAF, 0x42, 0x16, 0xE1, 0x83, 0x07, 0xAF, 0x44, 0x16, 0xE1, 0x83, 0x09, +0x4C, 0xE9, 0x01, 0x9C, 0x42, 0x16, 0x9C, 0x44, 0x16, 0x9C, 0x46, 0x16, 0x9C, 0x48, 0x16, 0x9C, +0x4A, 0x16, 0xA9, 0x01, 0x00, 0x85, 0x09, 0xE2, 0x30, 0xAD, 0x24, 0x16, 0x3A, 0x3A, 0x0A, 0xCD, +0xF7, 0x02, 0x90, 0x03, 0xAD, 0xF7, 0x02, 0xAA, 0xC2, 0x30, 0x8A, 0x0A, 0xF0, 0x58, 0x48, 0x22, +0xA0, 0x16, 0xE1, 0x90, 0x50, 0x20, 0xC9, 0x0D, 0xA5, 0x17, 0x8D, 0x46, 0x16, 0xA5, 0x19, 0x8D, +0x48, 0x16, 0x68, 0xAA, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x8D, 0x40, 0x16, 0xA0, 0x04, 0x00, 0xA9, +0x08, 0x00, 0x97, 0x17, 0xC8, 0xC8, 0xC8, 0xC8, 0xA9, 0x00, 0x40, 0x97, 0x17, 0xC8, 0xC8, 0xA9, +0x00, 0x00, 0x97, 0x17, 0x98, 0x18, 0x69, 0x0E, 0x00, 0xA8, 0xCA, 0xD0, 0xE2, 0xAD, 0xF6, 0x02, +0x29, 0xFF, 0x00, 0xEB, 0x4A, 0x4A, 0x38, 0xE9, 0x20, 0x00, 0x30, 0x07, 0x48, 0x20, 0x42, 0x12, +0x68, 0x80, 0xF3, 0x18, 0x60, 0x68, 0x38, 0x60, 0xAF, 0x4A, 0x00, 0x00, 0xD0, 0x09, 0xAF, 0x48, +0x00, 0x00, 0xCD, 0x40, 0x16, 0x90, 0x03, 0x4C, 0xA9, 0x12, 0x48, 0x29, 0xE0, 0xFF, 0x4A, 0x48, +0x4A, 0x4A, 0x63, 0x01, 0xFA, 0x6D, 0x46, 0x16, 0x85, 0x17, 0xAD, 0x48, 0x16, 0x69, 0x00, 0x00, +0x85, 0x19, 0xF0, 0x4A, 0xA0, 0x00, 0x00, 0xB7, 0x17, 0x85, 0x03, 0xC8, 0xC8, 0xB7, 0x17, 0x85, +0x05, 0xA5, 0x05, 0xD0, 0x22, 0x22, 0x98, 0x16, 0xE1, 0xB0, 0x33, 0xA5, 0x0B, 0xA8, 0x18, 0x6D, +0x42, 0x16, 0x8D, 0x42, 0x16, 0xAD, 0x44, 0x16, 0x69, 0x00, 0x00, 0x8D, 0x44, 0x16, 0xA9, 0x00, +0x00, 0x88, 0x88, 0x97, 0x03, 0xD0, 0xFA, 0x68, 0x29, 0x1F, 0x00, 0xEB, 0x0A, 0x65, 0x03, 0x85, +0x03, 0xA5, 0x05, 0x69, 0x00, 0x00, 0x85, 0x05, 0x60, 0xA9, 0x2D, 0x00, 0x80, 0x04, 0xA9, 0x27, +0x00, 0x68, 0x85, 0x01, 0x38, 0x60, 0xC9, 0x05, 0x00, 0xF0, 0x6B, 0x2C, 0x4A, 0x16, 0x30, 0x66, +0x48, 0xA9, 0x00, 0x00, 0x20, 0x42, 0x12, 0xB0, 0x5C, 0xAF, 0x00, 0xBF, 0x00, 0xA2, 0x40, 0x00, +0xA0, 0x0E, 0x04, 0x29, 0xFF, 0x00, 0xF0, 0x26, 0xAD, 0x40, 0x16, 0x4A, 0x4A, 0x4A, 0x4A, 0xA8, +0xEB, 0x0A, 0x29, 0x0F, 0x00, 0xAA, 0xBF, 0x57, 0x13, 0xFF, 0xBB, 0xA0, 0x00, 0x0C, 0x97, 0x03, +0xC8, 0xC8, 0xA9, 0xFF, 0xFF, 0xCA, 0xD0, 0xF6, 0xA2, 0x00, 0x00, 0xA0, 0x29, 0x04, 0xAD, 0x40, +0x16, 0x97, 0x03, 0xBF, 0x27, 0x13, 0xFF, 0xE8, 0xE8, 0xC9, 0xFE, 0xFE, 0xD0, 0x0B, 0xBF, 0x27, +0x13, 0xFF, 0xF0, 0x0B, 0xE8, 0xE8, 0xA8, 0x80, 0xEA, 0x97, 0x03, 0xC8, 0xC8, 0x80, 0xE4, 0xA9, +0xFF, 0xFF, 0x8D, 0x4A, 0x16, 0x68, 0x60, 0xFE, 0xFE, 0x02, 0x04, 0x03, 0x00, 0xF4, 0x52, 0x41, +0x4D, 0x35, 0x00, 0xFE, 0xFE, 0x22, 0x04, 0xC3, 0x27, 0x0D, 0x00, 0x00, 0x06, 0xFE, 0xFE, 0x00, +0x06, 0x02, 0x00, 0x04, 0x00, 0xFE, 0xFE, 0x00, 0x08, 0x03, 0x00, 0x05, 0x00, 0xFE, 0xFE, 0x00, +0x0A, 0x04, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x3F, 0x00, +0x1F, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x03, 0xFE, 0xFE, 0x02, 0x04, 0x06, 0x00, 0x00, 0x00, 0x04, +0x52, 0x41, 0x4D, 0x35, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x22, 0x89, 0x01, 0xFF, 0xAF, 0x45, 0x00, +0x00, 0x29, 0xFF, 0x00, 0xC9, 0x0A, 0x00, 0x90, 0x08, 0xE9, 0x40, 0x00, 0xC9, 0x0A, 0x00, 0xB0, +0x29, 0x20, 0xB6, 0x12, 0x0A, 0xAA, 0xFC, 0xA6, 0x13, 0xE2, 0x20, 0xA5, 0x01, 0x8F, 0x50, 0x00, +0x00, 0xC2, 0x20, 0x4C, 0xC4, 0x01, 0xC0, 0x13, 0x2A, 0x14, 0x4E, 0x14, 0xBF, 0x13, 0x6D, 0x14, +0x7C, 0x14, 0xBA, 0x13, 0xBA, 0x13, 0xBA, 0x13, 0xBA, 0x13, 0xA9, 0x01, 0x00, 0x85, 0x01, 0x60, +0xAF, 0x48, 0x00, 0x00, 0x29, 0xFF, 0x00, 0xF0, 0x0B, 0xC9, 0x03, 0x00, 0xF0, 0x06, 0xA9, 0x21, +0x00, 0x85, 0x01, 0x60, 0x48, 0xAF, 0x42, 0x00, 0x00, 0x85, 0x07, 0xAF, 0x44, 0x00, 0x00, 0x29, +0xFF, 0x00, 0x85, 0x09, 0xA0, 0x02, 0x00, 0xAF, 0x45, 0x00, 0x00, 0x29, 0x40, 0x00, 0xF0, 0x01, +0xC8, 0xA9, 0x00, 0x00, 0x97, 0x07, 0xC8, 0xC8, 0xAF, 0x40, 0x16, 0xE1, 0xAA, 0xF0, 0x03, 0xA9, +0xF8, 0x00, 0x09, 0xE8, 0x00, 0x87, 0x07, 0x8A, 0xBB, 0xA0, 0x01, 0x00, 0x97, 0x07, 0x9B, 0x68, +0xF0, 0x12, 0xE2, 0x30, 0xA2, 0x00, 0xBF, 0x93, 0x14, 0xFF, 0x97, 0x07, 0xC8, 0xE8, 0xE0, 0x15, +0x90, 0xF4, 0xC2, 0x30, 0x98, 0x8F, 0x51, 0x00, 0x00, 0x60, 0x20, 0x38, 0x12, 0xB0, 0x1E, 0xAF, +0x42, 0x00, 0x00, 0x85, 0x07, 0xAF, 0x44, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x85, 0x09, 0x64, 0x0D, +0xA9, 0x00, 0x02, 0x85, 0x0B, 0x8F, 0x51, 0x00, 0x00, 0x22, 0xA4, 0x16, 0xE1, 0x60, 0x20, 0x38, +0x12, 0xB0, 0x19, 0xA5, 0x03, 0x85, 0x07, 0xA5, 0x05, 0x85, 0x09, 0xAF, 0x42, 0x00, 0x00, 0x85, +0x03, 0xAF, 0x44, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x85, 0x05, 0x80, 0xD2, 0x60, 0xAF, 0x48, 0x00, +0x00, 0x29, 0xFF, 0x00, 0xF0, 0x05, 0xA9, 0x21, 0x00, 0x85, 0x01, 0x60, 0xA9, 0x00, 0x00, 0x8F, +0x51, 0x00, 0x00, 0xAD, 0x40, 0x16, 0xD0, 0x0A, 0x20, 0xB3, 0x11, 0x90, 0x05, 0xA9, 0x28, 0x00, +0x85, 0x01, 0x60, 0x07, 0x52, 0x41, 0x4D, 0x43, 0x41, 0x52, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, 0x20, 0x20, 0x00, 0xC0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC2, 0x30, 0xF4, 0xFF, 0x00, 0xF4, 0x91, 0x1A, 0xA2, 0x05, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0x6B, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x0C, 0x13, 0x22, 0x00, 0x00, 0xE1, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, 0xA2, 0x0C, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0xFF, 0x00, +0xF4, 0x80, 0x00, 0xA2, 0x0C, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x00, +0xF4, 0x03, 0x00, 0xA2, 0x0C, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x00, 0x00, 0xA2, 0x0C, 0x15, +0x22, 0x00, 0x00, 0xE1, 0xF4, 0x01, 0x00, 0xA2, 0x0C, 0x15, 0x22, 0x00, 0x00, 0xE1, 0xC2, 0x30, +0xF4, 0xFF, 0x00, 0xF4, 0xE3, 0x19, 0xA2, 0x0C, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0xF4, 0x00, 0x00, +0xF4, 0x00, 0x00, 0xA2, 0x0C, 0x22, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x29, 0x7F, 0x00, 0xC9, 0x61, +0x00, 0x90, 0x03, 0x49, 0x20, 0x00, 0xC9, 0x55, 0x00, 0xF0, 0x20, 0xC9, 0x50, 0x00, 0xF0, 0x20, +0xC9, 0x46, 0x00, 0xF0, 0x20, 0xC9, 0x51, 0x00, 0xD0, 0xD3, 0xC2, 0x30, 0xA2, 0x0C, 0x0A, 0x22, +0x00, 0x00, 0xE1, 0xA2, 0x0C, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x6B, 0xA2, 0x00, 0x00, 0x80, 0x0A, +0xA2, 0x04, 0x00, 0x80, 0x05, 0xA2, 0x08, 0x00, 0x80, 0x00, 0x08, 0x78, 0xBF, 0x00, 0x16, 0xE1, +0x85, 0x82, 0xBF, 0x02, 0x16, 0xE1, 0x85, 0x84, 0x64, 0x80, 0x64, 0x9D, 0x64, 0x9F, 0xF4, 0xFF, +0x00, 0xF4, 0x16, 0x1A, 0xA2, 0x0C, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xA5, 0x82, 0x05, +0x83, 0x05, 0x84, 0xD0, 0x1F, 0xA5, 0x9D, 0x05, 0x9E, 0x05, 0xA0, 0xF0, 0x13, 0xA2, 0x3C, 0xBF, +0x52, 0x1A, 0xFF, 0x95, 0xA1, 0xCA, 0x10, 0xF7, 0xA2, 0x1D, 0x20, 0x9A, 0x19, 0x20, 0xCF, 0x19, +0x28, 0x4C, 0x5E, 0x18, 0x64, 0xA1, 0xA0, 0x13, 0xB7, 0x82, 0xBB, 0x95, 0x85, 0x88, 0x10, 0xF8, +0xC2, 0x20, 0x64, 0x99, 0x64, 0x9B, 0xA5, 0x95, 0x05, 0x97, 0xF0, 0x2F, 0xA0, 0x02, 0xA7, 0x95, +0x17, 0x95, 0xF0, 0x27, 0xA7, 0x95, 0x38, 0xE7, 0x82, 0x85, 0x99, 0xB7, 0x95, 0xF7, 0x82, 0x85, +0x9B, 0xA5, 0x99, 0x38, 0xE5, 0x8D, 0x85, 0x99, 0xA5, 0x9B, 0xE5, 0x8F, 0x85, 0x9B, 0xA5, 0x99, +0x18, 0x65, 0x9D, 0x85, 0x9D, 0xA5, 0x9B, 0x65, 0x9F, 0x85, 0x9F, 0xE6, 0x80, 0xE2, 0x30, 0xA2, +0x00, 0x20, 0xA1, 0x19, 0xA2, 0x02, 0x20, 0x9A, 0x19, 0xA2, 0x05, 0x20, 0x9A, 0x19, 0xA2, 0x09, +0x20, 0xA1, 0x19, 0xA2, 0x0B, 0x20, 0xA1, 0x19, 0xA2, 0x0D, 0x20, 0x93, 0x19, 0xA2, 0x11, 0x20, +0x9A, 0x19, 0xA2, 0x15, 0x20, 0x9A, 0x19, 0xA5, 0x99, 0x05, 0x9A, 0x05, 0x9B, 0xF0, 0x05, 0xA2, +0x19, 0x20, 0x9A, 0x19, 0x20, 0xCF, 0x19, 0xA2, 0x03, 0xB5, 0x95, 0x95, 0x82, 0xCA, 0x10, 0xF9, +0x4C, 0xDD, 0x18, 0xDA, 0xB5, 0x83, 0x20, 0xB1, 0x19, 0xFA, 0xDA, 0xB5, 0x82, 0x20, 0xB1, 0x19, +0xFA, 0xDA, 0xB5, 0x81, 0x20, 0xB1, 0x19, 0xFA, 0xB5, 0x80, 0x20, 0xB1, 0x19, 0x20, 0xCB, 0x19, +0x60, 0x48, 0x4A, 0x4A, 0x4A, 0x4A, 0x20, 0xBC, 0x19, 0x68, 0x29, 0x0F, 0x09, 0xB0, 0xC9, 0xBA, +0x90, 0x02, 0x69, 0x06, 0xA6, 0xA1, 0x95, 0xA2, 0xE6, 0xA1, 0x60, 0xA9, 0xA0, 0x80, 0xF5, 0xC2, +0x30, 0xF4, 0x00, 0x00, 0xF4, 0xA1, 0x00, 0xA2, 0x0C, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, +0x64, 0xA1, 0x60, 0x32, 0xD5, 0xBD, 0xA0, 0xD5, 0xF3, 0xE5, 0xE4, 0xA0, 0xEC, 0xE9, 0xF3, 0xF4, +0xA0, 0xA0, 0xD0, 0xBD, 0xA0, 0xD0, 0xF5, 0xF2, 0xE7, 0xE5, 0xA0, 0xEC, 0xE9, 0xF3, 0xF4, 0xA0, +0xA0, 0xC6, 0xBD, 0xA0, 0xC6, 0xF2, 0xE5, 0xE5, 0xA0, 0xEC, 0xE9, 0xF3, 0xF4, 0xA0, 0xA0, 0xD1, +0xBD, 0xA0, 0xD1, 0xF5, 0xE9, 0xF4, 0x3B, 0x8D, 0x8D, 0xA3, 0xA0, 0xA0, 0xA0, 0xA0, 0xC8, 0xE1, +0xEE, 0xE4, 0xEC, 0xE5, 0xA0, 0xA0, 0xC1, 0xE4, 0xE4, 0xF2, 0xA0, 0xA0, 0xC1, 0xF4, 0xF4, 0xF2, +0xA0, 0xA0, 0xC9, 0xC4, 0xA0, 0xA0, 0xA0, 0xA0, 0xD3, 0xE9, 0xFA, 0xE5, 0xA0, 0xA0, 0xA0, 0xA0, +0xD0, 0xF2, 0xE5, 0xF6, 0xA0, 0xA0, 0xA0, 0xCE, 0xE5, 0xF8, 0xF4, 0xA0, 0xA0, 0xA0, 0xC6, 0xF2, +0xE5, 0xE5, 0x35, 0x8D, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, +0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, +0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xD4, 0xEF, 0xF4, 0xE1, 0xEC, 0xA0, 0xC6, 0xF2, 0xE5, 0xE5, +0xA0, 0xCD, 0xE5, 0xED, 0xEF, 0xF2, 0xF9, 0xA0, 0xBD, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, +0xA0, 0x95, 0x1A, 0xFF, 0x00, 0x0D, 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x50, 0x65, 0x65, +0x6B, 0x65, 0x72, 0x10, 0x18, 0xFF, 0x00, 0xAA, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x4C, 0x7E, 0x1D, 0x4C, 0x22, 0x1E, 0x20, 0x7E, 0x1D, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, +0xFF, 0x20, 0x69, 0x2A, 0xFF, 0x10, 0x0D, 0x2D, 0xFF, 0x10, 0x48, 0x26, 0xFF, 0x20, 0x68, 0x26, +0xFF, 0x20, 0xC1, 0x28, 0xFF, 0x00, 0x3B, 0x2A, 0xFF, 0x10, 0x60, 0x2C, 0xFF, 0x10, 0x67, 0x2D, +0xFF, 0x10, 0xF1, 0x2D, 0xFF, 0x10, 0xAF, 0x35, 0xFF, 0x0E, 0x17, 0x36, 0xFF, 0x0E, 0x3C, 0x34, +0xFF, 0x0E, 0x9F, 0x37, 0xFF, 0x0E, 0xA0, 0x3B, 0xFF, 0x0E, 0xF2, 0x37, 0xFF, 0x0E, 0xF7, 0x37, +0xFF, 0x0E, 0xAE, 0x1F, 0xFF, 0x20, 0x7E, 0x21, 0xFF, 0x20, 0x75, 0x23, 0xFF, 0x20, 0x97, 0x23, +0xFF, 0x20, 0x5A, 0x24, 0xFF, 0x20, 0x9F, 0x22, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x22, 0x24, +0xFF, 0x20, 0x0B, 0xA9, 0x00, 0x00, 0x5B, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xE2, 0x20, 0xAD, +0x68, 0xC0, 0x48, 0xAD, 0x83, 0xC0, 0xAD, 0x83, 0xC0, 0xAD, 0x36, 0xC0, 0x48, 0x09, 0x80, 0x8D, +0x36, 0xC0, 0xC2, 0x30, 0x5A, 0xDA, 0xA2, 0x80, 0x00, 0xA9, 0x08, 0x00, 0x20, 0x35, 0x1D, 0xFA, +0x7A, 0x84, 0x82, 0x86, 0x80, 0xA0, 0x01, 0x00, 0xB7, 0x80, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, +0xBD, 0x00, 0xD6, 0x85, 0x84, 0xBD, 0x02, 0xD6, 0xAA, 0x29, 0xFF, 0x00, 0x85, 0x86, 0x05, 0x84, +0xF0, 0x5A, 0x8A, 0xEB, 0x29, 0xFF, 0x00, 0x48, 0xA2, 0x88, 0x00, 0x20, 0x35, 0x1D, 0x18, 0xD4, +0x82, 0xD4, 0x80, 0x8B, 0x22, 0x2A, 0x1D, 0xFF, 0xAB, 0xC2, 0x31, 0x68, 0x85, 0x80, 0x68, 0x85, +0x82, 0x68, 0x69, 0x08, 0x00, 0xAA, 0xE2, 0x31, 0xA0, 0x02, 0xA7, 0x80, 0x30, 0x04, 0xB7, 0x80, +0x30, 0xFC, 0xB7, 0x80, 0xF0, 0x02, 0x10, 0x06, 0x18, 0xF4, 0x00, 0x00, 0x80, 0x03, 0xF4, 0x88, +0x88, 0xC2, 0x30, 0x08, 0x8A, 0xA0, 0x80, 0x00, 0x20, 0x5C, 0x1D, 0x28, 0x68, 0xE2, 0x30, 0xFA, +0x8E, 0x36, 0xC0, 0xFA, 0x8E, 0x68, 0xC0, 0xC2, 0x30, 0xAB, 0x2B, 0x60, 0xA0, 0x02, 0x00, 0xA9, +0x01, 0x01, 0x97, 0x80, 0x18, 0xA9, 0x00, 0x00, 0x80, 0xB8, 0xDC, 0x84, 0x00, 0x20, 0x72, 0x1C, +0x6B, 0xE2, 0x41, 0x80, 0x01, 0xB8, 0xC2, 0x31, 0x09, 0x00, 0x00, 0xF0, 0x1A, 0x8B, 0x48, 0x08, +0xAC, 0x04, 0xDA, 0x6D, 0x04, 0xDA, 0x8D, 0x04, 0xDA, 0x28, 0x68, 0x3A, 0x70, 0x05, 0x54, 0xE1, +0x00, 0xAB, 0x60, 0x54, 0xE1, 0xE1, 0xAB, 0x60, 0xE2, 0x40, 0x80, 0x01, 0xB8, 0xC2, 0x31, 0x3A, +0x30, 0xF5, 0x8B, 0x48, 0x08, 0xAD, 0x04, 0xDA, 0xE3, 0x02, 0x28, 0xAA, 0x68, 0xDA, 0x70, 0x05, +0x54, 0x00, 0xE1, 0x80, 0x03, 0x54, 0xE1, 0xE1, 0x68, 0xAB, 0x8D, 0x04, 0xDA, 0x60, 0x08, 0x8B, +0x20, 0xF5, 0x1D, 0xC2, 0x30, 0xA9, 0x74, 0xDC, 0x8D, 0x04, 0xDA, 0xA9, 0x00, 0x00, 0x8D, 0x00, +0xD6, 0xA2, 0x00, 0xD6, 0xA0, 0x01, 0xD6, 0xA9, 0xFE, 0x03, 0x54, 0xE1, 0xE1, 0xA2, 0x0A, 0x1C, +0xA0, 0x00, 0xD6, 0xA9, 0x67, 0x00, 0x54, 0xE1, 0xFF, 0xA2, 0x67, 0x29, 0xA0, 0xD8, 0xDD, 0xA9, +0x62, 0x00, 0x54, 0xE1, 0xFF, 0xA2, 0xD5, 0x1D, 0xA0, 0x00, 0x10, 0xA9, 0x1F, 0x00, 0x54, 0xE1, +0xFF, 0xA9, 0x5C, 0xDF, 0x8F, 0x36, 0x10, 0xE1, 0xA9, 0x33, 0xFF, 0x8F, 0x38, 0x10, 0xE1, 0x20, +0x13, 0x1E, 0xAB, 0x28, 0x60, 0x6B, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x5C, 0xAB, 0xC7, +0x00, 0x5C, 0x1C, 0x21, 0xFF, 0x5C, 0x32, 0x1E, 0xFF, 0x5C, 0x2D, 0x1D, 0xFF, 0x5C, 0x91, 0x2F, +0xFF, 0x5C, 0x95, 0x2F, 0xFF, 0xE2, 0x30, 0xA9, 0xE1, 0x48, 0xAB, 0xAD, 0x68, 0xC0, 0x2C, 0x83, +0xC0, 0x2C, 0x83, 0xC0, 0x8D, 0x4A, 0xDA, 0xAD, 0x36, 0xC0, 0x8D, 0x4B, 0xDA, 0x09, 0x80, 0x8D, +0x36, 0xC0, 0x60, 0xE2, 0x30, 0xAD, 0x4B, 0xDA, 0x8D, 0x36, 0xC0, 0xAD, 0x4A, 0xDA, 0x8D, 0x68, +0xC0, 0x60, 0x08, 0x8B, 0x20, 0xF5, 0x1D, 0xC2, 0x30, 0x22, 0x10, 0x10, 0xE1, 0x20, 0x13, 0x1E, +0xAB, 0x28, 0x6B, 0xC2, 0x30, 0xA3, 0x05, 0x85, 0x88, 0xA9, 0xE1, 0x00, 0x85, 0x8A, 0xBB, 0xB7, +0x88, 0x85, 0x8C, 0xC8, 0xC8, 0xB7, 0x88, 0x85, 0x8E, 0x9B, 0x8C, 0x44, 0xDA, 0xA5, 0x8C, 0x05, +0x8E, 0xF0, 0x2D, 0xB7, 0x8C, 0x85, 0x90, 0xBB, 0xC8, 0xC8, 0xB7, 0x8C, 0x85, 0x92, 0xDA, 0x9B, +0xF4, 0x67, 0x1E, 0xA3, 0x07, 0x3A, 0x48, 0x60, 0xC2, 0x30, 0x7A, 0xB0, 0x13, 0xA5, 0x8C, 0x85, +0x88, 0xA5, 0x8E, 0x85, 0x8A, 0xA5, 0x90, 0x85, 0x8C, 0xA5, 0x92, 0x85, 0x8E, 0x82, 0xCD, 0xFF, +0xA3, 0x01, 0x83, 0x05, 0x3B, 0x18, 0x69, 0x04, 0x00, 0x1B, 0x60, 0xBB, 0xA5, 0x90, 0x97, 0x88, +0xC8, 0xC8, 0xA5, 0x92, 0x97, 0x88, 0xAC, 0x64, 0xDE, 0xF0, 0x1E, 0xA5, 0x8E, 0xD9, 0x4A, 0xDA, +0xD0, 0x11, 0xA5, 0x8C, 0xD9, 0x48, 0xDA, 0xD0, 0x0A, 0xA5, 0x88, 0x99, 0x48, 0xDA, 0xA5, 0x8A, +0x99, 0x4A, 0xDA, 0x88, 0x88, 0x88, 0x88, 0xD0, 0xE2, 0xA5, 0x88, 0x85, 0x8C, 0xA5, 0x8A, 0x85, +0x8E, 0x9B, 0x60, 0x20, 0x8B, 0x1E, 0x6B, 0xAE, 0x64, 0xDE, 0xE8, 0xE8, 0xE8, 0xE8, 0x8E, 0x64, +0xDE, 0xA5, 0x8C, 0x9D, 0x48, 0xDA, 0xA5, 0x8E, 0x9D, 0x4A, 0xDA, 0x60, 0xAE, 0x64, 0xDE, 0xBD, +0x4A, 0xDA, 0x85, 0x8E, 0xBD, 0x48, 0xDA, 0x85, 0x8C, 0xCA, 0xCA, 0xCA, 0xCA, 0xB7, 0x8C, 0x85, +0x90, 0xC8, 0xC8, 0xB7, 0x8C, 0x85, 0x92, 0x88, 0x88, 0x8E, 0x64, 0xDE, 0x60, 0xFA, 0x68, 0x85, +0x8C, 0x68, 0x85, 0x8E, 0x68, 0x85, 0x88, 0xDA, 0xBB, 0xB1, 0x88, 0x97, 0x8C, 0xC8, 0xC8, 0xB1, +0x88, 0x97, 0x8C, 0xA5, 0x8E, 0x91, 0x88, 0x9B, 0xA5, 0x8C, 0x91, 0x88, 0xAC, 0x64, 0xDE, 0xF0, +0x1F, 0xA5, 0x88, 0xD9, 0x48, 0xDA, 0xD0, 0x12, 0xA9, 0xE1, 0x00, 0xD9, 0x4A, 0xDA, 0xD0, 0x0A, +0xA5, 0x8E, 0x99, 0x4A, 0xDA, 0xA5, 0x8C, 0x99, 0x48, 0xDA, 0x88, 0x88, 0x88, 0x88, 0xD0, 0xE1, +0x60, 0xC2, 0x30, 0xBB, 0x9C, 0x14, 0xDA, 0x9C, 0x16, 0xDA, 0x68, 0x85, 0x9C, 0x68, 0x38, 0xE9, +0x08, 0x00, 0x85, 0x94, 0x4B, 0x4B, 0x68, 0x85, 0x96, 0xF4, 0x6C, 0x1F, 0x20, 0x33, 0x1E, 0xD4, +0x9C, 0xAD, 0x14, 0xDA, 0x60, 0xE2, 0x30, 0xA9, 0x01, 0x8D, 0x16, 0xDA, 0xE2, 0x70, 0xA0, 0x07, +0xC8, 0xB7, 0x94, 0xF0, 0xFB, 0x10, 0x08, 0x1A, 0xF0, 0x20, 0x3A, 0x29, 0x7F, 0xC2, 0x40, 0x5A, +0xA8, 0xB7, 0xA0, 0x70, 0x03, 0xB9, 0x0A, 0xDA, 0x7A, 0xAE, 0x16, 0xDA, 0xF0, 0x04, 0x97, 0x8C, +0x80, 0xDE, 0xD7, 0x8C, 0xF0, 0xDA, 0x18, 0xC2, 0x30, 0x60, 0xAE, 0x16, 0xDA, 0xD0, 0xF8, 0xC2, +0x30, 0xA5, 0x8C, 0x85, 0x80, 0xA5, 0x8E, 0x85, 0x82, 0xEE, 0x14, 0xDA, 0x38, 0x60, 0x20, 0x99, +0x2F, 0xE2, 0x30, 0xA0, 0x19, 0xB7, 0x80, 0xC9, 0x09, 0x90, 0x07, 0xC2, 0x30, 0xA9, 0x0B, 0x05, +0x80, 0x5A, 0xC2, 0x30, 0xA2, 0x1F, 0x20, 0xA0, 0xFF, 0x00, 0xA9, 0x00, 0x00, 0x20, 0xE5, 0x26, +0xD0, 0x4A, 0xE2, 0x30, 0x8A, 0xA0, 0x08, 0x97, 0x80, 0xA0, 0x20, 0xB7, 0x80, 0xA0, 0x28, 0x97, +0x80, 0xA9, 0x00, 0xA0, 0x22, 0x97, 0x80, 0xC2, 0x30, 0xF4, 0x27, 0xDE, 0xD4, 0x82, 0xD4, 0x80, +0xA0, 0x23, 0x00, 0x20, 0xFD, 0x1E, 0xEE, 0x62, 0xDE, 0xAD, 0x62, 0xDE, 0xEB, 0xA0, 0x0D, 0x00, +0x97, 0x80, 0x20, 0x49, 0x21, 0xF0, 0x12, 0xC2, 0x30, 0xC9, 0x05, 0x03, 0xD0, 0x0B, 0xA9, 0x01, +0x05, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x4C, 0xB2, 0x21, 0x4C, 0xD7, 0x20, 0x4C, 0xDC, 0x20, 0xC2, +0x30, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xA2, 0x80, 0x00, 0xA9, 0x28, 0x00, 0x20, 0x35, 0x1D, 0xA6, +0x80, 0xA0, 0xE1, 0x00, 0x86, 0xA0, 0x84, 0xA2, 0xD4, 0xA1, 0xAB, 0xAB, 0x9C, 0x42, 0xDA, 0x20, +0x8C, 0x27, 0xE2, 0x30, 0xD0, 0x21, 0xAD, 0x0A, 0xDA, 0x29, 0xC0, 0xC9, 0x80, 0xD0, 0x18, 0xF4, +0x27, 0xDE, 0xF4, 0xD7, 0x29, 0xA0, 0x23, 0x20, 0x41, 0x1F, 0xE2, 0x30, 0xF0, 0x09, 0xAD, 0x0B, +0xDA, 0xA0, 0x19, 0xD7, 0x80, 0x90, 0x15, 0xC2, 0x20, 0x38, 0xA9, 0x00, 0x80, 0x20, 0x60, 0x2C, +0xC2, 0x30, 0xA0, 0x80, 0x00, 0xA9, 0x28, 0x00, 0x20, 0x5C, 0x1D, 0x6B, 0xAA, 0xBF, 0x09, 0x2A, +0xFF, 0xA0, 0x21, 0x37, 0x80, 0xF0, 0xE0, 0xC2, 0x30, 0x8A, 0x0A, 0x0A, 0x48, 0x0A, 0x63, 0x01, +0xFA, 0xA0, 0x1A, 0x00, 0x20, 0x9B, 0x27, 0xD0, 0xD7, 0xE2, 0x30, 0xA0, 0x22, 0xB7, 0x80, 0x1A, +0x97, 0x80, 0xA0, 0x21, 0xAE, 0x0B, 0xDA, 0xAD, 0x0A, 0xDA, 0x29, 0x10, 0xF0, 0x08, 0xBF, 0x11, +0x2A, 0xFF, 0x37, 0x80, 0x80, 0x06, 0xBF, 0x09, 0x2A, 0xFF, 0x57, 0x80, 0x97, 0x80, 0x08, 0xAD, +0x0A, 0xDA, 0x29, 0x08, 0xF0, 0x03, 0x20, 0x49, 0x21, 0x28, 0xD0, 0x09, 0xC2, 0x30, 0xAD, 0x42, +0xDA, 0x22, 0xB2, 0x21, 0xFF, 0x80, 0x99, 0xC2, 0x30, 0xA9, 0xFF, 0x05, 0xC2, 0x30, 0xA0, 0x02, +0x00, 0x97, 0x80, 0x20, 0xA9, 0x2F, 0xE2, 0x30, 0x09, 0x00, 0x10, 0x01, 0x6B, 0xE2, 0x30, 0xA7, +0x80, 0x10, 0xF9, 0xA0, 0x02, 0xB7, 0x80, 0x30, 0xF3, 0xA0, 0x04, 0xC2, 0x30, 0xAA, 0xB7, 0x80, +0x85, 0x84, 0xC8, 0xC8, 0xB7, 0x80, 0x85, 0x86, 0x05, 0x84, 0xF0, 0xE0, 0x20, 0xC7, 0x1E, 0xAD, +0x44, 0xDA, 0x48, 0x22, 0x1C, 0x21, 0xFF, 0x7A, 0x20, 0xDC, 0x1E, 0x6B, 0xC2, 0x30, 0x3B, 0xAA, +0xA5, 0x86, 0xF0, 0x0C, 0xDA, 0x8B, 0x22, 0xA1, 0xC7, 0x00, 0xC2, 0x30, 0xAB, 0x68, 0x1B, 0x6B, +0xE0, 0x00, 0x02, 0x90, 0x0B, 0xAF, 0x00, 0x01, 0x01, 0x29, 0xFF, 0x00, 0x09, 0x00, 0x01, 0x1B, +0x38, 0xDA, 0x8B, 0x22, 0xA0, 0xC7, 0x00, 0x80, 0xE1, 0xE2, 0x30, 0xA0, 0x1F, 0xB7, 0x80, 0xA0, +0x27, 0x97, 0x80, 0xA0, 0x1E, 0xB7, 0x80, 0x29, 0x20, 0x09, 0x40, 0xE2, 0x30, 0x8D, 0x0A, 0xDA, +0xA0, 0x21, 0xB7, 0x80, 0x8D, 0x0B, 0xDA, 0xC2, 0x31, 0xA5, 0x80, 0x69, 0x0F, 0x00, 0x85, 0xA4, +0xA5, 0x82, 0x69, 0x00, 0x00, 0x85, 0xA6, 0xA9, 0xFF, 0x00, 0x20, 0x07, 0x28, 0x60, 0xC2, 0x30, +0x20, 0x99, 0x2F, 0xA0, 0x02, 0x00, 0xA9, 0x00, 0x00, 0x97, 0x80, 0xA5, 0x80, 0x85, 0xA0, 0xA5, +0x82, 0x85, 0xA2, 0xF4, 0x27, 0xDE, 0xF4, 0xE9, 0x29, 0xA0, 0x23, 0x00, 0x20, 0x41, 0x1F, 0xF0, +0x0B, 0xA9, 0x07, 0x05, 0x22, 0xB2, 0x21, 0xFF, 0x20, 0xA9, 0x2F, 0x6B, 0xA9, 0x03, 0x05, 0x4C, +0xDC, 0x20, 0xC2, 0x30, 0x48, 0xF4, 0x27, 0xDE, 0xA0, 0x23, 0x00, 0x20, 0xEE, 0x21, 0xF0, 0x23, +0x68, 0x48, 0xC9, 0x01, 0x05, 0xF0, 0x13, 0xA0, 0x1E, 0x00, 0xB7, 0x80, 0x29, 0x20, 0x00, 0xF0, +0x09, 0xA9, 0xC0, 0x00, 0x20, 0x5B, 0x21, 0x80, 0x01, 0x48, 0xE2, 0x30, 0xA0, 0x08, 0xB7, 0x80, +0x20, 0x14, 0x27, 0xC2, 0x30, 0x68, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x4C, 0xED, 0x20, 0xC2, 0x30, +0x9C, 0x14, 0xDA, 0x68, 0x85, 0x94, 0xF4, 0x02, 0x22, 0x20, 0x33, 0x1E, 0xD4, 0x94, 0xAD, 0x14, +0xDA, 0x60, 0xA5, 0x80, 0xC5, 0x8C, 0xD0, 0x0E, 0xA5, 0x82, 0xC5, 0x8E, 0xD0, 0x08, 0x20, 0x8B, +0x1E, 0x38, 0xEE, 0x14, 0xDA, 0x60, 0x18, 0x60, 0xF4, 0x27, 0xDE, 0xF4, 0x65, 0x22, 0xA0, 0x23, +0x00, 0x20, 0x33, 0x1E, 0xF4, 0x52, 0xDE, 0xF4, 0x31, 0x22, 0xA0, 0x00, 0x00, 0x20, 0x33, 0x1E, +0x60, 0xE2, 0x31, 0xA0, 0x0F, 0xB7, 0x8C, 0xED, 0x40, 0xDA, 0xF0, 0x06, 0x90, 0x04, 0x97, 0x8C, +0x18, 0x60, 0xC2, 0x30, 0xA5, 0x8C, 0x85, 0x80, 0xA5, 0x8E, 0x85, 0x82, 0x20, 0x04, 0x25, 0x08, +0xA0, 0x00, 0x00, 0x20, 0x8B, 0x1E, 0x28, 0xF0, 0xE7, 0x20, 0x99, 0x2F, 0xA9, 0x05, 0x05, 0x22, +0xDC, 0x20, 0xFF, 0x80, 0xDB, 0xA5, 0x8C, 0x85, 0x80, 0xA5, 0x8E, 0x85, 0x82, 0xE2, 0x31, 0xA0, +0x27, 0xB7, 0x80, 0xED, 0x40, 0xDA, 0x97, 0x80, 0xF0, 0x02, 0xB0, 0x10, 0xA0, 0x28, 0xB7, 0x80, +0xF0, 0x0C, 0x3A, 0xC9, 0xFE, 0xF0, 0x02, 0x97, 0x80, 0x20, 0x49, 0x21, 0x18, 0x60, 0xC2, 0x30, +0xA0, 0x23, 0x00, 0x20, 0x8B, 0x1E, 0xA9, 0x08, 0x05, 0x22, 0xD9, 0x21, 0xFF, 0x80, 0xED, 0xE2, +0x30, 0x20, 0x99, 0x2F, 0xA0, 0x08, 0xB7, 0x80, 0x20, 0xA9, 0x28, 0xD0, 0x1F, 0xE2, 0x30, 0xA0, +0x15, 0xB7, 0x80, 0x29, 0x20, 0xF0, 0x12, 0x20, 0xD9, 0x22, 0xC2, 0x30, 0xD0, 0x05, 0xA9, 0x03, +0x05, 0x80, 0x09, 0x20, 0xCF, 0x22, 0x4C, 0xD7, 0x20, 0x20, 0xCF, 0x22, 0x4C, 0xDC, 0x20, 0xE2, +0x30, 0xA0, 0x16, 0xB7, 0x80, 0x20, 0x13, 0x23, 0x60, 0xC2, 0x30, 0xA5, 0x80, 0x85, 0xA0, 0xA5, +0x82, 0x85, 0xA2, 0xF4, 0x52, 0xDE, 0xF4, 0xF1, 0x29, 0xA0, 0x00, 0x00, 0x20, 0x41, 0x1F, 0x08, +0xF0, 0x1F, 0xA0, 0x04, 0x00, 0xA5, 0xA0, 0x48, 0x97, 0x80, 0xC8, 0xC8, 0xA5, 0xA2, 0x48, 0x97, +0x80, 0xE2, 0x30, 0xA0, 0x0F, 0xA9, 0x78, 0x97, 0x80, 0xC2, 0x30, 0x68, 0x85, 0x82, 0x68, 0x85, +0x80, 0x28, 0x60, 0xE2, 0x30, 0x48, 0xA0, 0x0F, 0xB7, 0x80, 0xAA, 0x68, 0x3F, 0x11, 0x2A, 0xFF, +0x48, 0xA9, 0x80, 0x8D, 0x0A, 0xDA, 0xA9, 0xFF, 0x8D, 0x0B, 0xDA, 0x68, 0xF0, 0x44, 0xEE, 0x0B, +0xDA, 0x4A, 0x48, 0x90, 0xF6, 0xD0, 0x0C, 0xA0, 0x15, 0xB7, 0x80, 0x29, 0x08, 0x0D, 0x0A, 0xDA, +0x8D, 0x0A, 0xDA, 0xAD, 0x0B, 0xDA, 0xAA, 0x1A, 0xA0, 0x10, 0xD7, 0x80, 0x90, 0x0A, 0xD0, 0xDB, +0xA9, 0x10, 0x0D, 0x0A, 0xDA, 0x8D, 0x0A, 0xDA, 0xA0, 0x15, 0xB7, 0x80, 0x29, 0x20, 0x0D, 0x0A, +0xDA, 0x8D, 0x0A, 0xDA, 0x8A, 0x0A, 0x0A, 0x48, 0x0A, 0x63, 0x01, 0xFA, 0x20, 0x07, 0x28, 0xF0, +0xBA, 0x7A, 0xC2, 0x30, 0x60, 0x20, 0x99, 0x2F, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0xA2, 0x7D, 0x24, +0xA0, 0xFF, 0x00, 0x20, 0xE5, 0x26, 0xD0, 0x0C, 0xE2, 0x30, 0x8A, 0xA0, 0x04, 0x97, 0x80, 0xC2, +0x30, 0xA9, 0x00, 0x00, 0x4C, 0xDC, 0x20, 0x20, 0x99, 0x2F, 0xC2, 0x30, 0xA0, 0x02, 0x00, 0xA9, +0x00, 0x00, 0x97, 0x80, 0xE2, 0x30, 0xA0, 0x04, 0xB7, 0x80, 0x85, 0x98, 0x20, 0x14, 0x27, 0xF0, +0x03, 0x4C, 0xDC, 0x20, 0xF4, 0x39, 0xDE, 0xF4, 0xD0, 0x23, 0xA0, 0x1D, 0x00, 0x20, 0x33, 0x1E, +0xF4, 0x52, 0xDE, 0xF4, 0xF8, 0x23, 0xA0, 0x00, 0x00, 0x20, 0x33, 0x1E, 0x20, 0xA9, 0x2F, 0x6B, +0xE2, 0x30, 0xA0, 0x08, 0xB7, 0x8C, 0xC5, 0x98, 0xF0, 0x02, 0x18, 0x60, 0xC2, 0x30, 0xA5, 0x8C, +0x85, 0x80, 0xA5, 0x8E, 0x85, 0x82, 0xA0, 0x1D, 0x00, 0x20, 0x8B, 0x1E, 0x20, 0x99, 0x2F, 0xA9, +0x09, 0x05, 0x22, 0xDC, 0x20, 0xFF, 0x18, 0x60, 0xE2, 0x30, 0xA0, 0x08, 0xB7, 0x8C, 0xC5, 0x98, +0xF0, 0x02, 0x18, 0x60, 0xC2, 0x30, 0xA5, 0x8C, 0x85, 0x94, 0x85, 0x80, 0xA5, 0x8E, 0x85, 0x96, +0x85, 0x82, 0xA0, 0x00, 0x00, 0x20, 0x8B, 0x1E, 0x20, 0xE5, 0x25, 0x20, 0xC4, 0x25, 0xF0, 0xD6, +0x80, 0xCA, 0xC2, 0x30, 0x20, 0x99, 0x2F, 0xA0, 0x02, 0x00, 0xA9, 0x00, 0x00, 0x97, 0x80, 0xA5, +0x80, 0x85, 0xA0, 0xA5, 0x82, 0x85, 0xA2, 0xF4, 0x52, 0xDE, 0xF4, 0x01, 0x2A, 0xA0, 0x00, 0x00, +0x20, 0x41, 0x1F, 0xF0, 0x0F, 0x20, 0xF9, 0x24, 0xF0, 0x06, 0xA9, 0x0D, 0x05, 0x4C, 0xDC, 0x20, +0x20, 0xA9, 0x2F, 0x6B, 0xA9, 0x03, 0x05, 0x4C, 0xDC, 0x20, 0xE2, 0x30, 0x20, 0x99, 0x2F, 0xA0, +0x08, 0xB7, 0x80, 0x20, 0xA9, 0x28, 0xF0, 0x03, 0x4C, 0xDC, 0x20, 0xC2, 0x30, 0xF4, 0x39, 0xDE, +0xD4, 0x82, 0xD4, 0x80, 0xA0, 0x1D, 0x00, 0x20, 0xFD, 0x1E, 0x4C, 0xD7, 0x20, 0xC2, 0x30, 0xF4, +0xE1, 0xE1, 0xAB, 0xAB, 0xA9, 0x28, 0x00, 0xA2, 0x80, 0x00, 0x20, 0x35, 0x1D, 0xA6, 0x80, 0xA0, +0xE1, 0x00, 0x86, 0xA0, 0x84, 0xA2, 0xD4, 0xA1, 0xAB, 0xAB, 0x9C, 0x42, 0xDA, 0x20, 0x8C, 0x27, +0xE2, 0x30, 0xD0, 0x3D, 0xAD, 0x0A, 0xDA, 0xAA, 0x0A, 0x10, 0x36, 0xB0, 0x40, 0x8A, 0x29, 0x20, +0xF0, 0x6F, 0x20, 0xB3, 0x25, 0xF0, 0x6A, 0xA0, 0x0F, 0xA9, 0x78, 0x97, 0x80, 0x20, 0xC4, 0x25, +0xE2, 0x30, 0xF0, 0x1D, 0xAD, 0x0B, 0xDA, 0xA0, 0x16, 0x37, 0x80, 0x48, 0x20, 0x13, 0x23, 0xE2, +0x30, 0x68, 0xAA, 0xA0, 0x16, 0x57, 0x80, 0x48, 0x8A, 0x97, 0x80, 0x68, 0xF0, 0x03, 0x20, 0xD8, +0x25, 0xC2, 0x20, 0x38, 0xA9, 0x00, 0x80, 0x20, 0x60, 0x2C, 0x4C, 0x70, 0x20, 0x20, 0xB3, 0x25, +0xF0, 0xEF, 0x20, 0xF9, 0x24, 0xF0, 0xEA, 0x80, 0x1A, 0xC2, 0x30, 0xF4, 0x52, 0xDE, 0xA0, 0x00, +0x00, 0x20, 0xEE, 0x21, 0xA5, 0x80, 0x85, 0x94, 0xA5, 0x82, 0x85, 0x96, 0x20, 0xE5, 0x25, 0x20, +0xC4, 0x25, 0x60, 0x20, 0x99, 0x2F, 0xC2, 0x30, 0xAD, 0x42, 0xDA, 0x22, 0xDC, 0x20, 0xFF, 0x80, +0xC0, 0xC2, 0x30, 0xF4, 0x39, 0xDE, 0xF4, 0xE7, 0x29, 0xA0, 0x1D, 0x00, 0x20, 0x41, 0x1F, 0xF0, +0xB0, 0x18, 0xA5, 0x80, 0x69, 0x0F, 0x00, 0x85, 0xA4, 0xA5, 0x82, 0x69, 0x00, 0x00, 0x85, 0xA6, +0x20, 0xAA, 0x27, 0xD0, 0xA5, 0xD4, 0x82, 0xD4, 0x80, 0x20, 0x9C, 0x25, 0xE2, 0x30, 0xF4, 0x39, +0xDE, 0xA0, 0x1D, 0x20, 0xEE, 0x21, 0xE2, 0x30, 0xA0, 0x1C, 0xAD, 0x0B, 0xDA, 0x97, 0x80, 0xA0, +0x1B, 0xAD, 0x0A, 0xDA, 0x97, 0x80, 0x29, 0x20, 0xF0, 0xA9, 0x20, 0x24, 0x26, 0xF0, 0x22, 0xA9, +0x00, 0x00, 0xA0, 0x04, 0x00, 0x97, 0x94, 0xC8, 0xC8, 0x97, 0x94, 0xF4, 0x52, 0xDE, 0xD4, 0x96, +0xD4, 0x94, 0xD4, 0x96, 0xD4, 0x94, 0x20, 0x9C, 0x25, 0xA0, 0x00, 0x00, 0x20, 0xFD, 0x1E, 0x80, +0x82, 0xC2, 0x30, 0xA9, 0x02, 0x01, 0x8D, 0x42, 0xDA, 0x82, 0x77, 0xFF, 0xFA, 0x68, 0x85, 0x8C, +0x68, 0x85, 0x8E, 0xF4, 0xD7, 0x29, 0x68, 0x85, 0x94, 0x4B, 0x4B, 0x68, 0x85, 0x96, 0xDA, 0x20, +0x65, 0x1F, 0x60, 0xC2, 0x30, 0xF4, 0x52, 0xDE, 0xF4, 0xDF, 0x29, 0xA0, 0x00, 0x00, 0x20, 0x41, +0x1F, 0xE2, 0x30, 0x60, 0xC2, 0x30, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x48, 0xC8, 0xC8, 0xB7, 0x80, +0x85, 0x82, 0x68, 0x85, 0x80, 0x05, 0x82, 0x60, 0xE2, 0x30, 0xA0, 0x1B, 0x97, 0x80, 0xA0, 0x17, +0x22, 0xFB, 0x20, 0xFF, 0x60, 0xC2, 0x30, 0xAD, 0x4E, 0xDE, 0x87, 0x94, 0xA0, 0x02, 0x00, 0xAD, +0x50, 0xDE, 0x97, 0x94, 0xA5, 0x94, 0x8D, 0x4E, 0xDE, 0xA5, 0x96, 0x8D, 0x50, 0xDE, 0x60, 0xC2, +0x30, 0xA9, 0x74, 0xDA, 0x85, 0x94, 0xA9, 0xE1, 0x00, 0x85, 0x96, 0xA2, 0x20, 0x00, 0x20, 0xE5, +0x25, 0x18, 0xA5, 0x94, 0x69, 0x10, 0x00, 0x85, 0x94, 0xA5, 0x96, 0x69, 0x00, 0x00, 0x85, 0x96, +0xCA, 0xD0, 0xEB, 0x60, 0xC2, 0x30, 0xF4, 0x4E, 0xDE, 0xF4, 0x3B, 0x26, 0x64, 0x94, 0x64, 0x96, +0xA0, 0x00, 0x00, 0x20, 0x33, 0x1E, 0xA5, 0x94, 0x05, 0x96, 0x60, 0xA5, 0x8C, 0x85, 0x94, 0xA5, +0x8E, 0x85, 0x96, 0x20, 0x8B, 0x1E, 0x38, 0x60, 0xC2, 0x30, 0x20, 0x99, 0x2F, 0xF4, 0x4E, 0xDE, +0xD4, 0x82, 0xD4, 0x80, 0xA0, 0x0C, 0x00, 0x20, 0xFD, 0x1E, 0xA0, 0x08, 0x00, 0xAD, 0x00, 0xDA, +0x97, 0x80, 0xA9, 0xFF, 0x01, 0x4C, 0xDC, 0x20, 0xC2, 0x30, 0x20, 0x99, 0x2F, 0xF4, 0x4E, 0xDE, +0xA0, 0x0C, 0x00, 0x20, 0xEE, 0x21, 0xF0, 0x06, 0xA9, 0x00, 0x00, 0x4C, 0xDC, 0x20, 0xA9, 0x03, +0x01, 0x80, 0xF8, 0x29, 0xFF, 0x00, 0x8D, 0x40, 0xDA, 0x18, 0x6D, 0x00, 0xDA, 0x8D, 0x00, 0xDA, +0xA9, 0x28, 0x00, 0xA2, 0x80, 0x00, 0x20, 0x35, 0x1D, 0x20, 0x18, 0x22, 0xF4, 0x4E, 0xDE, 0xF4, +0xB2, 0x26, 0xA0, 0x0C, 0x00, 0x20, 0x33, 0x1E, 0xA9, 0x28, 0x00, 0xA0, 0x80, 0x00, 0x20, 0x5C, +0x1D, 0x60, 0x38, 0xA0, 0x0A, 0x00, 0xB7, 0x8C, 0xED, 0x40, 0xDA, 0x97, 0x8C, 0xF0, 0x04, 0x90, +0x02, 0x18, 0x60, 0xA0, 0x08, 0x00, 0xAD, 0x00, 0xDA, 0x97, 0x8C, 0xA5, 0x8C, 0x85, 0x80, 0xA5, +0x8E, 0x85, 0x82, 0xA0, 0x0C, 0x00, 0x20, 0x8B, 0x1E, 0x20, 0x99, 0x2F, 0xA9, 0x00, 0x00, 0x22, +0xDC, 0x20, 0xFF, 0x80, 0xDC, 0x8E, 0x1D, 0xDA, 0x8C, 0x1F, 0xDA, 0xE2, 0x30, 0x8D, 0x1C, 0xDA, +0xA9, 0x0B, 0x8D, 0x19, 0xDA, 0x20, 0xFE, 0x26, 0xF0, 0x03, 0xA9, 0x0C, 0x05, 0x60, 0xC2, 0x30, +0xA2, 0x18, 0xDA, 0xA0, 0xE1, 0x00, 0x20, 0x72, 0x1C, 0xE2, 0x30, 0xAE, 0x1C, 0xDA, 0xC2, 0x30, +0xAD, 0x1A, 0xDA, 0x60, 0xE2, 0x30, 0x8D, 0x1C, 0xDA, 0xA9, 0x0C, 0x8D, 0x19, 0xDA, 0x20, 0xFE, +0x26, 0xF0, 0x03, 0xA9, 0x02, 0x05, 0x60, 0xA9, 0x5C, 0x62, 0x8F, 0x10, 0x10, 0xE1, 0xA9, 0x27, +0xFF, 0x8F, 0x12, 0x10, 0xE1, 0xC2, 0x30, 0xA2, 0xCA, 0x29, 0xA0, 0x3D, 0xDE, 0xA9, 0x0C, 0x00, +0x54, 0xE1, 0xFF, 0xE2, 0x30, 0xA9, 0x00, 0xA0, 0x20, 0x99, 0x49, 0xDE, 0x88, 0xD0, 0xFA, 0xC2, +0x31, 0x22, 0x93, 0x2A, 0xFF, 0xAA, 0xD0, 0x09, 0xEE, 0x68, 0xDE, 0x20, 0x58, 0x3D, 0x20, 0xFF, +0x25, 0x6B, 0xA9, 0x74, 0xDC, 0x8D, 0x04, 0xDA, 0xA2, 0x80, 0x00, 0xA9, 0x28, 0x00, 0x20, 0x35, +0x1D, 0x9C, 0xE1, 0xDD, 0xA9, 0xD8, 0xDD, 0x85, 0x80, 0xA9, 0xE1, 0x00, 0x85, 0x82, 0x22, 0x35, +0x27, 0xFF, 0xA0, 0x80, 0x00, 0xA9, 0x28, 0x00, 0x20, 0x5C, 0x1D, 0x6B, 0xC2, 0x30, 0xA2, 0x3D, +0xDE, 0xA0, 0xE1, 0x00, 0x20, 0x72, 0x1C, 0xAD, 0x3F, 0xDE, 0x60, 0xC2, 0x31, 0x77, 0x80, 0x85, +0xA4, 0xC8, 0xC8, 0xA9, 0x00, 0x00, 0x77, 0x80, 0x85, 0xA6, 0xC2, 0x30, 0x9C, 0x42, 0xDA, 0xA9, +0x00, 0x08, 0x8D, 0x18, 0xDA, 0x8D, 0x21, 0xDA, 0xA0, 0x06, 0x00, 0xAD, 0x0E, 0xDA, 0x97, 0xA4, +0xAD, 0x10, 0xDA, 0xC8, 0xC8, 0x97, 0xA4, 0xA0, 0x02, 0x00, 0xB7, 0xA4, 0x8D, 0x1E, 0xDA, 0xC8, +0xC8, 0xB7, 0xA4, 0x8D, 0x20, 0xDA, 0xA0, 0x00, 0x00, 0xB7, 0xA4, 0x8D, 0x1C, 0xDA, 0x20, 0xFE, +0x26, 0xF0, 0x13, 0xC9, 0x02, 0x02, 0xF0, 0x0E, 0xC9, 0x09, 0x02, 0xD0, 0x15, 0xAD, 0x23, 0xDA, +0x09, 0x00, 0x80, 0x8D, 0x23, 0xDA, 0xAD, 0x23, 0xDA, 0xA0, 0x0A, 0x00, 0x97, 0xA4, 0xAD, 0x42, +0xDA, 0x60, 0x8D, 0x42, 0xDA, 0x80, 0xEF, 0xC2, 0x30, 0xAA, 0xA9, 0x00, 0x0D, 0x8D, 0x18, 0xDA, +0xE2, 0x30, 0xA9, 0x03, 0x8D, 0x22, 0xDA, 0xA0, 0x08, 0xB7, 0x80, 0x8D, 0x21, 0xDA, 0xA0, 0x1E, +0xB7, 0x80, 0x29, 0x01, 0x8D, 0x1C, 0xDA, 0xC2, 0x20, 0xA0, 0x09, 0xB7, 0x80, 0x8D, 0x1D, 0xDA, +0xA0, 0x0B, 0xB7, 0x80, 0x8D, 0x1F, 0xDA, 0xA9, 0x2C, 0xDA, 0x8D, 0x23, 0xDA, 0xA9, 0xE1, 0x00, +0x8D, 0x25, 0xDA, 0x8A, 0xE8, 0xF0, 0x10, 0x18, 0xA0, 0x11, 0x77, 0x80, 0x85, 0xA4, 0xA0, 0x13, +0xA9, 0x00, 0x00, 0x77, 0x80, 0x85, 0xA6, 0xA0, 0x0D, 0xB7, 0x80, 0x8D, 0x0C, 0xDA, 0xA0, 0x06, +0xB7, 0xA4, 0x8D, 0x0E, 0xDA, 0xC8, 0xC8, 0xB7, 0xA4, 0x8D, 0x10, 0xDA, 0xA9, 0x0A, 0xDA, 0x8D, +0x34, 0xDA, 0xA9, 0xE1, 0x00, 0x8D, 0x36, 0xDA, 0xA9, 0x08, 0x00, 0x8D, 0x32, 0xDA, 0xA0, 0x02, +0xB7, 0xA4, 0x8D, 0x3A, 0xDA, 0xC8, 0xC8, 0xB7, 0xA4, 0x8D, 0x3C, 0xDA, 0xA0, 0x00, 0xB7, 0xA4, +0xAE, 0x0A, 0xDA, 0xE0, 0xC0, 0xD0, 0x03, 0xA9, 0x00, 0x00, 0x8D, 0x38, 0xDA, 0xA9, 0xFF, 0xFF, +0x8D, 0x3E, 0xDA, 0x20, 0xFE, 0x26, 0xE2, 0x30, 0x60, 0xC2, 0x30, 0x20, 0x36, 0x36, 0xE0, 0x7D, +0x24, 0xD0, 0x0A, 0x98, 0x29, 0xFF, 0x00, 0xC9, 0xFF, 0x00, 0xD0, 0x01, 0x60, 0xA9, 0x02, 0x05, +0x60, 0x9C, 0x46, 0xDA, 0xA0, 0xE1, 0x00, 0xA2, 0xD8, 0xDD, 0x20, 0x72, 0x1C, 0xA0, 0xE1, 0x00, +0xA2, 0xEE, 0xDD, 0x20, 0x72, 0x1C, 0xAD, 0x05, 0xDE, 0x29, 0xFF, 0x00, 0xF0, 0x77, 0xE2, 0x30, +0xA2, 0x27, 0xA9, 0xA0, 0x9F, 0x80, 0x04, 0x00, 0xCA, 0x10, 0xF9, 0xA9, 0xAE, 0x8D, 0x48, 0xDA, +0xA0, 0x03, 0xB9, 0x74, 0xDD, 0x99, 0x0F, 0xDE, 0x88, 0x10, 0xF7, 0xC2, 0x30, 0xA9, 0x01, 0x00, +0x8D, 0x1B, 0xDE, 0xA9, 0x00, 0x08, 0x8D, 0x31, 0xDE, 0xA9, 0x00, 0x00, 0x8D, 0x33, 0xDE, 0xE2, +0x30, 0xA9, 0x01, 0x8D, 0x27, 0xDE, 0xC2, 0x30, 0xA0, 0xE1, 0x00, 0xA2, 0x06, 0xDE, 0x20, 0x72, +0x1C, 0xB0, 0xAA, 0xE2, 0x30, 0xAD, 0x48, 0xDA, 0xAE, 0x46, 0xDA, 0xE8, 0xE0, 0x29, 0x90, 0x07, +0xA2, 0x01, 0x49, 0x80, 0x8D, 0x48, 0xDA, 0x8E, 0x46, 0xDA, 0x9F, 0x7F, 0x04, 0x00, 0xEE, 0x1C, +0xDE, 0xAD, 0x35, 0xDE, 0xD0, 0x09, 0x18, 0xEE, 0x32, 0xDE, 0xEE, 0x32, 0xDE, 0x80, 0xC0, 0xC2, +0x30, 0x5C, 0x00, 0x08, 0x00, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0x38, 0xFB, 0xAD, 0x81, 0xC0, 0xA9, +0xC7, 0x85, 0x01, 0x5C, 0xBA, 0xFA, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x2A, 0xFF, 0x00, 0x01, 0x1E, 0x00, 0x00, 0x64, 0x00, 0x74, +0xDD, 0xE1, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2F, +0xDE, 0xE1, 0x00, 0x00, 0x02, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, +0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, +0x0A, 0xDA, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0C, 0x0E, 0x82, 0x03, 0xFF, 0x0D, +0x09, 0x0A, 0x0C, 0x0E, 0x82, 0x03, 0xFF, 0x0D, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, +0xFF, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0xFF, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, +0xFF, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0xFF, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, +0x80, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x01, 0x3D, 0x0A, 0x41, 0x70, 0x70, +0x6C, 0x65, 0x20, 0x2F, 0x2F, 0x67, 0x73, 0x01, 0x2A, 0x28, 0x29, 0xFF, 0x00, 0xF0, 0x06, 0x09, +0x00, 0x02, 0x80, 0x01, 0x28, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x6B, 0x20, 0x99, 0x2F, 0x08, 0xA0, +0x06, 0x00, 0xB7, 0x80, 0x8D, 0x9C, 0x10, 0xC8, 0xC8, 0xB7, 0x80, 0x8D, 0x9E, 0x10, 0xE2, 0x20, +0xA0, 0x04, 0x00, 0xB7, 0x80, 0x8D, 0x94, 0x10, 0xA0, 0x05, 0x00, 0xB7, 0x80, 0x8D, 0x96, 0x10, +0x20, 0xFC, 0x30, 0x20, 0xA9, 0x2F, 0x4C, 0x29, 0x2A, 0x08, 0xA0, 0x04, 0x00, 0xA9, 0xA8, 0xC7, +0x97, 0x80, 0xA9, 0x00, 0x00, 0xC8, 0xC8, 0x97, 0x80, 0xC8, 0xC8, 0xAD, 0x10, 0xD0, 0x97, 0x80, +0xC8, 0xC8, 0xAD, 0x13, 0xD0, 0x97, 0x80, 0xC8, 0xA9, 0x00, 0x10, 0x97, 0x80, 0xA9, 0x00, 0x00, +0x4C, 0x29, 0x2A, 0x08, 0xE2, 0x20, 0xC2, 0x10, 0xB0, 0x22, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x10, +0x16, 0xA0, 0x09, 0x00, 0x5A, 0xB7, 0x80, 0x38, 0x20, 0x93, 0x2A, 0x09, 0x00, 0xD0, 0x05, 0xA9, +0x0A, 0x7A, 0x80, 0x05, 0x7A, 0x97, 0x80, 0xA9, 0x00, 0x4C, 0x29, 0x2A, 0x48, 0xAD, 0xE7, 0x02, +0xF0, 0x05, 0x68, 0xA9, 0x00, 0x28, 0x60, 0xA2, 0x38, 0xC0, 0xA0, 0x45, 0xC0, 0xA9, 0x04, 0x48, +0xA9, 0x4A, 0x48, 0xAD, 0xE1, 0x02, 0xF0, 0x0A, 0xE8, 0x88, 0xA9, 0x20, 0x83, 0x02, 0xA9, 0x8A, +0x83, 0x01, 0x8E, 0xA0, 0x10, 0x8C, 0x8D, 0x10, 0x86, 0x88, 0xE8, 0xE8, 0x86, 0x8A, 0x08, 0x78, +0xA9, 0x00, 0x92, 0x88, 0xA9, 0x09, 0x92, 0x88, 0xA3, 0x02, 0x92, 0x88, 0x28, 0x68, 0x08, 0xC2, +0x20, 0x9C, 0x4E, 0x10, 0xA2, 0x4E, 0x10, 0x9B, 0xC8, 0xA9, 0x0E, 0x00, 0x54, 0xE1, 0xE1, 0xCE, +0x5D, 0x10, 0xA9, 0x2E, 0x00, 0x54, 0xE1, 0xE1, 0xE2, 0x34, 0xA2, 0x00, 0xA0, 0x1E, 0xBF, 0xEB, +0x2B, 0xFF, 0x92, 0x88, 0xE8, 0x88, 0xD0, 0xF6, 0x28, 0x20, 0x31, 0x33, 0xA2, 0x63, 0xE2, 0x8E, +0xB1, 0x10, 0xA9, 0xE0, 0x8D, 0xB3, 0x10, 0xA2, 0x00, 0xE0, 0x8E, 0xAD, 0x10, 0x8E, 0xA9, 0x10, +0xC2, 0x20, 0x9E, 0x00, 0x00, 0xA2, 0xA6, 0xFD, 0x8E, 0xAF, 0x10, 0x4B, 0x4B, 0x68, 0x29, 0xFF, +0x00, 0xF4, 0x00, 0x00, 0xF4, 0x04, 0x00, 0xF4, 0x03, 0x23, 0xF4, 0x08, 0x00, 0x48, 0xF4, 0x60, +0x2E, 0xA2, 0x03, 0x10, 0xDA, 0xF4, 0x0E, 0x00, 0x48, 0xF4, 0x1A, 0x2F, 0x22, 0x00, 0x00, 0xE1, +0xFA, 0xD0, 0xF9, 0xE2, 0x20, 0x68, 0x8D, 0x03, 0x01, 0x68, 0xD0, 0x16, 0xC2, 0x30, 0xF4, 0x00, +0x00, 0xF4, 0x80, 0x00, 0xA2, 0x03, 0x0C, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xE2, 0x20, 0x1A, 0xF0, +0x01, 0x3A, 0x9C, 0x52, 0x10, 0xA2, 0x7F, 0x00, 0x1A, 0xD0, 0x0F, 0x20, 0x3D, 0x2C, 0xAD, 0x90, +0x10, 0x09, 0x80, 0xC9, 0xFF, 0xD0, 0x11, 0x3A, 0x80, 0x0E, 0x3A, 0xD0, 0x0B, 0x20, 0x3D, 0x2C, +0xAD, 0x90, 0x10, 0x29, 0x7F, 0xD0, 0x01, 0x1A, 0xDA, 0x48, 0x20, 0x09, 0x2C, 0x68, 0xFA, 0xB0, +0x14, 0x8D, 0x52, 0x10, 0xC2, 0x30, 0x48, 0x48, 0xF4, 0x80, 0x00, 0xA2, 0x03, 0x0B, 0x22, 0x00, +0x00, 0xE1, 0x68, 0x28, 0x60, 0x1A, 0xC9, 0xFF, 0xD0, 0x04, 0xA9, 0x80, 0x80, 0x06, 0xC9, 0x80, +0xD0, 0x02, 0xA9, 0x01, 0xCA, 0xD0, 0xD1, 0xA9, 0xFF, 0x28, 0x60, 0x01, 0x00, 0x0F, 0x00, 0x04, +0x20, 0x03, 0xD0, 0x05, 0xE9, 0xC0, 0x80, 0x05, 0xE1, 0x07, 0x7E, 0x0A, 0xE0, 0x0B, 0xF2, 0x0C, +0x06, 0x0D, 0x00, 0x0E, 0xC1, 0x0E, 0x21, 0x01, 0x08, 0xA2, 0x78, 0x00, 0x09, 0x00, 0x30, 0x03, +0xA2, 0x14, 0x00, 0x8D, 0x94, 0x10, 0x8D, 0x95, 0x10, 0x08, 0x48, 0x78, 0xA9, 0x06, 0x92, 0x88, +0x68, 0x92, 0x88, 0x28, 0xA9, 0x81, 0x8D, 0x96, 0x10, 0x9C, 0x91, 0x10, 0xDA, 0x20, 0xFC, 0x30, +0xFA, 0xAD, 0x91, 0x10, 0xF0, 0x02, 0x38, 0x60, 0xCA, 0xD0, 0xF1, 0x18, 0x60, 0x08, 0xC2, 0x20, +0xAD, 0x8E, 0x10, 0x29, 0x00, 0xFF, 0x48, 0x0A, 0x18, 0x63, 0x01, 0x18, 0x6D, 0x8F, 0x10, 0x83, +0x01, 0xAD, 0x8F, 0x10, 0x0A, 0x0A, 0x18, 0x63, 0x01, 0x1A, 0x8D, 0x8F, 0x10, 0x68, 0x28, 0x60, +0x08, 0xB0, 0x31, 0xA0, 0x06, 0x00, 0xB7, 0x80, 0xAA, 0xC8, 0xC8, 0xB7, 0x80, 0x48, 0xA0, 0x04, +0x00, 0xB7, 0x80, 0x48, 0xA0, 0x0A, 0x00, 0xB7, 0x80, 0x29, 0xFF, 0x00, 0xF0, 0x03, 0xA9, 0x00, +0x80, 0x03, 0x01, 0x7A, 0x7A, 0x38, 0x20, 0x60, 0x2C, 0x48, 0x8A, 0xA0, 0x0B, 0x00, 0x97, 0x80, +0x68, 0x4C, 0x29, 0x2A, 0x20, 0x99, 0x2F, 0xC2, 0x30, 0x48, 0xAD, 0x57, 0x10, 0xD0, 0x08, 0xA9, +0x01, 0x00, 0xFA, 0x28, 0x4C, 0xA9, 0x2F, 0x68, 0xF4, 0x00, 0x00, 0x48, 0x29, 0xFF, 0x7F, 0x48, +0xAD, 0xAB, 0x10, 0xC3, 0x01, 0xB0, 0x09, 0x83, 0x01, 0xA9, 0x02, 0x00, 0x83, 0x05, 0x80, 0x0B, +0xF0, 0x09, 0xA3, 0x03, 0x10, 0x05, 0xA9, 0x09, 0x00, 0x83, 0x05, 0xA9, 0x54, 0x00, 0x85, 0x84, +0x84, 0x85, 0xA9, 0xE1, 0x6B, 0x85, 0x86, 0x9B, 0xAE, 0x57, 0x10, 0xA3, 0x01, 0xF0, 0x07, 0x3A, +0x8B, 0x22, 0x84, 0x00, 0x00, 0xAB, 0xAD, 0xAB, 0x10, 0x38, 0xE3, 0x01, 0x8D, 0xAB, 0x10, 0xAD, +0x57, 0x10, 0x18, 0x63, 0x01, 0x8D, 0x57, 0x10, 0xFA, 0x68, 0x10, 0x0C, 0x9C, 0x57, 0x10, 0xDA, +0xE2, 0x20, 0x20, 0xC8, 0x33, 0xC2, 0x20, 0xFA, 0x68, 0x28, 0x4C, 0xA9, 0x2F, 0x08, 0xA0, 0x04, +0x00, 0xB7, 0x80, 0xAA, 0xC8, 0xC8, 0xB7, 0x80, 0xA8, 0x20, 0x99, 0x2F, 0xAD, 0x57, 0x10, 0x48, +0xAD, 0xAB, 0x10, 0x48, 0xDA, 0xAD, 0xA9, 0x10, 0xAA, 0x18, 0x69, 0x06, 0x00, 0x8D, 0x57, 0x10, +0xBD, 0x02, 0x00, 0x69, 0x03, 0x00, 0x8D, 0xAB, 0x10, 0x5A, 0xA0, 0x08, 0x00, 0x97, 0x80, 0x7A, +0xFA, 0xA9, 0x10, 0x00, 0x38, 0x20, 0x60, 0x2C, 0xC9, 0x02, 0x00, 0xD0, 0x03, 0xA9, 0x00, 0x00, +0x09, 0x00, 0x00, 0xF0, 0x03, 0x09, 0x00, 0x01, 0x7A, 0x8C, 0xAB, 0x10, 0x7A, 0x8C, 0x57, 0x10, +0x28, 0x20, 0xA9, 0x2F, 0x4C, 0x34, 0x2A, 0x08, 0xB0, 0x18, 0xA0, 0x05, 0x00, 0xB7, 0x80, 0xAA, +0xC8, 0xC8, 0xB7, 0x80, 0x48, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x7A, 0x38, 0x20, 0x67, 0x2D, 0x4C, +0x29, 0x2A, 0xE2, 0x20, 0xDA, 0x5A, 0x20, 0x99, 0x2F, 0xC9, 0xFF, 0xD0, 0x14, 0xAE, 0x59, 0x10, +0xD0, 0x3B, 0xAE, 0x5B, 0x10, 0xD0, 0x36, 0x7A, 0x8C, 0x5B, 0x10, 0xFA, 0x8E, 0x59, 0x10, 0x80, +0x25, 0x20, 0xD3, 0x2D, 0xB0, 0x27, 0xAE, 0xA4, 0x10, 0x10, 0x04, 0xA9, 0x07, 0x80, 0x20, 0x09, +0x00, 0xF0, 0x02, 0x10, 0x04, 0xA9, 0x05, 0x80, 0x16, 0x9D, 0x5D, 0x10, 0xC2, 0x20, 0x68, 0x9D, +0x7D, 0x10, 0x68, 0x9D, 0x6D, 0x10, 0xA9, 0x00, 0xEA, 0x28, 0x4C, 0xA9, 0x2F, 0xA9, 0x06, 0x7A, +0xFA, 0x80, 0xF6, 0xA0, 0xFF, 0xFF, 0xA2, 0x10, 0x00, 0x8C, 0xA4, 0x10, 0xCA, 0xCA, 0x10, 0x02, +0x18, 0x60, 0xDD, 0x5D, 0x10, 0xD0, 0x02, 0x38, 0x60, 0xBC, 0x5C, 0x10, 0x10, 0xEE, 0x9B, 0x80, +0xE8, 0x08, 0xE2, 0x20, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x20, 0x99, 0x2F, 0xC9, 0xFF, 0xD0, 0x16, +0xAE, 0x59, 0x10, 0xD0, 0x05, 0xAE, 0x5B, 0x10, 0xF0, 0x11, 0xA2, 0x00, 0x00, 0x8E, 0x59, 0x10, +0x8E, 0x5B, 0x10, 0x8A, 0x80, 0x0F, 0x20, 0xD3, 0x2D, 0xB0, 0x04, 0xA9, 0x08, 0x80, 0x06, 0xA9, +0xFF, 0x9D, 0x5D, 0x10, 0x1A, 0x28, 0x20, 0xA9, 0x2F, 0x4C, 0x29, 0x2A, 0x08, 0xC2, 0x30, 0xDA, +0xA2, 0x80, 0x00, 0xA9, 0x10, 0x00, 0x20, 0x35, 0x1D, 0xFA, 0x28, 0x60, 0x08, 0xC2, 0x30, 0xDA, +0xA0, 0x80, 0x00, 0xA9, 0x10, 0x00, 0x20, 0x5C, 0x1D, 0xFA, 0x28, 0x60, 0xAD, 0x68, 0xC0, 0x7A, +0x48, 0x5A, 0xAD, 0x83, 0xC0, 0xAD, 0x83, 0xC0, 0x60, 0x7A, 0x68, 0x8D, 0x68, 0xC0, 0x5A, 0x60, +0xC2, 0x10, 0xAE, 0xA0, 0x10, 0xBD, 0x02, 0x00, 0x8D, 0xA8, 0x10, 0x20, 0x4C, 0x2E, 0x20, 0x2C, +0x2E, 0x86, 0x88, 0xE8, 0xE8, 0x86, 0x8A, 0x9C, 0x54, 0x10, 0xAD, 0xA8, 0x10, 0x30, 0x03, 0x4C, +0x00, 0x2F, 0x38, 0x20, 0x9B, 0x30, 0x90, 0xF7, 0x20, 0x9B, 0x30, 0xB0, 0xF2, 0xAD, 0x54, 0x10, +0x30, 0xED, 0xEE, 0x05, 0x01, 0xF0, 0x03, 0x8D, 0x91, 0x10, 0xAD, 0x52, 0x10, 0xF0, 0xE0, 0xAD, +0xA8, 0x10, 0xC9, 0x84, 0xD0, 0x4C, 0xAE, 0xB1, 0x10, 0x86, 0x8C, 0xAE, 0xB3, 0x10, 0x86, 0x8E, +0xEE, 0x51, 0x10, 0x9C, 0x93, 0x10, 0xAD, 0x05, 0x01, 0xD0, 0x05, 0x20, 0x31, 0x33, 0x80, 0x08, +0xAE, 0x06, 0x01, 0xA9, 0x85, 0x20, 0x10, 0x32, 0xAC, 0xAF, 0x10, 0xF0, 0x0E, 0x20, 0xFB, 0x2F, +0x9C, 0x51, 0x10, 0xAD, 0x93, 0x10, 0xF0, 0x2B, 0x20, 0x43, 0x33, 0xAD, 0x53, 0x10, 0xD0, 0x23, +0xEE, 0x53, 0x10, 0x20, 0x5E, 0x2F, 0x58, 0x22, 0x36, 0x10, 0xE1, 0x78, 0x20, 0x7A, 0x2F, 0xCE, +0x53, 0x10, 0xC9, 0x81, 0xD0, 0x0A, 0xAE, 0x06, 0x01, 0xA9, 0x82, 0x20, 0x10, 0x32, 0x80, 0x03, +0x20, 0x31, 0x33, 0x20, 0x3C, 0x2E, 0x20, 0x59, 0x2E, 0xE2, 0x30, 0xA9, 0x03, 0x8D, 0x39, 0xC0, +0xAD, 0x39, 0xC0, 0x0D, 0x03, 0x01, 0x83, 0x04, 0x18, 0x6B, 0x08, 0x8B, 0xE2, 0x20, 0xC2, 0x10, +0xA9, 0xE1, 0x48, 0xAB, 0x8D, 0x47, 0xC0, 0xEE, 0x55, 0x10, 0xAD, 0x53, 0x10, 0xD0, 0x2B, 0x20, +0x4C, 0x2E, 0x20, 0x5E, 0x2F, 0x20, 0x2C, 0x2E, 0xAD, 0x55, 0x10, 0x9C, 0x55, 0x10, 0xEE, 0x53, +0x10, 0xC2, 0x20, 0x58, 0x20, 0x83, 0x26, 0xE2, 0x20, 0x22, 0x36, 0x10, 0xE1, 0x78, 0xCE, 0x53, +0x10, 0x20, 0x3C, 0x2E, 0x20, 0x7A, 0x2F, 0x20, 0x59, 0x2E, 0xAB, 0x28, 0x18, 0x6B, 0x08, 0xC2, +0x30, 0xA2, 0xC3, 0x00, 0xA9, 0x09, 0x00, 0x20, 0x31, 0x1D, 0xA2, 0x08, 0x01, 0xA9, 0x13, 0x00, +0x20, 0x31, 0x1D, 0xE2, 0x20, 0x9C, 0xCB, 0x00, 0x28, 0x60, 0x08, 0xC2, 0x30, 0xA0, 0x08, 0x01, +0xA9, 0x13, 0x00, 0x20, 0x58, 0x1D, 0xA0, 0xC3, 0x00, 0xA9, 0x09, 0x00, 0x20, 0x58, 0x1D, 0x28, +0x60, 0x20, 0x99, 0x2F, 0x6B, 0x20, 0xA9, 0x2F, 0x6B, 0x48, 0x08, 0xE2, 0x20, 0x8B, 0xA9, 0xE1, +0x48, 0xAB, 0xEE, 0x53, 0x10, 0xAB, 0x28, 0x68, 0x60, 0x48, 0xDA, 0x08, 0xE2, 0x20, 0xC2, 0x10, +0x8B, 0xA9, 0xE1, 0x48, 0xAB, 0x20, 0x4C, 0x2E, 0x08, 0x78, 0xCE, 0x53, 0x10, 0xD0, 0x33, 0xAE, +0xA9, 0x10, 0xBD, 0x01, 0x00, 0xF0, 0x15, 0xEE, 0x53, 0x10, 0x28, 0x08, 0x20, 0x2C, 0x2E, 0x22, +0x36, 0x10, 0xE1, 0x20, 0x3C, 0x2E, 0x78, 0xCE, 0x53, 0x10, 0xD0, 0x16, 0xAD, 0x55, 0x10, 0xF0, +0x11, 0x9C, 0x55, 0x10, 0xEE, 0x53, 0x10, 0x28, 0x08, 0xC2, 0x30, 0x20, 0x83, 0x26, 0x78, 0xCE, +0x53, 0x10, 0x28, 0x20, 0x59, 0x2E, 0xAB, 0x28, 0xFA, 0x68, 0x60, 0x9C, 0x54, 0x10, 0xA0, 0x00, +0x00, 0xA2, 0x64, 0x00, 0x18, 0x08, 0x38, 0x08, 0x08, 0x08, 0xB2, 0x88, 0x29, 0x01, 0xD0, 0x06, +0xCA, 0xD0, 0xF7, 0x4C, 0x7C, 0x30, 0xB2, 0x8A, 0x99, 0xA6, 0x10, 0xC8, 0xA2, 0x07, 0x00, 0xC0, +0x03, 0x00, 0xD0, 0xE6, 0xAD, 0xA8, 0x10, 0x30, 0x37, 0xAD, 0x51, 0x10, 0xF0, 0x51, 0xAC, 0xAF, +0x10, 0xAD, 0xA8, 0x10, 0xC9, 0x02, 0xD0, 0x0C, 0x38, 0x20, 0x9B, 0x30, 0x97, 0x8C, 0xC8, 0x28, +0xB0, 0xF7, 0xDA, 0xDA, 0x64, 0x80, 0x64, 0x81, 0x18, 0x20, 0x9B, 0x30, 0xAD, 0x54, 0x10, 0x30, +0x2E, 0xAD, 0x52, 0x10, 0xF0, 0x29, 0xEE, 0x93, 0x10, 0xA6, 0x80, 0x8E, 0xA2, 0x10, 0x80, 0x1F, +0x38, 0x20, 0x9B, 0x30, 0x90, 0x16, 0x20, 0x9B, 0x30, 0xB0, 0x11, 0xAD, 0x54, 0x10, 0x30, 0x0F, +0xAD, 0xA8, 0x10, 0xC9, 0x85, 0xD0, 0x08, 0x8D, 0x92, 0x10, 0x80, 0x03, 0xCE, 0x54, 0x10, 0xFA, +0xFA, 0xAD, 0x54, 0x10, 0x30, 0x0B, 0xAD, 0xA6, 0x10, 0xCD, 0x95, 0x10, 0xD0, 0x03, 0x8D, 0x91, +0x10, 0x4C, 0x31, 0x33, 0x38, 0x2A, 0x85, 0x80, 0xE2, 0x20, 0x18, 0xB2, 0x88, 0x29, 0x01, 0xD0, +0x10, 0xA2, 0x07, 0x00, 0xB2, 0x88, 0x29, 0x01, 0xD0, 0x07, 0xCA, 0xD0, 0xF7, 0xA9, 0x08, 0x80, +0x2A, 0x92, 0x88, 0xB2, 0x88, 0x29, 0xA0, 0xD0, 0x20, 0xB2, 0x8A, 0x90, 0x02, 0x38, 0x60, 0x97, +0x8C, 0xC8, 0xF0, 0x11, 0xC2, 0x20, 0x29, 0xFF, 0x00, 0x65, 0x80, 0x30, 0xC7, 0x18, 0x2A, 0x85, +0x80, 0xE2, 0x20, 0x80, 0xC6, 0xA9, 0x10, 0x80, 0x02, 0x30, 0x10, 0x09, 0x80, 0xAA, 0xAD, 0x54, +0x10, 0x29, 0x01, 0x18, 0xD0, 0x04, 0x8A, 0x0C, 0x54, 0x10, 0x60, 0xA9, 0x01, 0x92, 0x88, 0xB2, +0x88, 0x29, 0x60, 0xD0, 0xE6, 0xA9, 0x01, 0x8D, 0x54, 0x10, 0x18, 0x60, 0x08, 0xE2, 0x20, 0xAD, +0x96, 0x10, 0xC9, 0x81, 0xF0, 0x2E, 0xC2, 0x20, 0xAE, 0x9C, 0x10, 0x86, 0x8C, 0xAE, 0x9E, 0x10, +0x86, 0x8E, 0xA9, 0x58, 0x02, 0xA0, 0x00, 0x00, 0x48, 0xB7, 0x8C, 0x1A, 0xF0, 0x13, 0x68, 0x38, +0xF7, 0x8C, 0x10, 0x05, 0xA9, 0x03, 0x00, 0x28, 0x60, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0x80, +0xE7, 0x68, 0xE2, 0x20, 0xAE, 0xA0, 0x10, 0x86, 0x88, 0xE8, 0xE8, 0x86, 0x8A, 0xA9, 0x01, 0x0C, +0x41, 0xC0, 0xAD, 0x4E, 0x10, 0x20, 0x5B, 0x32, 0x90, 0x0A, 0xF0, 0x08, 0x2E, 0x50, 0x10, 0x9C, +0x4E, 0x10, 0x80, 0x10, 0xAD, 0x4F, 0x10, 0x20, 0x5B, 0x32, 0xB0, 0x08, 0x4E, 0x50, 0x10, 0xA9, +0xFF, 0x8D, 0x4F, 0x10, 0xAD, 0x50, 0x10, 0x8D, 0x97, 0x10, 0x0E, 0x4F, 0x10, 0x0E, 0x4E, 0x10, +0xA2, 0x20, 0x20, 0x8E, 0x98, 0x10, 0x28, 0x08, 0x20, 0x3D, 0x2C, 0xA0, 0xA0, 0x0F, 0xAE, 0x8D, +0x10, 0xBD, 0x00, 0x00, 0x20, 0x0F, 0x32, 0xBD, 0x00, 0x00, 0xF0, 0x08, 0x88, 0xD0, 0xF2, 0x20, +0x31, 0x33, 0x80, 0xE2, 0xA0, 0x04, 0x00, 0x20, 0x6C, 0x32, 0xB0, 0xDA, 0xAD, 0x90, 0x10, 0x2D, +0x97, 0x10, 0xC2, 0x20, 0x29, 0x0F, 0x00, 0xA8, 0xE2, 0x20, 0xF0, 0x05, 0x20, 0x6C, 0x32, 0xB0, +0x42, 0x78, 0x9C, 0x92, 0x10, 0xAE, 0x94, 0x10, 0xA9, 0x81, 0xCD, 0x96, 0x10, 0xF0, 0x02, 0xA9, +0x84, 0x20, 0x10, 0x32, 0xAD, 0x94, 0x10, 0x1A, 0xF0, 0x37, 0x20, 0xFB, 0x2F, 0xAD, 0x96, 0x10, +0xC9, 0x81, 0xD0, 0x07, 0xAD, 0x91, 0x10, 0xF0, 0x07, 0x28, 0x60, 0xAD, 0x92, 0x10, 0xD0, 0x29, +0xA9, 0x01, 0x0C, 0x4E, 0x10, 0x38, 0x2E, 0x97, 0x10, 0xA9, 0x04, 0xCE, 0x98, 0x10, 0xF0, 0x1E, +0x82, 0x83, 0xFF, 0xA9, 0x01, 0x0C, 0x4F, 0x10, 0xCE, 0x99, 0x10, 0xD0, 0xF3, 0xA9, 0x04, 0x80, +0x0D, 0xA0, 0x01, 0x00, 0x20, 0x6C, 0x32, 0xB0, 0xD7, 0x20, 0x8A, 0x32, 0xA9, 0x00, 0x28, 0x60, +0x48, 0x20, 0x20, 0x32, 0xAD, 0x95, 0x10, 0xAA, 0x20, 0x51, 0x32, 0x68, 0xAA, 0x4C, 0x06, 0x33, +0xA9, 0x03, 0x92, 0x88, 0xA9, 0xD0, 0x92, 0x88, 0xA9, 0x05, 0xA8, 0x92, 0x88, 0xA9, 0xE3, 0x92, +0x88, 0x98, 0x92, 0x88, 0xA9, 0xE1, 0x92, 0x88, 0x98, 0x92, 0x88, 0xA9, 0xEB, 0x92, 0x88, 0xA0, +0x1C, 0x00, 0x88, 0xD0, 0xFD, 0xA9, 0x80, 0x92, 0x88, 0x8A, 0x92, 0x8A, 0xA9, 0xC0, 0x92, 0x88, +0x60, 0xB2, 0x88, 0x29, 0x04, 0xF0, 0xFA, 0x8A, 0x92, 0x8A, 0x60, 0xA2, 0x07, 0x00, 0xA0, 0x00, +0x00, 0x0A, 0x90, 0x01, 0xC8, 0xCA, 0x10, 0xF9, 0xC0, 0x02, 0x00, 0x60, 0x84, 0x92, 0xA0, 0x07, +0x00, 0xAE, 0x8D, 0x10, 0xBD, 0x00, 0x00, 0x20, 0x0F, 0x32, 0xBD, 0x00, 0x00, 0xD0, 0x09, 0x88, +0xD0, 0xF2, 0xC6, 0x92, 0xD0, 0xE8, 0x18, 0x60, 0x38, 0x60, 0xC2, 0x20, 0xAD, 0x9C, 0x10, 0x85, +0x8C, 0xAD, 0x9E, 0x10, 0x85, 0x8E, 0xA7, 0x8C, 0x48, 0xA0, 0x02, 0x00, 0xB7, 0x8C, 0x85, 0x8F, +0xC8, 0xC8, 0xB7, 0x8C, 0x85, 0x91, 0xC8, 0xC8, 0x84, 0x92, 0xE2, 0x20, 0xAD, 0x94, 0x10, 0xAA, +0x20, 0x20, 0x32, 0xAD, 0x95, 0x10, 0xAA, 0x20, 0x51, 0x32, 0xAD, 0x96, 0x10, 0x85, 0x94, 0xA0, +0x00, 0x00, 0xFA, 0xB2, 0x88, 0x29, 0x04, 0xF0, 0xFA, 0xA5, 0x94, 0x92, 0x8A, 0xB7, 0x8F, 0x85, +0x94, 0xC8, 0xCA, 0xD0, 0xEE, 0xC2, 0x21, 0xA4, 0x92, 0xB7, 0x8C, 0xD0, 0x09, 0x98, 0x69, 0x06, +0x00, 0xA8, 0xB7, 0x8C, 0xF0, 0xF7, 0xAA, 0x1A, 0xF0, 0x17, 0xC8, 0xC8, 0xB7, 0x8C, 0x85, 0x8F, +0xC8, 0xC8, 0xE2, 0x20, 0xB7, 0x8C, 0x85, 0x91, 0xC8, 0xC8, 0x84, 0x92, 0xA0, 0x00, 0x00, 0x80, +0xC2, 0xE2, 0x20, 0xA5, 0x94, 0xAA, 0x20, 0x51, 0x32, 0xB2, 0x88, 0x29, 0x40, 0xF0, 0xFA, 0xB2, +0x88, 0x29, 0x04, 0xF0, 0xFA, 0xA2, 0x10, 0x00, 0xCA, 0xD0, 0xFD, 0xA9, 0x05, 0x92, 0x88, 0xA9, +0xE3, 0x92, 0x88, 0xA2, 0x2A, 0x00, 0xCA, 0xD0, 0xFD, 0xA9, 0x05, 0x92, 0x88, 0xA9, 0xE1, 0x92, +0x88, 0x08, 0x78, 0xF4, 0xDD, 0x00, 0xF4, 0x30, 0x23, 0xF4, 0x03, 0xD0, 0x68, 0x92, 0x88, 0xD0, +0xFB, 0x28, 0x60, 0xC2, 0x20, 0xAE, 0xAD, 0x10, 0x88, 0x98, 0x38, 0xED, 0xAF, 0x10, 0x9D, 0x02, +0x00, 0xB7, 0x8C, 0x29, 0xFF, 0x00, 0x48, 0xAD, 0xA2, 0x10, 0x6A, 0x08, 0x2A, 0x28, 0x6A, 0x38, +0xE3, 0x01, 0x9D, 0x04, 0x00, 0x68, 0xAD, 0xA6, 0x10, 0x9D, 0x06, 0x00, 0xE2, 0x20, 0xAD, 0xA8, +0x10, 0x9D, 0x08, 0x00, 0xC2, 0x20, 0x98, 0x18, 0x6D, 0xB1, 0x10, 0x18, 0x69, 0x63, 0x02, 0x8D, +0xB1, 0x10, 0x30, 0x0B, 0xA9, 0x63, 0xE2, 0x8D, 0xB1, 0x10, 0xE2, 0x20, 0xEE, 0x56, 0x10, 0xE2, +0x20, 0xAE, 0xAD, 0x10, 0xAD, 0x56, 0x10, 0xC2, 0x21, 0xF0, 0x13, 0xAC, 0xA9, 0x10, 0xCC, 0xB1, +0x10, 0xB0, 0x0B, 0xA9, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x8D, 0xAF, 0x10, 0x80, 0x17, 0x38, 0xAD, +0xB1, 0x10, 0xE9, 0x63, 0x02, 0x9D, 0x00, 0x00, 0x8D, 0xAD, 0x10, 0xAA, 0x9E, 0x00, 0x00, 0xA9, +0xA6, 0xFD, 0x8D, 0xAF, 0x10, 0xE2, 0x20, 0x60, 0xAE, 0xA9, 0x10, 0xBC, 0x00, 0x00, 0xCC, 0xA9, +0x10, 0xB0, 0x03, 0x9C, 0x56, 0x10, 0x8C, 0xA9, 0x10, 0xAC, 0xAF, 0x10, 0xF0, 0xB1, 0x60, 0x08, +0xAD, 0x53, 0x10, 0xC9, 0x01, 0xD0, 0x0A, 0xC2, 0x20, 0xAE, 0xA9, 0x10, 0xBD, 0x00, 0x00, 0xD0, +0x02, 0x28, 0x6B, 0x86, 0x80, 0xBD, 0x02, 0x00, 0x8D, 0xAB, 0x10, 0x8A, 0x18, 0x69, 0x09, 0x00, +0x8D, 0x57, 0x10, 0xE2, 0x20, 0xBD, 0x08, 0x00, 0x20, 0xD3, 0x2D, 0x90, 0x16, 0xC2, 0x20, 0xBC, +0x7D, 0x10, 0xBD, 0x6D, 0x10, 0x85, 0x84, 0x84, 0x86, 0x22, 0x1C, 0x21, 0xFF, 0xE2, 0x20, 0xC2, +0x10, 0x80, 0xBD, 0xAC, 0x59, 0x10, 0xD0, 0x0A, 0xAC, 0x5B, 0x10, 0xD0, 0x05, 0x20, 0xC8, 0x33, +0x80, 0xAE, 0xC2, 0x20, 0xAD, 0x59, 0x10, 0xAC, 0x5B, 0x10, 0x80, 0xD9, 0xA0, 0x09, 0x00, 0xB7, +0x80, 0x20, 0x36, 0x36, 0xF0, 0x09, 0xA6, 0x80, 0xA4, 0x82, 0x20, 0x58, 0x34, 0x80, 0x03, 0xA9, +0x02, 0x03, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x6B, 0x86, 0x88, 0x84, 0x8A, 0x20, 0x99, 0x2F, 0xE2, +0x10, 0xA0, 0x0B, 0xB7, 0x88, 0x85, 0x84, 0x8D, 0x29, 0xD0, 0xA0, 0x0D, 0xB7, 0x88, 0x85, 0x86, +0x8D, 0x2B, 0xD0, 0xA0, 0x05, 0xB7, 0x88, 0xF0, 0x05, 0xCD, 0x10, 0xD0, 0xD0, 0x30, 0xA9, 0x05, +0x00, 0x87, 0x84, 0xEB, 0x8D, 0x16, 0xD0, 0xE2, 0x30, 0xA0, 0x07, 0xB7, 0x88, 0x8D, 0x27, 0xD0, +0xC8, 0xB7, 0x88, 0x8D, 0x18, 0xD0, 0xA0, 0x09, 0xB7, 0x88, 0x8D, 0x19, 0xD0, 0xC8, 0xB7, 0x88, +0x8D, 0x1A, 0xD0, 0xA2, 0x01, 0x8E, 0x28, 0xD0, 0x64, 0x8B, 0xC2, 0x20, 0x80, 0x74, 0xA9, 0x0D, +0x00, 0x87, 0x84, 0xEB, 0x8D, 0x16, 0xD0, 0xA0, 0x05, 0xB7, 0x88, 0x8D, 0x1A, 0xD0, 0xAD, 0x10, +0xD0, 0x8D, 0x1C, 0xD0, 0xE2, 0x30, 0xA0, 0x07, 0xB7, 0x88, 0x8D, 0x1E, 0xD0, 0xC8, 0xB7, 0x88, +0x8D, 0x20, 0xD0, 0xAD, 0x12, 0xD0, 0x8D, 0x1F, 0xD0, 0xA0, 0x09, 0xB7, 0x88, 0x8D, 0x21, 0xD0, +0xC8, 0xB7, 0x88, 0x8D, 0x22, 0xD0, 0xC2, 0x20, 0xA2, 0x02, 0x8E, 0x28, 0xD0, 0x9C, 0x18, 0xD0, +0xA0, 0x04, 0xB7, 0x88, 0xAA, 0x86, 0x8B, 0xF0, 0x11, 0xA9, 0x1A, 0xD0, 0x85, 0x88, 0xA2, 0xE1, +0x86, 0x8A, 0x64, 0x8C, 0xA9, 0x09, 0x00, 0x20, 0x90, 0x35, 0xAD, 0x10, 0xD0, 0xF0, 0x0D, 0xAE, +0x13, 0xD0, 0xD0, 0x0B, 0xC2, 0x30, 0xA9, 0x06, 0x03, 0x4C, 0x8C, 0x35, 0xAE, 0x1E, 0xD0, 0x8E, +0x27, 0xD0, 0xA0, 0x02, 0xA9, 0x16, 0xD0, 0x97, 0x84, 0xA0, 0x04, 0xA9, 0xE1, 0x00, 0x97, 0x84, +0x18, 0xA9, 0x06, 0x00, 0x65, 0x84, 0x85, 0x84, 0xA7, 0x84, 0x30, 0x2F, 0x18, 0xAD, 0x16, 0xD0, +0xEB, 0x67, 0x84, 0xC9, 0x4B, 0x02, 0x90, 0x07, 0xC2, 0x30, 0xA9, 0x05, 0x03, 0x80, 0x3D, 0xEB, +0x8D, 0x16, 0xD0, 0xA6, 0x8B, 0xF0, 0xD9, 0xA0, 0x02, 0xB7, 0x84, 0x85, 0x88, 0xA0, 0x04, 0xB7, +0x84, 0xAA, 0x86, 0x8A, 0xA7, 0x84, 0x20, 0x90, 0x35, 0x80, 0xC5, 0xA6, 0x8B, 0xF0, 0x09, 0xA5, +0x8C, 0xD0, 0x01, 0x3A, 0xEB, 0x8D, 0x18, 0xD0, 0xC2, 0x30, 0xA9, 0x00, 0x07, 0x8D, 0x23, 0xD0, +0xA2, 0x23, 0xD0, 0xA0, 0xE1, 0x00, 0x20, 0x72, 0x1C, 0xAD, 0x25, 0xD0, 0x20, 0xA9, 0x2F, 0x60, +0xC2, 0x30, 0xA0, 0x00, 0x00, 0xAA, 0xE8, 0xCA, 0xF0, 0x12, 0xB7, 0x88, 0x29, 0xFF, 0x00, 0x18, +0x65, 0x8C, 0x18, 0x10, 0x01, 0x38, 0x2A, 0x85, 0x8C, 0xC8, 0x80, 0xEB, 0xE2, 0x10, 0x60, 0xE2, +0x30, 0xA0, 0x04, 0xB7, 0x80, 0xC2, 0x30, 0x30, 0x50, 0xD0, 0x29, 0xAE, 0x31, 0xD0, 0xE8, 0xE8, +0xE8, 0xE8, 0xE0, 0xFC, 0x01, 0x90, 0x03, 0xA2, 0x00, 0x00, 0xEC, 0x31, 0xD0, 0xF0, 0x3F, 0x3C, +0x35, 0xD2, 0x30, 0xEA, 0x8E, 0x31, 0xD0, 0x8A, 0x4A, 0x4A, 0xE2, 0x30, 0x69, 0x80, 0xA0, 0x04, +0x97, 0x80, 0xC2, 0x30, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0xA9, 0x03, 0x03, 0x3C, 0x35, 0xD0, +0x30, 0x1F, 0xA0, 0x05, 0x00, 0xB7, 0x80, 0x9D, 0x33, 0xD0, 0xC8, 0xC8, 0xB7, 0x80, 0x09, 0x00, +0x80, 0x9D, 0x35, 0xD0, 0xA9, 0x00, 0x00, 0x80, 0x08, 0xA9, 0x04, 0x03, 0x80, 0x03, 0xA9, 0x01, +0x03, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x6B, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x29, 0xFF, 0x00, 0x0A, +0x0A, 0xAA, 0xA9, 0x02, 0x03, 0x3C, 0x35, 0xD0, 0x10, 0x06, 0x9E, 0x35, 0xD0, 0xA9, 0x00, 0x00, +0xA0, 0x02, 0x00, 0x97, 0x80, 0x6B, 0x29, 0xFF, 0x00, 0x0A, 0x0A, 0xAA, 0x3C, 0x35, 0xD0, 0x10, +0x0A, 0xBC, 0x35, 0xD0, 0xBD, 0x33, 0xD0, 0xAA, 0xC2, 0x02, 0x60, 0xA2, 0x00, 0x00, 0x9B, 0x60, +0xA0, 0xE1, 0x00, 0x38, 0x20, 0x60, 0x2C, 0x18, 0xA8, 0xF0, 0x04, 0x20, 0x60, 0x36, 0x38, 0x60, +0x38, 0xA9, 0x00, 0x80, 0x4C, 0x60, 0x2C, 0x20, 0x15, 0x37, 0xF0, 0x03, 0x4C, 0x11, 0x37, 0x18, +0xA9, 0x0E, 0x00, 0x65, 0x80, 0x8D, 0x14, 0xD0, 0xA9, 0x05, 0x00, 0xA2, 0x03, 0xD0, 0x20, 0x50, +0x36, 0x90, 0x01, 0x6B, 0xE2, 0x10, 0xA2, 0x01, 0x8E, 0x02, 0xD0, 0xAD, 0x05, 0xD0, 0x8D, 0x0D, +0xD0, 0xAE, 0x07, 0xD0, 0x8E, 0x0F, 0xD0, 0xAE, 0x00, 0xD0, 0x8E, 0x0B, 0xD0, 0xAE, 0x01, 0xD0, +0x8E, 0x0C, 0xD0, 0x9C, 0x09, 0xD0, 0x80, 0x45, 0x20, 0x15, 0x37, 0xD0, 0x64, 0xA0, 0x0B, 0x00, +0xB1, 0x80, 0xF0, 0x08, 0xEB, 0xA0, 0x04, 0x00, 0xD1, 0x80, 0xD0, 0x55, 0x18, 0xA9, 0x16, 0x00, +0x65, 0x80, 0x8D, 0x14, 0xD0, 0xA9, 0x0D, 0x00, 0xA2, 0x03, 0xD0, 0x20, 0x50, 0x36, 0xB0, 0x3E, +0xE2, 0x10, 0xA2, 0x02, 0x8E, 0x02, 0xD0, 0xAD, 0x07, 0xD0, 0xF0, 0x05, 0xCD, 0x10, 0xD0, 0xD0, +0x2E, 0xAE, 0x0B, 0xD0, 0xEC, 0x12, 0xD0, 0xF0, 0x04, 0xE0, 0xFF, 0xD0, 0x22, 0xAE, 0x0D, 0xD0, +0xF0, 0x1D, 0x8A, 0xC2, 0x30, 0x20, 0x36, 0x36, 0xF0, 0x17, 0x86, 0x84, 0x98, 0x29, 0xFF, 0x00, +0x85, 0x86, 0x05, 0x84, 0xF0, 0x0B, 0xA9, 0x00, 0xD0, 0x85, 0x80, 0x4C, 0x1C, 0x21, 0x6B, 0xC2, +0x30, 0x20, 0x60, 0x36, 0x6B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xA0, 0x06, 0x00, 0xB1, 0x80, 0x8D, +0x00, 0xD0, 0xA0, 0x09, 0x00, 0xB1, 0x80, 0xEB, 0x29, 0xFF, 0x03, 0xA0, 0x02, 0x00, 0xD1, 0x80, +0x60, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xAD, 0x0F, 0xD0, 0x29, 0xFF, 0x00, 0xC9, 0x01, 0x00, 0xD0, +0x4A, 0xA9, 0x04, 0x00, 0xA2, 0x2D, 0xD0, 0x20, 0x50, 0x36, 0xB0, 0x42, 0xE2, 0x30, 0xAD, 0x2F, +0xD0, 0xC9, 0x08, 0xD0, 0x34, 0xAD, 0x30, 0xD0, 0x8D, 0x13, 0xD0, 0xC2, 0x30, 0xAD, 0x2D, 0xD0, +0x8D, 0x10, 0xD0, 0xA9, 0x69, 0x01, 0x8D, 0x3D, 0xD4, 0xAD, 0x33, 0xD4, 0xD0, 0x1D, 0xA9, 0x80, +0x04, 0x8D, 0x33, 0xD4, 0xA9, 0x8F, 0x37, 0x8D, 0x37, 0xD4, 0xA9, 0xFF, 0x00, 0x8D, 0x39, 0xD4, +0xA2, 0x33, 0xD4, 0xA0, 0xE1, 0x00, 0x20, 0x72, 0x1C, 0xC2, 0x30, 0x20, 0x60, 0x36, 0x6B, 0xF4, +0xE1, 0xE1, 0xAB, 0xAB, 0xE2, 0x30, 0x9C, 0x13, 0xD0, 0xC2, 0x30, 0x9C, 0x33, 0xD4, 0x6B, 0xA0, +0x08, 0x00, 0xB7, 0x80, 0x18, 0x69, 0x09, 0x00, 0x85, 0x88, 0xA0, 0x0A, 0x00, 0xB7, 0x80, 0x85, +0x8A, 0xE2, 0x30, 0xA0, 0x00, 0xA2, 0x02, 0x20, 0xAA, 0x3A, 0xA8, 0xC2, 0x30, 0xB7, 0x88, 0xC9, +0x01, 0x2A, 0xF0, 0x05, 0xA9, 0x06, 0x04, 0x80, 0x21, 0xE2, 0x30, 0xA0, 0x11, 0xB7, 0x80, 0xC2, +0x30, 0xF0, 0x08, 0x20, 0xB3, 0x3A, 0xA9, 0x00, 0x00, 0x80, 0x0F, 0x20, 0x32, 0x3B, 0xF0, 0x22, +0xA9, 0x02, 0x04, 0x80, 0x05, 0xC2, 0x30, 0xA9, 0x08, 0x04, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x4C, +0x91, 0x38, 0xA0, 0x17, 0x00, 0x80, 0x03, 0xA0, 0x14, 0x00, 0xE2, 0x30, 0xA9, 0x00, 0x97, 0x80, +0xC2, 0x30, 0xAD, 0x56, 0xD4, 0xD0, 0xDE, 0x20, 0x99, 0x2F, 0xA9, 0xFF, 0x04, 0xA0, 0x02, 0x00, +0x97, 0x80, 0xE2, 0x30, 0xEE, 0x4F, 0xD4, 0xA0, 0x0D, 0xB7, 0x80, 0xA0, 0x0F, 0x97, 0x80, 0x20, +0xA6, 0x38, 0xC2, 0x30, 0xA5, 0x80, 0x8D, 0x55, 0xD4, 0xA5, 0x82, 0x8D, 0x57, 0xD4, 0x20, 0xA9, +0x2F, 0x6B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0xC2, 0x20, 0xAD, 0x56, 0xD4, 0x85, 0x81, 0xF0, 0x15, +0xE2, 0x30, 0xAD, 0x55, 0xD4, 0x85, 0x80, 0xA0, 0x0F, 0xB7, 0x80, 0xF0, 0x0B, 0x38, 0xE9, 0x01, +0x97, 0x80, 0x20, 0xA6, 0x38, 0xC2, 0x30, 0x6B, 0x9C, 0x6E, 0xD4, 0x9C, 0x6F, 0xD4, 0xA0, 0x01, +0xB7, 0x80, 0xC9, 0x10, 0xC2, 0x30, 0xF0, 0x05, 0xB0, 0x08, 0x20, 0xB3, 0x3A, 0xA9, 0x00, 0x00, +0x80, 0x03, 0xA9, 0x03, 0x04, 0xA0, 0x02, 0x00, 0x97, 0x80, 0x9C, 0x56, 0xD4, 0xAD, 0x6E, 0xD4, +0xF0, 0x0F, 0xA9, 0x00, 0x05, 0x8D, 0x6E, 0xD4, 0xA2, 0x6E, 0xD4, 0xA0, 0xE1, 0x00, 0x20, 0x72, +0x1C, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x85, 0x84, 0xC8, 0xC8, 0xB7, 0x80, 0x85, 0x86, 0x05, 0x84, +0xF0, 0x03, 0x4C, 0x1C, 0x21, 0x6B, 0xA0, 0x0C, 0xB7, 0x80, 0xA0, 0x0E, 0x97, 0x80, 0xA9, 0x21, +0x8D, 0x4E, 0xD4, 0xA0, 0x01, 0xB7, 0x80, 0xC9, 0x11, 0xC2, 0x20, 0xF0, 0x15, 0x9C, 0x44, 0xD4, +0xAE, 0x13, 0xD0, 0xD0, 0x03, 0xCA, 0x80, 0x05, 0xA0, 0x11, 0x8C, 0x4E, 0xD4, 0x8E, 0x46, 0xD4, +0x80, 0x0F, 0xA0, 0x10, 0xB7, 0x80, 0x8D, 0x44, 0xD4, 0xA0, 0x12, 0xB7, 0x80, 0xA8, 0x8C, 0x46, +0xD4, 0xA0, 0x02, 0x8C, 0x49, 0xD4, 0x8C, 0x48, 0xD4, 0x8C, 0x47, 0xD4, 0x8C, 0x53, 0xD4, 0xAD, +0x10, 0xD0, 0x8D, 0x50, 0xD4, 0xA7, 0x80, 0xEB, 0xAA, 0xA0, 0x08, 0xB7, 0x80, 0xE0, 0x0E, 0xD0, +0x03, 0x69, 0x08, 0x00, 0x85, 0x88, 0x8D, 0x67, 0xD4, 0xA0, 0x0A, 0xB7, 0x80, 0x85, 0x8A, 0x8D, +0x69, 0xD4, 0xE2, 0x30, 0xA0, 0x00, 0x20, 0xA8, 0x3A, 0x8D, 0x65, 0xD4, 0x9C, 0x66, 0xD4, 0xAD, +0x12, 0xD0, 0x8D, 0x52, 0xD4, 0x9C, 0x54, 0xD4, 0x9C, 0x43, 0xD4, 0xC2, 0x30, 0xA9, 0x59, 0xD4, +0x8D, 0x4A, 0xD4, 0xA9, 0xE1, 0x00, 0x8D, 0x4C, 0xD4, 0xA2, 0x3F, 0xD4, 0xA0, 0xE1, 0x00, 0x20, +0x58, 0x34, 0xA0, 0x0C, 0x00, 0xB7, 0x80, 0x29, 0xFF, 0x00, 0x8D, 0x78, 0xD4, 0xA9, 0x80, 0x04, +0x8D, 0x6E, 0xD4, 0xA9, 0x32, 0x38, 0x8D, 0x72, 0xD4, 0xA9, 0xFF, 0x00, 0x8D, 0x74, 0xD4, 0xA2, +0x6E, 0xD4, 0xA0, 0xE1, 0x00, 0x20, 0x72, 0x1C, 0xE2, 0x30, 0x60, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, +0xA2, 0x88, 0x00, 0xA9, 0x06, 0x00, 0x20, 0x35, 0x1D, 0xE2, 0x30, 0xA9, 0x02, 0xCD, 0x0F, 0xD0, +0xD0, 0x27, 0xC2, 0x30, 0xAD, 0x14, 0xD0, 0x85, 0x88, 0xE2, 0x30, 0xA9, 0xE1, 0x85, 0x8A, 0xA0, +0x00, 0xB1, 0x88, 0xAA, 0x29, 0x0F, 0xF0, 0x11, 0x8D, 0x6D, 0xD4, 0x8A, 0x29, 0xF0, 0xC9, 0x30, +0xF0, 0x16, 0xC9, 0x20, 0xD0, 0x03, 0x20, 0x08, 0x3C, 0xC2, 0x30, 0x20, 0x60, 0x36, 0xA0, 0x88, +0x00, 0xA9, 0x06, 0x00, 0x20, 0x5C, 0x1D, 0x6B, 0xC2, 0x30, 0xAD, 0x56, 0xD4, 0x85, 0x81, 0xE2, +0x30, 0xF0, 0xE6, 0xAD, 0x4F, 0xD4, 0xA0, 0x01, 0xD1, 0x88, 0xD0, 0xDD, 0xAD, 0x55, 0xD4, 0x85, +0x80, 0xA0, 0x01, 0xB7, 0x80, 0xC9, 0x10, 0xF0, 0x29, 0xB0, 0x07, 0xC2, 0x30, 0xA9, 0x02, 0x04, +0x80, 0x17, 0xA0, 0x05, 0xB1, 0x88, 0xA0, 0x14, 0x97, 0x80, 0x88, 0xD7, 0x80, 0xC2, 0x30, 0xD0, +0x05, 0xA9, 0x00, 0x00, 0x80, 0x03, 0xA9, 0x07, 0x04, 0x48, 0x22, 0xA9, 0x39, 0xFF, 0x68, 0x4C, +0x75, 0x38, 0xC2, 0x30, 0x18, 0xA5, 0x88, 0x69, 0x02, 0x00, 0x85, 0x88, 0xE2, 0x30, 0xCE, 0x6D, +0xD4, 0x30, 0x96, 0xC2, 0x30, 0xA0, 0x12, 0x00, 0xB7, 0x80, 0x85, 0x84, 0xE2, 0x30, 0xA0, 0x14, +0xB7, 0x80, 0x85, 0x86, 0xA0, 0x17, 0xB7, 0x80, 0xAA, 0xE8, 0x86, 0x8C, 0xC6, 0x8C, 0xF0, 0x30, +0xA0, 0x04, 0xB7, 0x84, 0xD1, 0x88, 0xD0, 0x11, 0x88, 0x10, 0xF7, 0x20, 0xA6, 0x3A, 0x18, 0x65, +0x88, 0x85, 0x88, 0x90, 0xC9, 0xE6, 0x89, 0x80, 0xC5, 0xA0, 0x05, 0xA2, 0x03, 0x38, 0x98, 0x77, +0x84, 0xA8, 0xCA, 0xD0, 0xF8, 0x18, 0x65, 0x84, 0x85, 0x84, 0x90, 0xD0, 0xE6, 0x85, 0x80, 0xCC, +0x20, 0xA6, 0x3A, 0xAA, 0xC2, 0x20, 0x29, 0xFF, 0x00, 0x18, 0x65, 0x84, 0x38, 0xA0, 0x12, 0xF7, +0x80, 0xA0, 0x10, 0xD7, 0x80, 0xE2, 0x30, 0xF0, 0x02, 0xB0, 0x23, 0x9B, 0x88, 0x30, 0x06, 0xB1, +0x88, 0x97, 0x84, 0x80, 0xF7, 0xA0, 0x17, 0x18, 0xB7, 0x80, 0x69, 0x01, 0x97, 0x80, 0x88, 0xD7, +0x80, 0xF0, 0x03, 0x8A, 0x80, 0xA8, 0xC2, 0x30, 0xA9, 0x00, 0x00, 0x4C, 0xF9, 0x39, 0xC2, 0x30, +0xA9, 0x04, 0x04, 0x4C, 0xF9, 0x39, 0xA0, 0x05, 0xA2, 0x03, 0x38, 0x98, 0x77, 0x88, 0xA8, 0xCA, +0xD0, 0xF8, 0x60, 0x20, 0x99, 0x2F, 0xE2, 0x30, 0xA0, 0x10, 0xB7, 0x80, 0x85, 0x8C, 0x64, 0x8D, +0xC2, 0x20, 0xA6, 0x8D, 0xE8, 0x86, 0x8D, 0xAD, 0x7E, 0xD4, 0x85, 0x84, 0xAD, 0x80, 0xD4, 0x85, +0x86, 0xA5, 0x85, 0xF0, 0x1F, 0xA0, 0x07, 0xB7, 0x84, 0xAA, 0xE4, 0x8C, 0xD0, 0x08, 0xA6, 0x8D, +0xF0, 0xEF, 0xC5, 0x8C, 0xF0, 0xDC, 0xA0, 0x02, 0xB7, 0x84, 0x48, 0xA7, 0x84, 0x85, 0x84, 0x68, +0x85, 0x86, 0x80, 0xDD, 0xA0, 0x0A, 0xB7, 0x80, 0x85, 0x86, 0xA0, 0x08, 0xB7, 0x80, 0x85, 0x84, +0xAD, 0x7E, 0xD4, 0x87, 0x84, 0xAD, 0x80, 0xD4, 0xA0, 0x02, 0x97, 0x84, 0xA5, 0x84, 0x8D, 0x7E, +0xD4, 0xA5, 0x86, 0x8D, 0x80, 0xD4, 0xAD, 0x10, 0xD0, 0xA0, 0x04, 0x97, 0x84, 0xA5, 0x8C, 0xA0, +0x07, 0x97, 0x84, 0xE2, 0x30, 0xAD, 0x12, 0xD0, 0xA0, 0x06, 0x97, 0x84, 0xC2, 0x30, 0x20, 0xA9, +0x2F, 0x60, 0xE2, 0x30, 0xA0, 0x00, 0x20, 0xA8, 0x3A, 0x85, 0x8C, 0xC2, 0x30, 0xAD, 0x7E, 0xD4, +0x85, 0x84, 0xAD, 0x80, 0xD4, 0x85, 0x86, 0xA5, 0x85, 0xF0, 0x54, 0x18, 0xA5, 0x84, 0x69, 0x09, +0x00, 0x85, 0x84, 0xE2, 0x30, 0xA4, 0x8C, 0x88, 0xB7, 0x84, 0xC9, 0x61, 0x90, 0x06, 0xC9, 0x7B, +0xB0, 0x02, 0x29, 0xDF, 0x85, 0x83, 0xB7, 0x88, 0xC9, 0x61, 0x90, 0x06, 0xC9, 0x7B, 0xB0, 0x02, +0x29, 0xDF, 0xC5, 0x83, 0xD0, 0x11, 0x88, 0x10, 0xDF, 0xC2, 0x30, 0x38, 0xA5, 0x84, 0xE9, 0x09, +0x00, 0x85, 0x84, 0xA9, 0x01, 0x00, 0x60, 0xC2, 0x30, 0x38, 0xA5, 0x84, 0xE9, 0x09, 0x00, 0x85, +0x84, 0xA0, 0x02, 0x00, 0xB7, 0x84, 0xAA, 0xA7, 0x84, 0x85, 0x84, 0x86, 0x86, 0x80, 0xA8, 0x60, +0x20, 0x99, 0x2F, 0xA0, 0x04, 0x00, 0xB7, 0x80, 0x85, 0x88, 0xA0, 0x06, 0x00, 0xB7, 0x80, 0x85, +0x8A, 0x20, 0x32, 0x3B, 0xF0, 0x46, 0xAD, 0x7E, 0xD4, 0x85, 0x88, 0xC5, 0x84, 0x08, 0xAD, 0x80, +0xD4, 0x85, 0x8A, 0x28, 0xD0, 0x04, 0xC5, 0x86, 0xF0, 0x20, 0xA7, 0x88, 0xAA, 0xA0, 0x02, 0x00, +0xB7, 0x88, 0xC5, 0x86, 0xD0, 0x04, 0xE4, 0x84, 0xF0, 0x06, 0x86, 0x88, 0x85, 0x8A, 0x80, 0xEA, +0xA7, 0x84, 0x87, 0x88, 0xB7, 0x84, 0x97, 0x88, 0x80, 0x0D, 0xA0, 0x02, 0x00, 0xB7, 0x84, 0x8D, +0x80, 0xD4, 0xA7, 0x84, 0x8D, 0x7E, 0xD4, 0xA9, 0x00, 0x00, 0x80, 0x03, 0xA9, 0x03, 0x04, 0xA0, +0x02, 0x00, 0x97, 0x80, 0x20, 0xA9, 0x2F, 0x6B, 0xA0, 0x01, 0xB1, 0x88, 0x8D, 0x83, 0xD4, 0xA0, +0x04, 0xB1, 0x88, 0xCD, 0x12, 0xD0, 0xC2, 0x20, 0xD0, 0x0E, 0xA0, 0x02, 0xB1, 0x88, 0xF0, 0x05, +0xCD, 0x10, 0xD0, 0xD0, 0x03, 0xE2, 0x30, 0x60, 0x20, 0x00, 0x3D, 0xAD, 0x7E, 0xD4, 0x85, 0x84, +0xAD, 0x80, 0xD4, 0x85, 0x86, 0xA5, 0x85, 0xF0, 0x7C, 0xA0, 0x07, 0x84, 0x8C, 0xA0, 0x09, 0x84, +0x8D, 0x20, 0x0A, 0x3D, 0xD0, 0x05, 0x20, 0x0A, 0x3D, 0xF0, 0x0E, 0xA0, 0x02, 0xB7, 0x84, 0x48, +0xA7, 0x84, 0x85, 0x84, 0x68, 0x85, 0x86, 0x80, 0xDC, 0xAD, 0x10, 0xD0, 0xA0, 0x04, 0x97, 0x84, +0xE2, 0x30, 0x38, 0xA4, 0x8D, 0x98, 0x77, 0x84, 0x38, 0xE9, 0x04, 0xC2, 0x20, 0x29, 0xFF, 0x00, +0xA6, 0x8B, 0x9D, 0x84, 0xD4, 0xE8, 0xE8, 0x18, 0xA5, 0x84, 0x69, 0x04, 0x00, 0x9D, 0x84, 0xD4, +0xE8, 0xE8, 0xA5, 0x86, 0x9D, 0x84, 0xD4, 0xE8, 0xE8, 0x86, 0x8B, 0xAC, 0x82, 0xD4, 0xC8, 0x8C, +0x82, 0xD4, 0xC0, 0x04, 0xD0, 0xB5, 0xC2, 0x30, 0xA2, 0x84, 0x00, 0xA9, 0x07, 0x00, 0x20, 0x35, +0x1D, 0xE2, 0x10, 0x20, 0xC0, 0x3C, 0xC2, 0x30, 0xA0, 0x84, 0x00, 0xA9, 0x07, 0x00, 0x20, 0x5C, +0x1D, 0xE2, 0x10, 0x80, 0x96, 0xAE, 0x82, 0xD4, 0xF0, 0x03, 0x20, 0xC0, 0x3C, 0xE2, 0x30, 0x60, +0xA9, 0xFF, 0xFF, 0xA6, 0x8B, 0x9D, 0x84, 0xD4, 0xA0, 0x02, 0xB1, 0x88, 0x8D, 0x44, 0xD4, 0xA0, +0x04, 0xB1, 0x88, 0x8D, 0x46, 0xD4, 0xE2, 0x30, 0x9C, 0x43, 0xD4, 0xAD, 0x82, 0xD4, 0x09, 0x30, +0x8D, 0x82, 0xD4, 0xC2, 0x30, 0xA9, 0x84, 0xD4, 0x8D, 0x4A, 0xD4, 0xA9, 0xE1, 0x00, 0x8D, 0x4C, +0xD4, 0xA2, 0x3F, 0xD4, 0xA0, 0xE1, 0x00, 0x20, 0x58, 0x34, 0xE2, 0x10, 0x20, 0x00, 0x3D, 0x60, +0xA2, 0x0C, 0x86, 0x8B, 0xA2, 0x00, 0x8E, 0x82, 0xD4, 0x60, 0xA4, 0x8C, 0xB1, 0x88, 0xC9, 0x01, +0x3D, 0xF0, 0x31, 0xE2, 0x30, 0xAA, 0xA4, 0x8C, 0xE6, 0x8C, 0xB1, 0x88, 0xC9, 0x61, 0x90, 0x06, +0xC9, 0x7B, 0xB0, 0x02, 0x29, 0xDF, 0x85, 0x83, 0xA4, 0x8D, 0xE6, 0x8D, 0xB7, 0x84, 0xC9, 0x61, +0x90, 0x06, 0xC9, 0x7B, 0xB0, 0x02, 0x29, 0xDF, 0xC5, 0x83, 0xD0, 0x05, 0xCA, 0x10, 0xD7, 0xE2, +0x02, 0xC2, 0x20, 0x60, 0xC8, 0xC8, 0x84, 0x8C, 0xA4, 0x8D, 0xE2, 0x30, 0xB7, 0x84, 0x38, 0x65, +0x8D, 0x85, 0x8D, 0xE2, 0x02, 0xC2, 0x20, 0x60, 0x9C, 0x00, 0xD0, 0xA2, 0x00, 0xD0, 0xA0, 0x01, +0xD0, 0xA9, 0xA8, 0x04, 0x54, 0xE1, 0xE1, 0xE2, 0x30, 0xA0, 0x09, 0xB7, 0x80, 0x8D, 0x12, 0xD0, +0xC2, 0x30, 0xA9, 0x07, 0x00, 0x8D, 0x5F, 0xD4, 0xA9, 0x4E, 0xD4, 0x8D, 0x61, 0xD4, 0xA9, 0xE1, +0x00, 0x8D, 0x63, 0xD4, 0xA9, 0xFF, 0xFF, 0x8D, 0x6B, 0xD4, 0xA9, 0x02, 0x00, 0x8D, 0x8A, 0xD4, +0xA9, 0x82, 0xD4, 0x8D, 0x8C, 0xD4, 0xA9, 0xE1, 0x00, 0x8D, 0x8E, 0xD4, 0xA9, 0x01, 0x00, 0xA2, +0x67, 0x36, 0xA0, 0xFF, 0x00, 0x38, 0x20, 0x67, 0x2D, 0xA9, 0x02, 0x00, 0xA2, 0xA8, 0x36, 0xA0, +0xFF, 0x00, 0x38, 0x20, 0x67, 0x2D, 0xA2, 0xD2, 0x3D, 0xA0, 0xFF, 0x00, 0x20, 0x72, 0x1C, 0xA2, +0xDB, 0x3D, 0xA0, 0xFF, 0x00, 0x20, 0x72, 0x1C, 0xA2, 0xE4, 0x3D, 0xA0, 0xFF, 0x00, 0x20, 0x72, +0x1C, 0x60, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x31, 0x37, 0xFF, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x02, +0x6B, 0x39, 0xFF, 0x00, 0x00, 0x07, 0x00, 0x00, 0xFF, 0x01, 0xEE, 0x3D, 0xFF, 0x00, 0x06, 0x00, +0xF6, 0x3D, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x06, 0x01, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, +0x15, 0x00, 0x00, 0x00, 0x8A, 0x3E, 0xFF, 0x00, 0x88, 0x3F, 0xFF, 0x00, 0x3C, 0x40, 0xFF, 0x00, +0x55, 0x40, 0xFF, 0x00, 0x60, 0x40, 0xFF, 0x00, 0x29, 0x43, 0xFF, 0x00, 0xB6, 0x3E, 0xFF, 0x00, +0xB6, 0x3E, 0xFF, 0x00, 0xA4, 0x41, 0xFF, 0x00, 0x52, 0x41, 0xFF, 0x00, 0x6D, 0x40, 0xFF, 0x00, +0x1B, 0x42, 0xFF, 0x00, 0xF2, 0x41, 0xFF, 0x00, 0xF1, 0x43, 0xFF, 0x00, 0x5A, 0x42, 0xFF, 0x00, +0x3B, 0x43, 0xFF, 0x00, 0x47, 0x43, 0xFF, 0x00, 0x82, 0x43, 0xFF, 0x00, 0xB4, 0x43, 0xFF, 0x00, +0x66, 0x47, 0xFF, 0x00, 0x2B, 0xA2, 0x00, 0x00, 0x80, 0x01, 0x2B, 0x98, 0x9B, 0xAA, 0xE0, 0x00, +0x00, 0xF0, 0x1E, 0x08, 0x0B, 0x3B, 0x48, 0x2B, 0xA3, 0x08, 0x95, 0x08, 0xA3, 0x06, 0x95, 0x06, +0xA3, 0x04, 0x95, 0x04, 0x3B, 0x83, 0x04, 0x8A, 0x18, 0x63, 0x04, 0x69, 0x03, 0x00, 0x2B, 0x28, +0x1B, 0x98, 0xC9, 0x01, 0x00, 0x90, 0x03, 0x09, 0x00, 0x08, 0x6B, 0x08, 0x78, 0x20, 0x2F, 0x41, +0xA2, 0x1F, 0x00, 0xA9, 0x00, 0x00, 0xE2, 0x20, 0x9F, 0xB0, 0x1D, 0xE1, 0xCA, 0x10, 0xF9, 0xAF, +0xCA, 0x00, 0xE1, 0x0A, 0x0A, 0x0A, 0x0A, 0x8F, 0xB0, 0x1D, 0xE1, 0xAF, 0xD6, 0x00, 0xE1, 0xD0, +0x03, 0x20, 0xBD, 0x3E, 0x28, 0xC2, 0x20, 0xA0, 0x00, 0x00, 0x4C, 0x55, 0x3E, 0xA9, 0x20, 0x0F, +0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0xA9, 0xE1, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x3E, 0x8F, +0x3D, 0xC0, 0xE1, 0x20, 0x0C, 0x3F, 0xC2, 0x20, 0xA9, 0xF4, 0x3F, 0x8F, 0x49, 0x01, 0xE1, 0x8F, +0xBE, 0x1D, 0xE1, 0xE2, 0x20, 0xA9, 0xFF, 0x8F, 0x4B, 0x01, 0xE1, 0x8F, 0xC0, 0x1D, 0xE1, 0xA9, +0x5C, 0x8F, 0x48, 0x01, 0xE1, 0x8F, 0xBD, 0x1D, 0xE1, 0xC2, 0x20, 0xF4, 0x0B, 0x00, 0xF4, 0xFF, +0x00, 0xF4, 0xF4, 0x3F, 0xA2, 0x03, 0x10, 0x22, 0x00, 0x00, 0xE1, 0x60, 0x08, 0x78, 0xA9, 0x20, +0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0xA9, 0x20, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x00, +0x20, 0x7E, 0x3F, 0xA9, 0x00, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x00, 0x20, 0x7E, 0x3F, 0xA9, 0x40, +0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x00, 0x8F, 0xB1, 0x1D, 0xE1, 0x20, 0x7E, 0x3F, 0xA9, 0x80, 0x8F, +0x3E, 0xC0, 0xE1, 0xA9, 0x00, 0x20, 0x7E, 0x3F, 0xA9, 0xC0, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x00, +0x20, 0x7E, 0x3F, 0xA9, 0xA0, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x01, 0x20, 0x7E, 0x3F, 0xAF, 0xCA, +0x00, 0xE1, 0x29, 0x0F, 0x8F, 0x3C, 0xC0, 0xE1, 0xA9, 0xE0, 0x8F, 0x3E, 0xC0, 0xE1, 0xAF, 0x3D, +0xC0, 0xE1, 0xA2, 0x22, 0x00, 0xAF, 0x3D, 0xC0, 0xE1, 0xCA, 0xD0, 0xF9, 0x28, 0x60, 0xA2, 0x20, +0x00, 0x8F, 0x3D, 0xC0, 0xE1, 0xCA, 0xD0, 0xF9, 0x60, 0xAF, 0xD6, 0x00, 0xE1, 0x29, 0xFF, 0x00, +0xF0, 0x09, 0xA2, 0x10, 0x00, 0xA0, 0x02, 0x00, 0x4C, 0x5B, 0x3E, 0x20, 0x34, 0x40, 0xF0, 0x0B, +0xA2, 0x18, 0x00, 0xA0, 0x02, 0x00, 0x4C, 0x5B, 0x3E, 0xC2, 0x20, 0xA3, 0x07, 0x8F, 0xB7, 0x1D, +0xE1, 0xF4, 0x00, 0x00, 0xF4, 0x08, 0x00, 0xF4, 0x00, 0x00, 0x48, 0xA2, 0x01, 0x0D, 0x22, 0x00, +0x00, 0xE1, 0x0B, 0xAF, 0xB7, 0x1D, 0xE1, 0x5B, 0xA2, 0xFA, 0x00, 0xE2, 0x20, 0xA9, 0x00, 0x95, +0x00, 0xCA, 0x10, 0xFB, 0x2B, 0xA9, 0xFF, 0x8F, 0xB6, 0x1D, 0xE1, 0x8F, 0xC1, 0x1D, 0xE1, 0xC2, +0x20, 0xF4, 0xFF, 0x00, 0xF4, 0x16, 0x46, 0xA2, 0x08, 0x12, 0x22, 0x00, 0x00, 0xE1, 0xA0, 0x02, +0x00, 0x4C, 0x55, 0x3E, 0xC2, 0x30, 0xF4, 0xFF, 0x08, 0xF4, 0xFF, 0x00, 0xF4, 0x06, 0x40, 0xA2, +0x03, 0x15, 0x22, 0x00, 0x00, 0xE1, 0x2D, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, +0x0A, 0x00, 0x0A, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6E, 0x63, 0x6C, 0x61, 0x69, +0x6D, 0x65, 0x64, 0x20, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x72, +0x75, 0x70, 0x74, 0x20, 0xE2, 0x20, 0xAF, 0xB6, 0x1D, 0xE1, 0xC2, 0x20, 0x60, 0x08, 0x78, 0xA9, +0x00, 0x00, 0xF4, 0x00, 0x00, 0xF4, 0x08, 0x00, 0xF4, 0x00, 0x00, 0x48, 0xA2, 0x01, 0x0D, 0x22, +0x00, 0x00, 0xE1, 0x82, 0x3A, 0xFE, 0xA9, 0x00, 0x02, 0x83, 0x07, 0xA0, 0x00, 0x00, 0x4C, 0x55, +0x3E, 0xE2, 0x20, 0x20, 0x0C, 0x3F, 0xC2, 0x20, 0xA0, 0x00, 0x00, 0x4C, 0x55, 0x3E, 0xA9, 0x7B, +0x40, 0x83, 0x07, 0xA9, 0xFF, 0x00, 0x83, 0x09, 0x4C, 0xB5, 0x3E, 0xA3, 0x40, 0xFF, 0x00, 0xB4, +0x40, 0xFF, 0x00, 0xA8, 0x40, 0xFF, 0x00, 0xB9, 0x40, 0xFF, 0x00, 0xAF, 0x40, 0xFF, 0x00, 0xBC, +0x40, 0xFF, 0x00, 0xF0, 0x40, 0xFF, 0x00, 0x00, 0x41, 0xFF, 0x00, 0x20, 0x41, 0xFF, 0x00, 0xE1, +0x40, 0xFF, 0x00, 0x20, 0xCF, 0x40, 0x80, 0x03, 0x20, 0xC1, 0x40, 0xAF, 0x3D, 0xC0, 0xE1, 0xAF, +0x3D, 0xC0, 0xE1, 0x6B, 0x20, 0xCF, 0x40, 0x80, 0x03, 0x20, 0xC1, 0x40, 0x8F, 0x3D, 0xC0, 0xE1, +0x6B, 0x48, 0xC2, 0x20, 0x8A, 0x8F, 0x3E, 0xC0, 0xE1, 0xE2, 0x20, 0xA9, 0x60, 0x80, 0x08, 0x48, +0x8A, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x20, 0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0x68, +0x60, 0xAF, 0x3C, 0xC0, 0xE1, 0x29, 0xD0, 0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0x6B, +0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E, +0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C, 0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E, +0x01, 0x01, 0x09, 0x09, 0x05, 0x05, 0x0D, 0x0D, 0x03, 0x03, 0x0B, 0x0B, 0x07, 0x07, 0x0F, 0x0F, +0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xE2, +0x20, 0xC2, 0x10, 0xA9, 0x00, 0x8F, 0x3E, 0xC0, 0xE1, 0x8F, 0x3F, 0xC0, 0xE1, 0xA9, 0x60, 0x0F, +0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0xA9, 0x80, 0x8F, 0x3D, 0xC0, 0xE1, 0xE8, 0xD0, 0xF9, +0xC2, 0x30, 0x60, 0xAF, 0xD6, 0x00, 0xE1, 0x29, 0xFF, 0x00, 0xF0, 0x09, 0xA2, 0x10, 0x00, 0xA0, +0x08, 0x00, 0x4C, 0x5B, 0x3E, 0x0B, 0xA3, 0x09, 0xAA, 0x3A, 0x18, 0x63, 0x0B, 0x90, 0x09, 0xA2, +0x11, 0x00, 0xA0, 0x08, 0x00, 0x4C, 0x5A, 0x3E, 0xA0, 0x00, 0x00, 0xA3, 0x0B, 0x8F, 0x3E, 0xC0, +0xE1, 0x3B, 0x5B, 0xE2, 0x20, 0xA9, 0x60, 0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0xAF, +0x3D, 0xC0, 0xE1, 0xAF, 0x3D, 0xC0, 0xE1, 0x97, 0x0D, 0xC8, 0xCA, 0xD0, 0xF6, 0xC2, 0x20, 0xA0, +0x08, 0x00, 0x4C, 0x54, 0x3E, 0xAF, 0xD6, 0x00, 0xE1, 0x29, 0xFF, 0x00, 0xF0, 0x09, 0xA9, 0x10, +0x00, 0xA0, 0x08, 0x00, 0x4C, 0x5B, 0x3E, 0x0B, 0xA3, 0x09, 0xAA, 0x3A, 0x18, 0x63, 0x0B, 0x90, +0x09, 0xA2, 0x11, 0x00, 0xA0, 0x08, 0x00, 0x4C, 0x5A, 0x3E, 0xA0, 0x00, 0x00, 0xA3, 0x0B, 0x8F, +0x3E, 0xC0, 0xE1, 0x3B, 0x5B, 0xE2, 0x20, 0xA9, 0x60, 0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, +0xE1, 0xB7, 0x0D, 0x8F, 0x3D, 0xC0, 0xE1, 0xC8, 0xCA, 0xD0, 0xF6, 0xC2, 0x20, 0xA0, 0x08, 0x00, +0x4C, 0x54, 0x3E, 0x20, 0x39, 0x42, 0xA3, 0x09, 0xB0, 0x10, 0x8F, 0x3D, 0xC0, 0xE1, 0x8F, 0x3D, +0xC0, 0xE1, 0xC2, 0x20, 0xA0, 0x04, 0x00, 0x4C, 0x55, 0x3E, 0x8F, 0xB0, 0x1D, 0xE1, 0x4A, 0x4A, +0x4A, 0x4A, 0x8F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0x80, 0xE6, 0x20, 0x39, 0x42, 0xB0, +0x0A, 0xAF, 0x3D, 0xC0, 0xE1, 0xAF, 0x3D, 0xC0, 0xE1, 0x80, 0x04, 0xAF, 0xB0, 0x1D, 0xE1, 0x83, +0x09, 0xC2, 0x20, 0xA0, 0x02, 0x00, 0x4C, 0x55, 0x3E, 0xE2, 0x20, 0xA3, 0x09, 0xC9, 0x0F, 0xB0, +0x19, 0xEB, 0xA9, 0x00, 0xEB, 0xAA, 0xBF, 0xF0, 0x40, 0xFF, 0x69, 0x40, 0x8F, 0x3E, 0xC0, 0xE1, +0xA9, 0x20, 0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0x60, 0x0B, 0x8B, 0x08, 0x78, 0x48, +0x2B, 0xE2, 0x20, 0xA9, 0xE1, 0x48, 0xAB, 0xAF, 0x3C, 0xC0, 0xE1, 0x29, 0xF0, 0x0F, 0xCA, 0x00, +0xE1, 0x48, 0x29, 0x0F, 0x8F, 0x3C, 0xC0, 0xE1, 0xC2, 0x20, 0xAF, 0xB2, 0x1D, 0xE1, 0x23, 0x0C, +0x8F, 0xB4, 0x1D, 0xE1, 0x4F, 0xB2, 0x1D, 0xE1, 0x8F, 0xB2, 0x1D, 0xE1, 0xA2, 0x10, 0x00, 0xCA, +0xC2, 0x20, 0xAF, 0xB4, 0x1D, 0xE1, 0x0A, 0x8F, 0xB4, 0x1D, 0xE1, 0xB0, 0x04, 0xF0, 0x7C, 0x80, +0xEE, 0xE2, 0x20, 0xBF, 0xF0, 0x40, 0xFF, 0x48, 0x18, 0x69, 0x00, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, +0x00, 0x8F, 0x3D, 0xC0, 0xE1, 0x8F, 0x3D, 0xC0, 0xE1, 0xA3, 0x01, 0x18, 0x65, 0x20, 0x8F, 0x3E, +0xC0, 0xE1, 0xA9, 0x00, 0x8F, 0x3D, 0xC0, 0xE1, 0x8F, 0x3D, 0xC0, 0xE1, 0xA9, 0x14, 0x3A, 0xD0, +0xFD, 0xA3, 0x01, 0x18, 0x69, 0xA0, 0x8F, 0x3E, 0xC0, 0xE1, 0xAF, 0x3D, 0xC0, 0xE1, 0xAF, 0x3D, +0xC0, 0xE1, 0x29, 0xF7, 0x09, 0x01, 0x8F, 0x3D, 0xC0, 0xE1, 0xEE, 0x3E, 0xC0, 0x8F, 0x3D, 0xC0, +0xE1, 0x68, 0x69, 0x40, 0x8F, 0x3E, 0xC0, 0xE1, 0xA9, 0x00, 0x8F, 0x3D, 0xC0, 0xE1, 0xEE, 0x3E, +0xC0, 0x8F, 0x3D, 0xC0, 0xE1, 0xAF, 0xB6, 0x1D, 0xE1, 0xF0, 0x84, 0xDA, 0xBF, 0x20, 0x41, 0xFF, +0xAA, 0xA9, 0x00, 0x95, 0x00, 0x95, 0x01, 0xFA, 0x82, 0x74, 0xFF, 0xE2, 0x20, 0x68, 0x8F, 0x3C, +0xC0, 0xE1, 0x28, 0xAB, 0xA0, 0x02, 0x00, 0x4C, 0x54, 0x3E, 0xE2, 0x20, 0xAF, 0xC1, 0x1D, 0xE1, +0x83, 0x07, 0x83, 0x08, 0xC2, 0x20, 0xA0, 0x00, 0x00, 0x4C, 0x55, 0x3E, 0xAF, 0xB2, 0x1D, 0xE1, +0x83, 0x07, 0xA0, 0x00, 0x00, 0x4C, 0x55, 0x3E, 0xC9, 0x00, 0x00, 0xF0, 0x2D, 0x0B, 0x48, 0x2B, +0xA3, 0x09, 0xC9, 0x0F, 0x00, 0x90, 0x09, 0xA2, 0x13, 0x00, 0xA0, 0x02, 0x00, 0x4C, 0x5A, 0x3E, +0xAA, 0xE2, 0x30, 0xA9, 0xFF, 0xEB, 0xBF, 0x20, 0x41, 0xFF, 0xAA, 0xC2, 0x30, 0xB5, 0x00, 0xEB, +0xC2, 0x30, 0x83, 0x0B, 0xA0, 0x02, 0x00, 0x4C, 0x54, 0x3E, 0xA2, 0x12, 0x00, 0xA0, 0x02, 0x00, +0x4C, 0x5B, 0x3E, 0xAF, 0xB6, 0x1D, 0xE1, 0x29, 0xFF, 0x00, 0xD0, 0x09, 0xA2, 0x12, 0x00, 0xA0, +0x04, 0x00, 0x4C, 0x5B, 0x3E, 0xF4, 0x0B, 0x00, 0xA3, 0x0B, 0x48, 0xA3, 0x0B, 0x48, 0xA2, 0x03, +0x10, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x20, 0xA9, 0xFF, 0x8F, 0xB9, 0x1D, 0xE1, 0xC2, 0x20, 0xA0, +0x04, 0x00, 0x4C, 0x55, 0x3E, 0xAF, 0xB6, 0x1D, 0xE1, 0x29, 0xFF, 0x00, 0xD0, 0x09, 0xA2, 0x12, +0x00, 0xA0, 0x04, 0x00, 0x4C, 0x5B, 0x3E, 0xAF, 0xBE, 0x1D, 0xE1, 0x83, 0x0B, 0xAF, 0xC0, 0x1D, +0xE1, 0x29, 0xFF, 0x00, 0x83, 0x0D, 0xA3, 0x07, 0x8F, 0xBE, 0x1D, 0xE1, 0xA3, 0x08, 0x8F, 0xBF, +0x1D, 0xE1, 0x08, 0xE2, 0x20, 0xA9, 0x5C, 0x8F, 0xBD, 0x1D, 0xE1, 0x28, 0xA0, 0x04, 0x00, 0x4C, +0x55, 0x3E, 0x0B, 0x08, 0x78, 0x20, 0x56, 0x44, 0xB0, 0x54, 0xDA, 0x20, 0x25, 0x45, 0xFA, 0xE2, +0x30, 0xDA, 0xB5, 0x01, 0x29, 0x0F, 0xAA, 0xBF, 0xF0, 0x40, 0xFF, 0x18, 0x69, 0xA0, 0x8F, 0x3E, +0xC0, 0xE1, 0xAF, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0xFA, 0xB5, 0x01, 0x29, 0xF0, 0x09, +0x0E, 0x24, 0xFA, 0xF0, 0x02, 0x29, 0xFA, 0x8F, 0x3D, 0xC0, 0xE1, 0xC2, 0x30, 0xB5, 0x01, 0x29, +0x0F, 0x00, 0xA8, 0xA9, 0x00, 0x00, 0x38, 0x2A, 0x18, 0x88, 0x10, 0xFB, 0x0F, 0xB2, 0x1D, 0xE1, +0x8F, 0xB2, 0x1D, 0xE1, 0xA2, 0x00, 0x00, 0x28, 0xA0, 0x06, 0x00, 0x4C, 0x54, 0x3E, 0xAA, 0x28, +0xA0, 0x06, 0x00, 0x4C, 0x5A, 0x3E, 0xE2, 0x30, 0xA3, 0x11, 0x29, 0x0F, 0xC9, 0x0F, 0x90, 0x03, +0x82, 0x96, 0x00, 0xAA, 0xBF, 0x20, 0x41, 0xFF, 0xAA, 0xAF, 0xB6, 0x1D, 0xE1, 0xD0, 0x03, 0x82, +0x79, 0x00, 0xAF, 0xB8, 0x1D, 0xE1, 0x48, 0xAF, 0xB7, 0x1D, 0xE1, 0x48, 0x2B, 0xB5, 0x00, 0x29, +0x0F, 0xF0, 0x03, 0x82, 0x6C, 0x00, 0x0F, 0xB9, 0x1D, 0xE1, 0xD0, 0x03, 0x82, 0x78, 0x00, 0xC2, +0x20, 0xA3, 0x0C, 0x85, 0xF3, 0xA3, 0x0D, 0x85, 0xF4, 0xA0, 0x0C, 0xB7, 0xF3, 0x95, 0x07, 0xC8, +0xB7, 0xF3, 0x95, 0x08, 0xC8, 0xC8, 0xC8, 0xE2, 0x20, 0xB7, 0xF3, 0x95, 0x0E, 0xC2, 0x20, 0xA3, +0x10, 0x29, 0xFF, 0x00, 0xC9, 0x01, 0x00, 0xD0, 0x47, 0xA3, 0x10, 0x95, 0x00, 0xA0, 0x00, 0xB7, +0xF3, 0x95, 0x02, 0xC8, 0xB7, 0xF3, 0x95, 0x03, 0xC8, 0xC8, 0xC8, 0xB7, 0xF3, 0x95, 0x05, 0xA0, +0x08, 0xB7, 0xF3, 0x95, 0x0A, 0xE2, 0x30, 0xA0, 0x0A, 0xB7, 0xF3, 0xC2, 0x30, 0x29, 0x07, 0x00, +0xDA, 0x0A, 0xAA, 0xBF, 0x15, 0x45, 0xFF, 0xFA, 0x95, 0x0C, 0x60, 0xC2, 0x20, 0xA9, 0x12, 0x00, +0x38, 0x60, 0xC2, 0x20, 0xA9, 0x15, 0x00, 0x38, 0x60, 0xC2, 0x20, 0xA9, 0x13, 0x00, 0x38, 0x60, +0xC2, 0x20, 0xA9, 0x14, 0x00, 0x38, 0x60, 0xC2, 0x20, 0xA9, 0x17, 0x00, 0x38, 0x60, 0xC2, 0x20, +0xA9, 0x16, 0x00, 0x38, 0x60, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, +0x20, 0x00, 0x40, 0x00, 0x80, 0xC2, 0x30, 0xA0, 0x00, 0x00, 0x98, 0xE2, 0x20, 0xDA, 0xB5, 0x01, +0x29, 0x0F, 0xAA, 0xBF, 0xF0, 0x40, 0xFF, 0xFA, 0x48, 0x85, 0xF6, 0xA9, 0x03, 0x95, 0x0F, 0x20, +0xBA, 0x46, 0xE2, 0x20, 0x68, 0x1A, 0x85, 0xF6, 0xB5, 0x00, 0x10, 0x32, 0xC2, 0x20, 0xB5, 0x07, +0x15, 0x08, 0xD0, 0x0D, 0xC6, 0xF6, 0x20, 0x84, 0x45, 0xE2, 0x20, 0xA9, 0xFF, 0x85, 0xFA, 0x80, +0x22, 0x20, 0x7F, 0x46, 0xE2, 0x20, 0x34, 0x00, 0x10, 0x12, 0x20, 0x84, 0x45, 0xC2, 0x20, 0xB5, +0x07, 0x15, 0x08, 0xD0, 0x07, 0xE2, 0x20, 0xA9, 0x03, 0x20, 0x4D, 0x47, 0x80, 0x05, 0x20, 0xBA, +0x46, 0x64, 0xFA, 0x60, 0x08, 0x8B, 0x86, 0xF7, 0xE2, 0x30, 0xA9, 0xE1, 0x48, 0xAB, 0xA9, 0x00, +0x0F, 0xCA, 0x00, 0xE1, 0x8D, 0x3C, 0xC0, 0xA0, 0x0A, 0xB7, 0xF3, 0x29, 0x07, 0x0A, 0x0A, 0x0A, +0x17, 0xF3, 0xEB, 0xA5, 0xF6, 0x18, 0x69, 0xC0, 0xAA, 0xEB, 0x8E, 0x3E, 0xC0, 0x8D, 0x3D, 0xC0, +0xA9, 0x00, 0x18, 0x65, 0xF6, 0xAA, 0xA0, 0x06, 0xB7, 0xF3, 0x8E, 0x3E, 0xC0, 0x8D, 0x3D, 0xC0, +0xA9, 0x20, 0x18, 0x65, 0xF6, 0xAA, 0xA0, 0x07, 0xB7, 0xF3, 0x8E, 0x3E, 0xC0, 0x8D, 0x3D, 0xC0, +0xA9, 0x40, 0x18, 0x65, 0xF6, 0xAA, 0xA0, 0x10, 0xB7, 0xF3, 0xF0, 0x06, 0x8E, 0x3E, 0xC0, 0x8D, +0x3D, 0xC0, 0xA9, 0x80, 0x18, 0x65, 0xF6, 0xA8, 0xA6, 0xF7, 0xB5, 0x0B, 0x48, 0x98, 0x6A, 0x68, +0x90, 0x03, 0x18, 0x75, 0x0D, 0xBB, 0x8E, 0x3E, 0xC0, 0x8D, 0x3D, 0xC0, 0xA9, 0xA0, 0x18, 0x65, +0xF6, 0x48, 0xA6, 0xF7, 0xB5, 0x01, 0x29, 0xF0, 0x09, 0x0F, 0xFA, 0x8E, 0x3E, 0xC0, 0x8D, 0x3D, +0xC0, 0xA6, 0xF7, 0xAB, 0x28, 0x60, 0x0B, 0xAF, 0xB8, 0x1D, 0xE1, 0x48, 0xAF, 0xB7, 0x1D, 0xE1, +0x48, 0x2B, 0xAF, 0xCC, 0x00, 0xE1, 0xE2, 0x30, 0x18, 0x6A, 0x29, 0x1F, 0x85, 0xF6, 0xC9, 0x1E, +0x90, 0x06, 0x22, 0x65, 0x46, 0xFF, 0x80, 0x10, 0xAA, 0xBF, 0x00, 0x41, 0xFF, 0xAA, 0xBF, 0x20, +0x41, 0xFF, 0xAA, 0x08, 0x20, 0x69, 0x46, 0x28, 0xE2, 0x20, 0xAF, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, +0xC0, 0xE1, 0xA9, 0xE0, 0x8F, 0x3E, 0xC0, 0xE1, 0xAF, 0x3D, 0xC0, 0xE1, 0xAF, 0x3D, 0xC0, 0xE1, +0x10, 0xC4, 0x2B, 0x18, 0x6B, 0x5C, 0x48, 0x01, 0xE1, 0xB5, 0x00, 0xF0, 0x47, 0x29, 0x0F, 0xC9, +0x01, 0xD0, 0x42, 0xB5, 0x00, 0x10, 0x43, 0xC2, 0x20, 0xB5, 0x07, 0x15, 0x08, 0xF0, 0x2E, 0xB5, +0x00, 0x29, 0x7F, 0xFF, 0x48, 0xB5, 0x09, 0x29, 0xFF, 0x00, 0x48, 0xB5, 0x07, 0x48, 0xA9, 0x00, +0x00, 0x95, 0x00, 0x3B, 0x38, 0xE9, 0x09, 0x00, 0x1B, 0x20, 0x56, 0x44, 0x3B, 0x18, 0x69, 0x0F, +0x00, 0x1B, 0xE2, 0x20, 0xA9, 0x03, 0x95, 0x0F, 0x20, 0xBA, 0x46, 0x80, 0x07, 0xE2, 0x20, 0xA9, +0x01, 0x20, 0x4D, 0x47, 0x60, 0x22, 0xBD, 0x1D, 0xE1, 0x60, 0xA9, 0x60, 0x0F, 0xCA, 0x00, 0xE1, +0x8F, 0x3C, 0xC0, 0xE1, 0xA5, 0xF6, 0xC2, 0x30, 0x6A, 0xB5, 0x0A, 0x90, 0x03, 0x18, 0x75, 0x0C, +0x8F, 0x3E, 0xC0, 0xE1, 0x08, 0xB5, 0x02, 0x85, 0xF0, 0xB5, 0x03, 0x85, 0xF1, 0xB5, 0x0C, 0xEB, +0x85, 0xF8, 0xA0, 0x00, 0x00, 0xB5, 0x05, 0xF0, 0x21, 0xE2, 0x30, 0xB7, 0xF0, 0x8F, 0x3D, 0xC0, +0xE1, 0xC8, 0xD0, 0xF7, 0xC2, 0x20, 0xE6, 0xF1, 0xD6, 0x05, 0xF0, 0x0E, 0xC6, 0xF8, 0xD0, 0xE9, +0xA5, 0xF0, 0x95, 0x02, 0xA5, 0xF1, 0x95, 0x03, 0x80, 0x2B, 0xA5, 0xF8, 0x3A, 0xF0, 0x0D, 0xE2, +0x30, 0xA9, 0x00, 0xA0, 0x40, 0x8F, 0x3D, 0xC0, 0xE1, 0x88, 0xD0, 0xF9, 0xE2, 0x20, 0xA9, 0x80, +0x15, 0x00, 0x95, 0x00, 0xC2, 0x20, 0xB5, 0x07, 0x15, 0x08, 0xD0, 0x09, 0xE2, 0x20, 0xA9, 0x03, +0x20, 0x4D, 0x47, 0x80, 0x16, 0xE2, 0x20, 0xA5, 0xF6, 0x29, 0x01, 0x18, 0xD0, 0x01, 0x38, 0x2A, +0x35, 0x0F, 0xF0, 0x07, 0x55, 0x0F, 0x95, 0x0F, 0x20, 0x84, 0x45, 0x28, 0x60, 0x48, 0xA9, 0x00, +0x0F, 0xCA, 0x00, 0xE1, 0x8F, 0x3C, 0xC0, 0xE1, 0x18, 0xA5, 0xF6, 0x69, 0xA0, 0x8F, 0x3E, 0xC0, +0xE1, 0x68, 0x8F, 0x3D, 0xC0, 0xE1, 0x60, 0x08, 0x78, 0xA3, 0x08, 0xC9, 0x0F, 0x00, 0xB0, 0x43, +0xAA, 0xBF, 0xF0, 0x40, 0xFF, 0x29, 0xFF, 0x00, 0x69, 0xA0, 0x00, 0xAA, 0xA8, 0xE2, 0x20, 0x22, +0xA3, 0x40, 0xFF, 0x83, 0x0A, 0x22, 0xAF, 0x40, 0xFF, 0x29, 0x01, 0x23, 0x0A, 0xF0, 0x19, 0xA2, +0x08, 0x00, 0xCA, 0xD0, 0xFD, 0xBB, 0x22, 0xA3, 0x40, 0xFF, 0x83, 0x0A, 0x22, 0xAF, 0x40, 0xFF, +0x29, 0x01, 0x23, 0x0A, 0xF0, 0x02, 0xA9, 0xFF, 0x83, 0x0A, 0x83, 0x0B, 0x28, 0xA0, 0x02, 0x00, +0x4C, 0x55, 0x3E, 0x28, 0xA2, 0x13, 0x00, 0xA0, 0x02, 0x00, 0x4C, 0x5B, 0x3E, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x4C, 0x0C, 0x48, 0x4C, 0x65, 0x49, 0x4C, 0x52, 0x4F, 0x4C, 0xC8, 0x52, 0x5A, 0x48, 0x8E, 0xF8, +0x07, 0x20, 0x3C, 0x4F, 0xBF, 0x82, 0x00, 0xE1, 0x08, 0xA9, 0xFF, 0x70, 0x01, 0x1A, 0x9F, 0x82, +0x00, 0xE1, 0x28, 0x50, 0x1C, 0xD0, 0x03, 0x20, 0x28, 0x54, 0xE4, 0x37, 0xD0, 0x0B, 0xA9, 0x07, +0xC5, 0x36, 0xF0, 0x05, 0x85, 0x36, 0x18, 0x80, 0x08, 0xE4, 0x39, 0xD0, 0xF9, 0xA9, 0x05, 0x85, +0x38, 0xB0, 0x03, 0x4C, 0xC2, 0x48, 0x68, 0x2C, 0x1F, 0xC0, 0x30, 0x04, 0xA4, 0x24, 0x91, 0x28, +0xEB, 0xAD, 0x15, 0xC0, 0x48, 0x8D, 0x07, 0xC0, 0xEB, 0x80, 0x2D, 0x3C, 0xB8, 0x04, 0x50, 0x1C, +0x20, 0xEB, 0x49, 0x80, 0x23, 0x68, 0x20, 0xFC, 0xCE, 0x10, 0x20, 0x20, 0x7D, 0x4B, 0xB0, 0xEB, +0x29, 0x5F, 0xC9, 0x51, 0xF0, 0x04, 0xC9, 0x52, 0xD0, 0x0E, 0xA9, 0x98, 0x7A, 0x30, 0x03, 0x8D, +0x06, 0xC0, 0x7A, 0x6B, 0x18, 0x20, 0x1D, 0x4E, 0x20, 0xC9, 0xCE, 0x48, 0x20, 0xE6, 0x4A, 0xB0, +0x09, 0xBD, 0x38, 0x07, 0x29, 0x10, 0xF0, 0xCD, 0x80, 0xF2, 0xA8, 0x68, 0x5A, 0x20, 0xE7, 0xCD, +0x68, 0xBC, 0x38, 0x04, 0xF0, 0x12, 0x09, 0x80, 0xC9, 0x91, 0xF0, 0xDC, 0xC9, 0xFF, 0xF0, 0xD8, +0xC9, 0x92, 0xF0, 0xD0, 0xC9, 0x94, 0xF0, 0xCD, 0x3C, 0xB8, 0x04, 0x50, 0xBF, 0x20, 0x94, 0xF8, +0x80, 0xC6, 0xBD, 0x38, 0x07, 0x0A, 0x7A, 0x5A, 0xBD, 0x38, 0x05, 0x89, 0x80, 0xD0, 0x61, 0xBD, +0x38, 0x06, 0x08, 0xA5, 0x24, 0x28, 0xB0, 0x23, 0xF0, 0x08, 0xDD, 0x38, 0x06, 0x90, 0x03, 0xBD, +0xB8, 0x06, 0xDD, 0xB8, 0x06, 0xB0, 0x10, 0xC9, 0x08, 0xF0, 0x04, 0xC9, 0x10, 0xD0, 0x12, 0x09, +0xF0, 0x3D, 0xB8, 0x06, 0x18, 0x65, 0x24, 0x85, 0x24, 0x80, 0x06, 0xC5, 0x21, 0x90, 0x02, 0x64, +0x24, 0xBD, 0xB8, 0x05, 0x89, 0x08, 0xF0, 0x15, 0xBD, 0x38, 0x06, 0xF0, 0x10, 0xBD, 0xB8, 0x06, +0xDD, 0x38, 0x06, 0x90, 0x08, 0xA9, 0x1A, 0xC0, 0x80, 0x6A, 0x20, 0x04, 0x4A, 0x7A, 0x5A, 0xBD, +0xB8, 0x06, 0xC5, 0x24, 0xB0, 0x0A, 0xA9, 0x40, 0xC0, 0x80, 0x6A, 0x20, 0x04, 0x4A, 0x80, 0xD1, +0x98, 0x20, 0xE6, 0x49, 0x3C, 0x38, 0x07, 0x30, 0x29, 0xBD, 0x38, 0x06, 0xF0, 0x10, 0x38, 0xBD, +0xB8, 0x06, 0xFD, 0x38, 0x06, 0xC9, 0xF8, 0x90, 0x05, 0x18, 0x65, 0x21, 0x80, 0x0A, 0xBD, 0x38, +0x05, 0x29, 0x08, 0xF0, 0x03, 0xBD, 0xB8, 0x06, 0x85, 0x24, 0x2C, 0x1F, 0xC0, 0x10, 0x03, 0x8D, +0x7B, 0x05, 0x68, 0x7A, 0x6B, 0x20, 0x40, 0x4F, 0x8E, 0xF8, 0x07, 0xEB, 0x98, 0x48, 0x29, 0xF0, +0xA8, 0x68, 0x29, 0x07, 0x5A, 0xEB, 0x48, 0xEB, 0x3A, 0xD0, 0x3F, 0x68, 0x48, 0x4A, 0xD0, 0x60, +0xBD, 0xB8, 0x05, 0x89, 0x40, 0xF0, 0x16, 0x8B, 0xB0, 0x06, 0x38, 0x20, 0xB1, 0x53, 0x80, 0x04, +0x18, 0x20, 0x9B, 0x53, 0xE2, 0x30, 0x38, 0xD0, 0x01, 0x18, 0xAB, 0x80, 0x31, 0xB0, 0x0C, 0xBD, +0x38, 0x07, 0x89, 0x02, 0xD0, 0x28, 0x20, 0xB2, 0x4A, 0x80, 0x23, 0x89, 0x10, 0xD0, 0x1F, 0x20, +0x7A, 0xC1, 0x4A, 0x90, 0x19, 0x20, 0xDA, 0x55, 0x80, 0x14, 0x3A, 0xD0, 0x07, 0x68, 0x48, 0x20, +0xE6, 0x49, 0x80, 0x0A, 0x3A, 0xD0, 0x0C, 0x68, 0x20, 0xE6, 0x4A, 0x90, 0xFB, 0x48, 0x68, 0x7A, +0xA2, 0x00, 0x6B, 0x20, 0x28, 0x54, 0xBD, 0x38, 0x07, 0x29, 0xBF, 0x9D, 0x38, 0x07, 0x80, 0xEE, +0xA2, 0x40, 0x68, 0x7A, 0x18, 0x6B, 0x20, 0x7D, 0x4B, 0x90, 0x4F, 0x3C, 0x38, 0x07, 0x10, 0x14, +0xC9, 0x91, 0xF0, 0x10, 0xAC, 0x15, 0xC0, 0x5A, 0x8D, 0x07, 0xC0, 0x20, 0x97, 0xF8, 0x7A, 0x30, +0x03, 0x8D, 0x06, 0xC0, 0xA8, 0xBD, 0xB8, 0x05, 0x89, 0x40, 0x08, 0x98, 0x28, 0xF0, 0x43, 0x08, +0x78, 0x48, 0x8B, 0x38, 0x20, 0x9B, 0x53, 0xE2, 0x30, 0xD0, 0x20, 0xAB, 0xBD, 0xB8, 0x05, 0x89, +0x02, 0xD0, 0x19, 0xBD, 0x38, 0x07, 0x89, 0x02, 0xD0, 0x12, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0xB9, +0xFD, 0xBF, 0x89, 0x04, 0xF0, 0x06, 0x68, 0x28, 0x80, 0x1F, 0x60, 0xAB, 0x68, 0x38, 0x20, 0xF6, +0x52, 0x90, 0x04, 0x28, 0x08, 0x80, 0xF6, 0x28, 0x48, 0x89, 0x60, 0xF0, 0x03, 0xFE, 0xB8, 0x06, +0x80, 0x49, 0x48, 0x20, 0xB2, 0x4A, 0x90, 0xFB, 0x68, 0x48, 0x89, 0x60, 0xF0, 0x03, 0xFE, 0xB8, +0x06, 0xBD, 0xB8, 0x05, 0x89, 0x40, 0xD0, 0x1C, 0xBF, 0xD5, 0x14, 0xE1, 0x30, 0x16, 0xBD, 0x38, +0x07, 0x89, 0x20, 0xF0, 0x0F, 0x20, 0x16, 0x4B, 0x90, 0x03, 0x20, 0xEB, 0x55, 0xBD, 0x38, 0x07, +0x29, 0x02, 0xD0, 0xCF, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0xBF, 0xD5, 0x14, 0xE1, 0x2A, 0x68, 0x48, +0x90, 0x06, 0x22, 0x2A, 0x10, 0xE1, 0x80, 0x03, 0x99, 0xFF, 0xBF, 0x3C, 0x38, 0x07, 0x49, 0x0D, +0x0A, 0xD0, 0x0D, 0x50, 0x06, 0xA9, 0x14, 0x6A, 0x20, 0x04, 0x4A, 0x64, 0x24, 0x9E, 0xB8, 0x06, +0x68, 0x60, 0x20, 0x7A, 0xC1, 0x18, 0x49, 0x2C, 0xEB, 0xBD, 0x38, 0x07, 0x89, 0x04, 0xF0, 0x06, +0xEB, 0x89, 0x20, 0xD0, 0x14, 0xEB, 0xBD, 0xB8, 0x05, 0x89, 0x20, 0xF0, 0x06, 0xEB, 0x89, 0x08, +0xD0, 0x07, 0xEB, 0xEB, 0x89, 0x04, 0xD0, 0x0D, 0x38, 0xBD, 0xB8, 0x05, 0x29, 0xFD, 0xB0, 0x02, +0x09, 0x02, 0x9D, 0xB8, 0x05, 0x60, 0xBD, 0xB8, 0x05, 0x89, 0x40, 0xF0, 0x16, 0x18, 0x20, 0x40, +0x53, 0x90, 0x2E, 0x50, 0x2C, 0x48, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0x18, 0x20, 0x2A, 0x52, 0x68, +0x38, 0x80, 0x1E, 0xBD, 0xB8, 0x05, 0x89, 0x10, 0xF0, 0x0C, 0x29, 0xEF, 0x9D, 0xB8, 0x05, 0xBF, +0xD7, 0x14, 0xE1, 0x38, 0x80, 0x0B, 0x20, 0x7A, 0xC1, 0x29, 0x01, 0x18, 0xF0, 0x03, 0x20, 0x24, +0x4B, 0x60, 0x00, 0x80, 0xBF, 0xD5, 0x14, 0xE1, 0x10, 0x06, 0x22, 0x2E, 0x10, 0xE1, 0x80, 0x08, +0x20, 0x61, 0x4B, 0x90, 0x2B, 0xB9, 0xFF, 0xBF, 0x48, 0x09, 0x80, 0xA8, 0xBD, 0x38, 0x07, 0x89, +0x08, 0xD0, 0x04, 0xC0, 0x8A, 0xF0, 0x12, 0x89, 0x20, 0xF0, 0x10, 0xC0, 0x91, 0xD0, 0x04, 0x29, +0xFD, 0x80, 0x06, 0xC0, 0x93, 0xD0, 0x04, 0x09, 0x02, 0x18, 0xB0, 0x38, 0x9D, 0x38, 0x07, 0x68, +0x60, 0x38, 0xBD, 0x38, 0x05, 0x29, 0x02, 0xD0, 0x13, 0xA9, 0x01, 0x20, 0xCE, 0x55, 0x29, 0x50, +0xF0, 0x0A, 0x1D, 0x38, 0x05, 0x9D, 0x38, 0x05, 0xB9, 0xFF, 0xBF, 0x18, 0x60, 0x48, 0x3C, 0xB8, +0x04, 0x30, 0x1F, 0xBC, 0x38, 0x05, 0x30, 0x17, 0x5D, 0x38, 0x04, 0x0A, 0xD0, 0x11, 0xAF, 0x34, +0x01, 0xE1, 0x8F, 0x8B, 0x15, 0xE1, 0xA9, 0xBF, 0x8F, 0x34, 0x01, 0xE1, 0x4C, 0xB7, 0x4C, 0x38, +0x68, 0x60, 0xEB, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0xEB, 0x29, 0x5F, 0x48, 0xBD, 0xB8, 0x04, 0x89, +0x08, 0xD0, 0x03, 0x68, 0x80, 0x5F, 0x68, 0x48, 0xC9, 0x00, 0xD0, 0x04, 0x18, 0x68, 0x80, 0xE0, +0xBD, 0xB8, 0x04, 0x48, 0x29, 0x07, 0x9D, 0xB8, 0x03, 0x68, 0x29, 0xF0, 0x9D, 0xB8, 0x04, 0x68, +0xDA, 0x48, 0xBD, 0xB8, 0x03, 0xAA, 0x68, 0xC9, 0x45, 0xD0, 0x03, 0x4C, 0x5F, 0x4C, 0xC9, 0x44, +0xF0, 0x7F, 0xFA, 0xDA, 0xDD, 0x38, 0x04, 0x08, 0x48, 0xBD, 0xB8, 0x03, 0xAA, 0x68, 0x28, 0xF0, +0x15, 0xC9, 0x0D, 0xF0, 0x1A, 0xFA, 0xAF, 0x8B, 0x15, 0xE1, 0x8F, 0x34, 0x01, 0xE1, 0x1E, 0xB8, +0x04, 0x5E, 0xB8, 0x04, 0x80, 0x99, 0xFA, 0xDA, 0xFE, 0xB8, 0x04, 0xBD, 0xB8, 0x03, 0xAA, 0xBF, +0x97, 0x4E, 0xFF, 0x80, 0x0C, 0xDA, 0xA2, 0x07, 0xDF, 0x97, 0x4E, 0xFF, 0xF0, 0x73, 0xCA, 0x10, +0xF7, 0xA2, 0x0C, 0xDF, 0x8A, 0x4E, 0xFF, 0xD0, 0x03, 0x4C, 0xAE, 0x4C, 0xCA, 0x10, 0xF4, 0xFA, +0x68, 0x48, 0x29, 0x7F, 0xC9, 0x20, 0xB0, 0x03, 0x9D, 0x38, 0x04, 0x49, 0x30, 0xC9, 0x0A, 0xB0, +0x38, 0xA0, 0x0A, 0x6F, 0x8A, 0x15, 0xE1, 0x88, 0xD0, 0xF9, 0x48, 0xA9, 0x80, 0x1D, 0xB8, 0x05, +0x9D, 0xB8, 0x05, 0x68, 0x80, 0x73, 0xA9, 0x4C, 0x28, 0xB0, 0xC6, 0xA9, 0x4B, 0x80, 0xC2, 0x38, +0x90, 0x18, 0x08, 0xE0, 0x00, 0xF0, 0xEF, 0xE0, 0x07, 0xD0, 0x03, 0x4C, 0x52, 0x4E, 0xE0, 0x06, +0xF0, 0x5E, 0xE0, 0x05, 0xF0, 0x78, 0x4C, 0xE1, 0x4C, 0xBD, 0xB8, 0x04, 0x4A, 0xB0, 0x38, 0xAF, +0x8B, 0x15, 0xE1, 0x8F, 0x34, 0x01, 0xE1, 0x08, 0x1E, 0xB8, 0x04, 0x28, 0x7E, 0xB8, 0x04, 0x68, +0x60, 0xC9, 0x42, 0xD0, 0x0C, 0x8A, 0xFA, 0xDA, 0x48, 0xBD, 0xB8, 0x05, 0xFA, 0x89, 0x80, 0xD0, +0x0D, 0x8A, 0xFA, 0x1D, 0xB8, 0x04, 0x09, 0x08, 0x9D, 0xB8, 0x04, 0x38, 0x80, 0xD9, 0xA9, 0x4D, +0x48, 0xBF, 0x63, 0x4E, 0xFF, 0x48, 0x60, 0xBD, 0xB8, 0x04, 0x29, 0xC0, 0x9D, 0xB8, 0x04, 0xBD, +0xB8, 0x05, 0x29, 0x7F, 0x9D, 0xB8, 0x05, 0xA9, 0x00, 0x8F, 0x8A, 0x15, 0xE1, 0x38, 0x80, 0xB7, +0x28, 0xFA, 0xA9, 0xF7, 0x3D, 0xB8, 0x05, 0x90, 0x02, 0x09, 0x08, 0x9D, 0xB8, 0x05, 0x4C, 0x79, +0x4C, 0x8A, 0x18, 0x0A, 0x69, 0x03, 0xAA, 0x28, 0xB0, 0x01, 0xE8, 0x4C, 0x31, 0x4D, 0x28, 0xFA, +0x08, 0x78, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0xBD, 0xB8, 0x05, 0x29, 0xBF, 0x90, 0x02, 0x09, 0x40, +0x9D, 0xB8, 0x05, 0x20, 0xDE, 0x52, 0x28, 0x90, 0x08, 0xDA, 0x20, 0xBC, 0x53, 0x20, 0xC4, 0x51, +0xFA, 0x4C, 0x41, 0x4D, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x9E, 0x38, 0x06, 0xA9, 0x80, 0x1D, 0x38, +0x05, 0x9D, 0x38, 0x05, 0x80, 0x1B, 0x7A, 0xAF, 0x8A, 0x15, 0xE1, 0xF0, 0x05, 0x99, 0x38, 0x06, +0xF0, 0x7A, 0xB9, 0x38, 0x07, 0x3F, 0x70, 0x4E, 0xFF, 0x1F, 0x7D, 0x4E, 0xFF, 0x99, 0x38, 0x07, +0xBB, 0x4C, 0x79, 0x4C, 0xAF, 0x8A, 0x15, 0xE1, 0xBB, 0x5F, 0x55, 0x15, 0xE1, 0x29, 0x03, 0x5F, +0x55, 0x15, 0xE1, 0x9F, 0x55, 0x15, 0xE1, 0xFA, 0xDA, 0x20, 0x7A, 0xC2, 0xFA, 0x80, 0xE2, 0xAF, +0x8A, 0x15, 0xE1, 0x48, 0x29, 0x03, 0x49, 0x03, 0xAA, 0xBF, 0x09, 0x55, 0xFF, 0xBB, 0x5F, 0x53, +0x15, 0xE1, 0x29, 0xC0, 0x5F, 0x53, 0x15, 0xE1, 0x9F, 0x53, 0x15, 0xE1, 0x4A, 0x5F, 0x57, 0x15, +0xE1, 0x29, 0x60, 0x5F, 0x57, 0x15, 0xE1, 0x9F, 0x57, 0x15, 0xE1, 0x68, 0x0A, 0xBB, 0x5F, 0x55, +0x15, 0xE1, 0x29, 0x08, 0x80, 0xB9, 0xAF, 0x8A, 0x15, 0xE1, 0xD0, 0x03, 0x20, 0xFD, 0x54, 0x20, +0x03, 0x55, 0x80, 0xB3, 0xFA, 0xDA, 0xBF, 0xD5, 0x14, 0xE1, 0x30, 0x24, 0xBB, 0xBF, 0x57, 0x15, +0xE1, 0x48, 0x09, 0x10, 0xA2, 0x05, 0x20, 0xC1, 0x55, 0x18, 0xA2, 0xF7, 0xA9, 0xF3, 0x3A, 0xD0, +0xFD, 0x6A, 0x49, 0x80, 0x2A, 0xB0, 0xF5, 0xCA, 0xD0, 0xF2, 0x68, 0xA2, 0x05, 0x20, 0xC1, 0x55, +0xFA, 0x4C, 0x41, 0x4D, 0x18, 0xB0, 0x38, 0xFA, 0x20, 0x1D, 0x4E, 0x4C, 0x79, 0x4C, 0xFA, 0xDA, +0xAD, 0x15, 0xC0, 0x48, 0x8D, 0x07, 0xC0, 0xBD, 0x38, 0x05, 0x29, 0x04, 0xF0, 0x16, 0x18, 0x20, +0x1D, 0x4E, 0xAD, 0x1F, 0xC0, 0x0A, 0x20, 0x59, 0xCF, 0xB0, 0x09, 0x20, 0x2C, 0xFB, 0xA9, 0xFF, +0x8F, 0x8B, 0x15, 0xE1, 0x68, 0x30, 0x03, 0x8D, 0x06, 0xC0, 0xFA, 0xDA, 0xBD, 0xB8, 0x05, 0x29, +0x40, 0xF0, 0xBD, 0x20, 0xDE, 0x52, 0xFA, 0xDA, 0x20, 0xE9, 0x4E, 0x80, 0xB3, 0xBD, 0xB8, 0x04, +0x89, 0x40, 0x90, 0x16, 0xD0, 0x2B, 0xE4, 0x39, 0xD0, 0x27, 0x09, 0x40, 0x48, 0xAF, 0x8B, 0x15, +0xE1, 0x8F, 0x8C, 0x15, 0xE1, 0x68, 0xA0, 0xDF, 0x80, 0x0B, 0xF0, 0x15, 0x29, 0xBF, 0x48, 0xAF, +0x8C, 0x15, 0xE1, 0xA8, 0x68, 0x9D, 0xB8, 0x04, 0x98, 0x8F, 0x8B, 0x15, 0xE1, 0x8F, 0x34, 0x01, +0xE1, 0x60, 0x28, 0xFA, 0xA9, 0xF7, 0x3D, 0x38, 0x05, 0x90, 0x02, 0x09, 0x08, 0x9D, 0x38, 0x05, +0x4C, 0x79, 0x4C, 0x30, 0x30, 0x30, 0x25, 0x25, 0x95, 0x5E, 0x43, 0xD3, 0xDD, 0xA3, 0xD5, 0x17, +0x7F, 0xBF, 0xBF, 0x7F, 0xFF, 0xDF, 0xDF, 0xEF, 0xEF, 0xF7, 0xF7, 0x7F, 0x7F, 0x80, 0x00, 0x40, +0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x08, 0x80, 0x00, 0x49, 0x4B, 0x4C, 0x4E, 0x0D, 0x42, +0x44, 0x50, 0x51, 0x52, 0x53, 0x54, 0x5A, 0x4C, 0x58, 0x46, 0x4D, 0x45, 0x42, 0x43, 0x41, 0x3C, +0x3B, 0xDA, 0xF4, 0x00, 0x00, 0xF4, 0x00, 0x80, 0xA2, 0x03, 0x20, 0x22, 0x00, 0x00, 0xE1, 0x68, +0xFA, 0x08, 0xE0, 0xC1, 0x00, 0xF0, 0x01, 0xE8, 0x9F, 0x08, 0x15, 0xE1, 0x28, 0xB0, 0x29, 0xA2, +0x00, 0x00, 0xDA, 0xDA, 0xDA, 0xF4, 0x00, 0x10, 0x48, 0xF4, 0x08, 0x40, 0xDA, 0xDA, 0xA2, 0x02, +0x09, 0x22, 0x00, 0x00, 0xE1, 0xFA, 0x68, 0xB0, 0x0F, 0x8B, 0xEB, 0x48, 0xAB, 0xAB, 0xBD, 0x00, +0x00, 0x48, 0xBD, 0x02, 0x00, 0xAA, 0x68, 0xAB, 0x60, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0x18, +0x20, 0x18, 0x54, 0xC2, 0x30, 0xDA, 0xA9, 0x00, 0x00, 0x48, 0x48, 0xB9, 0xDA, 0x1D, 0x48, 0xB9, +0xD8, 0x1D, 0x48, 0xA2, 0x02, 0x1A, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x01, 0x03, 0x03, 0x38, 0xF0, +0x1F, 0xA2, 0x02, 0x10, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0x16, 0xFA, 0xDA, 0xE0, 0xC1, 0x00, 0xF0, +0x01, 0xE8, 0xBF, 0x08, 0x15, 0xE1, 0x48, 0xA2, 0x03, 0x21, 0x22, 0x00, 0x00, 0xE1, 0x80, 0x02, +0xFA, 0x68, 0xFA, 0xE2, 0x30, 0xB0, 0x03, 0x9E, 0x3D, 0x0F, 0xAB, 0x60, 0x08, 0x38, 0x80, 0x02, +0x08, 0x18, 0x48, 0xBD, 0x38, 0x05, 0x29, 0xFB, 0x90, 0x02, 0x09, 0x04, 0x9D, 0x38, 0x05, 0x68, +0x28, 0x60, 0x8B, 0xEB, 0xA5, 0x00, 0x48, 0xA5, 0x01, 0x48, 0xA5, 0x02, 0x48, 0xEB, 0x85, 0x00, +0x86, 0x01, 0x84, 0x02, 0xA0, 0x01, 0xB7, 0x00, 0xC9, 0x19, 0xB0, 0x5D, 0x4A, 0xAA, 0xBF, 0xE0, +0x4F, 0xFF, 0xA0, 0x00, 0x57, 0x00, 0xD0, 0x13, 0xBF, 0x03, 0x50, 0xFF, 0x48, 0xBF, 0xF6, 0x4F, +0xFF, 0x48, 0xAE, 0xF8, 0x07, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0x60, 0xA9, 0x01, 0x80, 0x3C, 0xA0, +0x04, 0xBD, 0x38, 0x07, 0x90, 0x02, 0xB7, 0x00, 0x9D, 0x38, 0x07, 0x97, 0x00, 0xC8, 0xBD, 0xB8, +0x05, 0x90, 0x02, 0xB7, 0x00, 0x9D, 0xB8, 0x05, 0x97, 0x00, 0xC8, 0xBD, 0x38, 0x05, 0x90, 0x02, +0xB7, 0x00, 0x9D, 0x38, 0x05, 0x97, 0x00, 0xC8, 0xBD, 0xB8, 0x04, 0x90, 0x02, 0xB7, 0x00, 0x9D, +0xB8, 0x04, 0x97, 0x00, 0x18, 0xA9, 0x00, 0x80, 0x03, 0xA9, 0x02, 0x38, 0xA0, 0x02, 0x97, 0x00, +0xC8, 0xA9, 0x00, 0x97, 0x00, 0x68, 0x85, 0x02, 0x68, 0x85, 0x01, 0x68, 0x85, 0x00, 0xAB, 0x6B, +0x03, 0x00, 0x00, 0x03, 0x04, 0x03, 0x03, 0x00, 0x04, 0x04, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, +0x03, 0x03, 0x03, 0x03, 0x04, 0x00, 0x8E, 0xC8, 0xC8, 0x89, 0x99, 0xAF, 0x77, 0xC8, 0x16, 0x0F, +0x4A, 0x50, 0x8D, 0x4F, 0x4F, 0x4F, 0xC2, 0xC2, 0xC2, 0x50, 0x4F, 0x50, 0x50, 0x50, 0x50, 0xC1, +0x20, 0x35, 0x50, 0xE2, 0x40, 0x80, 0x04, 0xB8, 0x20, 0x18, 0x54, 0xBB, 0xA0, 0x04, 0xBF, 0xD8, +0x1D, 0xE1, 0x50, 0x02, 0xB7, 0x00, 0x9F, 0xD8, 0x1D, 0xE1, 0x97, 0x00, 0xE8, 0xC8, 0xC0, 0x0A, +0x90, 0xEC, 0x4C, 0xC4, 0x4F, 0x20, 0x18, 0x54, 0xDA, 0xBB, 0xC2, 0x20, 0xA9, 0x00, 0x00, 0x9F, +0xDE, 0x1D, 0xE1, 0x9F, 0xE0, 0x1D, 0xE1, 0xE2, 0x20, 0xFA, 0x60, 0x20, 0x35, 0x50, 0x4C, 0xC4, +0x4F, 0xB0, 0x05, 0x20, 0x9B, 0x53, 0x80, 0x03, 0x20, 0xB1, 0x53, 0xA0, 0x04, 0x00, 0x97, 0x00, +0xC8, 0xC8, 0xAF, 0xDC, 0x00, 0xE1, 0xE0, 0xC2, 0x00, 0x90, 0x01, 0xE8, 0x38, 0xFF, 0xD9, 0x14, +0xE1, 0x97, 0x00, 0xE2, 0x30, 0x4C, 0xC4, 0x4F, 0x5A, 0xDA, 0x08, 0xA0, 0x08, 0xA9, 0x03, 0xE0, +0xC1, 0xF0, 0x02, 0xA9, 0x07, 0xAA, 0x28, 0x08, 0xB7, 0x00, 0xB0, 0x04, 0xBF, 0xC1, 0x15, 0xE1, +0x97, 0x00, 0x9F, 0xC1, 0x15, 0xE1, 0xCA, 0x88, 0xC0, 0x06, 0x10, 0xEA, 0xA9, 0x5C, 0x9F, 0xC1, +0x15, 0xE1, 0x28, 0xFA, 0xB0, 0x08, 0x7A, 0xBF, 0xE1, 0x14, 0xE1, 0x4C, 0xCA, 0xC2, 0xA0, 0x04, +0xB7, 0x00, 0x9F, 0xDD, 0x14, 0xE1, 0x29, 0xEA, 0x7A, 0x48, 0xA9, 0x0F, 0xAA, 0x20, 0xCE, 0x55, +0x03, 0x01, 0xAB, 0x4C, 0xC5, 0xC2, 0xAD, 0x68, 0xC0, 0x48, 0x29, 0x8F, 0x8D, 0x68, 0xC0, 0x9C, +0xA2, 0x15, 0x9C, 0xA3, 0x15, 0x8B, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xA2, 0xC1, 0xBF, 0xDE, 0x4D, +0xFF, 0xA8, 0xA9, 0x03, 0x20, 0xCE, 0x55, 0x2F, 0x04, 0x01, 0xE1, 0xC9, 0x08, 0xB0, 0x21, 0xE8, +0x88, 0xC9, 0x00, 0xD0, 0x1E, 0xAF, 0xA2, 0x15, 0xE1, 0xF0, 0x04, 0x22, 0xC1, 0x15, 0xE1, 0xAF, +0xA3, 0x15, 0xE1, 0xF0, 0x04, 0x22, 0xC5, 0x15, 0xE1, 0x18, 0xAB, 0x68, 0x8D, 0x68, 0xC0, 0x6B, +0x4A, 0x4A, 0x4A, 0xEB, 0xBD, 0xB8, 0x05, 0x89, 0x40, 0x38, 0xF0, 0xEE, 0xB9, 0xFD, 0xBF, 0x48, +0x5F, 0xDF, 0x14, 0xE1, 0x3F, 0xDD, 0x14, 0xE1, 0x1F, 0xE1, 0x14, 0xE1, 0x9F, 0xE1, 0x14, 0xE1, +0x68, 0x29, 0xFA, 0x9F, 0xDF, 0x14, 0xE1, 0xEB, 0x4A, 0x90, 0x26, 0xA9, 0x0F, 0x20, 0xCE, 0x55, +0x29, 0xFD, 0xDA, 0xA2, 0x0F, 0x20, 0xC1, 0x55, 0xFA, 0x20, 0xB2, 0x4A, 0xA9, 0x10, 0x99, 0xFD, +0xBF, 0xBD, 0x38, 0x07, 0x89, 0x02, 0xD0, 0x83, 0xB9, 0xFD, 0xBF, 0x89, 0x04, 0xF0, 0x2A, 0x80, +0x03, 0x4A, 0x90, 0x2D, 0xA9, 0x28, 0x99, 0xFD, 0xBF, 0xBD, 0xB8, 0x05, 0x89, 0x02, 0xD0, 0x19, +0xBD, 0x38, 0x07, 0x89, 0x02, 0xD0, 0x12, 0x38, 0x20, 0x40, 0x53, 0xB0, 0x0F, 0xBD, 0xB8, 0x05, +0x89, 0x01, 0xF0, 0x05, 0x20, 0x91, 0x52, 0xD0, 0xC8, 0x4C, 0xDB, 0x50, 0x99, 0xFF, 0xBF, 0x80, +0xF8, 0x5A, 0x20, 0x24, 0x4B, 0x7A, 0x90, 0x23, 0x18, 0x20, 0xF6, 0x52, 0xB0, 0x1D, 0xDA, 0xE0, +0xC2, 0x90, 0x01, 0xE8, 0xAF, 0xDC, 0x00, 0xE1, 0x9F, 0xD9, 0x14, 0xE1, 0xAF, 0xDD, 0x00, 0xE1, +0x9F, 0xDA, 0x14, 0xE1, 0xFA, 0x50, 0x04, 0x38, 0x20, 0x2A, 0x52, 0xB9, 0xFD, 0xBF, 0x4A, 0xB0, +0xD0, 0x4C, 0x51, 0x51, 0xBF, 0xD5, 0x14, 0xE1, 0x10, 0x01, 0x60, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, +0xDA, 0xA9, 0x02, 0xA2, 0x09, 0x20, 0xC1, 0x55, 0xFA, 0xAF, 0x04, 0x01, 0xE1, 0xE0, 0xC2, 0x90, +0x04, 0x09, 0x07, 0x80, 0x02, 0x09, 0x38, 0x8F, 0x04, 0x01, 0xE1, 0xBD, 0xB8, 0x05, 0x89, 0x20, +0x08, 0xBD, 0x38, 0x07, 0x29, 0x04, 0xF0, 0x02, 0xA9, 0x20, 0x28, 0xF0, 0x02, 0x09, 0x08, 0x09, +0x02, 0xA2, 0x0F, 0x20, 0xC1, 0x55, 0xA9, 0x13, 0xA2, 0x01, 0x20, 0xC1, 0x55, 0x08, 0x78, 0xA9, +0xFF, 0x8F, 0x27, 0x00, 0xE1, 0xA9, 0x50, 0x8F, 0x26, 0x00, 0xE1, 0xA9, 0xC6, 0x8F, 0x25, 0x00, +0xE1, 0x28, 0x58, 0xA9, 0x0A, 0xA2, 0x09, 0x4C, 0xC1, 0x55, 0xA9, 0x00, 0x90, 0x02, 0xA9, 0x04, +0x5D, 0xB8, 0x05, 0x29, 0x04, 0xF0, 0x3D, 0x5D, 0xB8, 0x05, 0x9D, 0xB8, 0x05, 0xDA, 0xBD, 0x38, +0x07, 0x48, 0x89, 0x04, 0xF0, 0x10, 0xBB, 0xBF, 0x57, 0x15, 0xE1, 0x49, 0x80, 0x9F, 0x57, 0x15, +0xE1, 0xA2, 0x05, 0x20, 0xC1, 0x55, 0x68, 0x89, 0x20, 0xF0, 0x18, 0x08, 0x78, 0xB9, 0xFD, 0xBF, +0x89, 0x04, 0xF0, 0xF9, 0xA9, 0x28, 0x99, 0xFD, 0xBF, 0xA9, 0x93, 0xB0, 0x02, 0xA9, 0x91, 0x99, +0xFF, 0xBF, 0x28, 0xFA, 0x60, 0xA0, 0x02, 0xE0, 0xC2, 0xBB, 0x90, 0x02, 0xA2, 0x05, 0x18, 0xBF, +0xA4, 0x15, 0xE1, 0xE9, 0x00, 0x48, 0xCA, 0x88, 0x10, 0xF5, 0xFA, 0x7A, 0x68, 0xDA, 0x5A, 0x48, +0x6B, 0x5A, 0xDA, 0x38, 0x20, 0x35, 0x50, 0xFA, 0xDA, 0x5A, 0xAF, 0xF8, 0x07, 0x00, 0x48, 0x22, +0x75, 0x52, 0xFF, 0x68, 0x8F, 0xF8, 0x07, 0x00, 0x8A, 0xFA, 0x9F, 0xE0, 0x1D, 0xE1, 0x98, 0x9F, +0xE1, 0x1D, 0xE1, 0x1F, 0xE0, 0x1D, 0xE1, 0xEB, 0xFA, 0x7A, 0xEB, 0xD0, 0x0A, 0x08, 0xBD, 0xB8, +0x05, 0x29, 0xFE, 0x9D, 0xB8, 0x05, 0x28, 0x60, 0xA2, 0xC1, 0xBF, 0xD5, 0x14, 0xE1, 0x30, 0x01, +0xE8, 0x38, 0x20, 0x40, 0x53, 0xB0, 0x06, 0x20, 0x91, 0x52, 0xD0, 0xEC, 0x18, 0x6B, 0xBF, 0xDE, +0x4D, 0xFF, 0xA8, 0xDA, 0x20, 0xB3, 0x55, 0xFA, 0xB9, 0xFF, 0xBF, 0xA9, 0xD0, 0x99, 0xFD, 0xBF, +0xA9, 0x28, 0x99, 0xFD, 0xBF, 0x60, 0xDA, 0x5A, 0x8B, 0x48, 0x48, 0x20, 0xB1, 0x53, 0xD0, 0x04, +0x68, 0x38, 0x80, 0x36, 0xFA, 0xE2, 0x40, 0x48, 0xB9, 0xDC, 0x1D, 0x4A, 0x4A, 0xC3, 0x01, 0x68, +0xB0, 0x01, 0xB8, 0x08, 0x78, 0x5A, 0x20, 0x82, 0x53, 0xB9, 0xE0, 0x1D, 0xA8, 0x8A, 0xE2, 0x20, +0x97, 0x00, 0xC2, 0x20, 0xC8, 0x98, 0x7A, 0x48, 0x20, 0x82, 0x53, 0x68, 0xD9, 0xDC, 0x1D, 0x90, +0x03, 0xA9, 0x00, 0x00, 0x99, 0xE0, 0x1D, 0x28, 0x18, 0x8A, 0xE2, 0x30, 0xAB, 0x7A, 0xFA, 0x60, +0xDA, 0x5A, 0x8B, 0x20, 0x9B, 0x53, 0xF0, 0x33, 0xE2, 0x40, 0x48, 0xB9, 0xDC, 0x1D, 0x4A, 0x4A, +0xC3, 0x01, 0x68, 0xB0, 0x01, 0xB8, 0x38, 0x08, 0x78, 0x20, 0x82, 0x53, 0x5A, 0xB9, 0xDE, 0x1D, +0xA8, 0xB7, 0x00, 0xAA, 0x98, 0x1A, 0x7A, 0x48, 0x20, 0x82, 0x53, 0x68, 0xD9, 0xDC, 0x1D, 0x90, +0x03, 0xA9, 0x00, 0x00, 0x99, 0xDE, 0x1D, 0x28, 0x8A, 0x80, 0x01, 0x18, 0xE2, 0x30, 0xAB, 0x7A, +0xFA, 0x60, 0xB9, 0xD8, 0x1D, 0x48, 0xA5, 0x00, 0x99, 0xD8, 0x1D, 0x68, 0x85, 0x00, 0xB9, 0xDA, +0x1D, 0x48, 0xA5, 0x02, 0x99, 0xDA, 0x1D, 0x68, 0x85, 0x02, 0x60, 0xA9, 0xE1, 0x48, 0xAB, 0x20, +0x18, 0x54, 0xC2, 0x30, 0xB9, 0xE0, 0x1D, 0x38, 0xF9, 0xDE, 0x1D, 0xB0, 0x03, 0x79, 0xDC, 0x1D, +0x60, 0x20, 0x9B, 0x53, 0x38, 0xF9, 0xDC, 0x1D, 0x49, 0xFF, 0xFF, 0x60, 0xDA, 0x8B, 0xF4, 0xE1, +0xE1, 0xAB, 0xAB, 0x18, 0x20, 0x18, 0x54, 0xBD, 0x3D, 0x0F, 0xD0, 0x3F, 0xFE, 0x3D, 0x0F, 0xC2, +0x30, 0x5A, 0x20, 0xA1, 0x4E, 0x7A, 0x08, 0x90, 0x0E, 0xA2, 0xE1, 0x00, 0xA9, 0x00, 0x1E, 0xC0, +0x00, 0x00, 0xF0, 0x03, 0xA9, 0x00, 0x1F, 0x99, 0xD8, 0x1D, 0x8A, 0x99, 0xDA, 0x1D, 0x28, 0xA9, +0x80, 0x00, 0xB0, 0x03, 0xA9, 0x00, 0x08, 0x99, 0xDC, 0x1D, 0x99, 0xE6, 0x1D, 0x18, 0x79, 0xD8, +0x1D, 0x99, 0xE2, 0x1D, 0x90, 0x01, 0xE8, 0x8A, 0x99, 0xE4, 0x1D, 0xE2, 0x30, 0xAB, 0xFA, 0x18, +0x20, 0x35, 0x50, 0x38, 0x20, 0x35, 0x50, 0x60, 0xEB, 0xA9, 0x00, 0x90, 0x02, 0xA9, 0x0A, 0xE0, +0xC2, 0x90, 0x02, 0x69, 0x13, 0xA8, 0xEB, 0x60, 0xDA, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0x20, 0x1E, +0x55, 0xBF, 0xD5, 0x14, 0xE1, 0x30, 0x09, 0xA9, 0x00, 0x20, 0xCE, 0x55, 0xC9, 0x40, 0xF0, 0xF7, +0xA2, 0x07, 0x20, 0xED, 0x54, 0x29, 0x01, 0x38, 0x2A, 0xEB, 0xA2, 0x08, 0x20, 0xED, 0x54, 0x49, +0x02, 0x4A, 0xEB, 0x2A, 0xEB, 0x4A, 0xEB, 0x2A, 0xBB, 0x09, 0x40, 0x9F, 0x55, 0x15, 0xE1, 0xA2, +0x07, 0x20, 0xED, 0x54, 0x4A, 0x29, 0x03, 0xAA, 0xBF, 0x09, 0x55, 0xFF, 0xBB, 0x9F, 0x53, 0x15, +0xE1, 0x4A, 0x09, 0x0A, 0x9F, 0x57, 0x15, 0xE1, 0x20, 0xFD, 0x54, 0xFA, 0xDA, 0x20, 0x2E, 0x55, +0xA9, 0x00, 0xA2, 0x0B, 0xEB, 0x20, 0xED, 0x54, 0x4A, 0xEB, 0x90, 0x04, 0x1F, 0x0D, 0x55, 0xFF, +0xCA, 0x10, 0xF1, 0x7A, 0x49, 0x08, 0x99, 0x38, 0x07, 0x29, 0x01, 0xD0, 0x02, 0xA9, 0x09, 0x99, +0x38, 0x04, 0xA2, 0x05, 0x20, 0xED, 0x54, 0xF0, 0x02, 0xA9, 0x40, 0xEB, 0xA2, 0x09, 0x20, 0xED, +0x54, 0x4A, 0xEB, 0x90, 0x02, 0x09, 0x20, 0xBB, 0x9D, 0xB8, 0x05, 0xA2, 0x01, 0x20, 0xED, 0x54, +0xAA, 0xBF, 0x19, 0x55, 0xFF, 0x99, 0x38, 0x06, 0xBB, 0x9E, 0xB8, 0x04, 0x9E, 0xB8, 0x06, 0xBD, +0x38, 0x05, 0x29, 0x04, 0x9D, 0x38, 0x05, 0xA9, 0x00, 0x9F, 0xDD, 0x14, 0xE1, 0xBD, 0xB8, 0x05, +0x89, 0x40, 0xF0, 0x08, 0xDA, 0x20, 0xBC, 0x53, 0x20, 0xC4, 0x51, 0xFA, 0x60, 0xAD, 0xF8, 0x07, +0x4A, 0x90, 0x05, 0xBF, 0xC0, 0x02, 0xE1, 0x60, 0xBF, 0xCC, 0x02, 0xE1, 0x60, 0xA2, 0x06, 0x20, +0xED, 0x54, 0x1A, 0xBB, 0x9F, 0x59, 0x15, 0xE1, 0x60, 0x01, 0x81, 0x41, 0xC1, 0x01, 0x00, 0x08, +0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x28, 0x48, 0x50, 0x84, 0xBF, 0xD5, +0x14, 0xE1, 0x30, 0xD8, 0xBB, 0xBF, 0x76, 0x55, 0xFF, 0xA2, 0x09, 0x4C, 0xC1, 0x55, 0xBF, 0xD5, +0x14, 0xE1, 0x30, 0xC8, 0xB9, 0xFD, 0xBF, 0xBB, 0xBF, 0x55, 0x15, 0xE1, 0xA2, 0x04, 0x20, 0xC1, +0x55, 0xBB, 0xA9, 0x00, 0xA2, 0x01, 0x20, 0xC1, 0x55, 0xBB, 0xBF, 0x53, 0x15, 0xE1, 0x48, 0x29, +0xFE, 0xA2, 0x03, 0x20, 0xC1, 0x55, 0xBB, 0xBF, 0x57, 0x15, 0xE1, 0x48, 0x29, 0xF7, 0xA2, 0x05, +0x20, 0xC1, 0x55, 0xA9, 0xD2, 0xC0, 0x3C, 0xF0, 0x02, 0xA9, 0x52, 0xA2, 0x0B, 0x20, 0xC1, 0x55, +0xBB, 0xBF, 0x59, 0x15, 0xE1, 0x29, 0x0F, 0xAA, 0xDA, 0xBF, 0xD7, 0xC2, 0xFF, 0xA2, 0x0C, 0x20, +0xC1, 0x55, 0xFA, 0xBF, 0xE7, 0xC2, 0xFF, 0xA2, 0x0D, 0x20, 0xC1, 0x55, 0xA2, 0x0E, 0xA9, 0x00, +0x20, 0xC1, 0x55, 0xA2, 0x0E, 0xA9, 0x01, 0x20, 0xC1, 0x55, 0x68, 0x09, 0x08, 0xA2, 0x05, 0x20, +0xC1, 0x55, 0x68, 0x09, 0x01, 0xA2, 0x03, 0x20, 0xC1, 0x55, 0xA9, 0x00, 0xA2, 0x0F, 0x4C, 0xC1, +0x55, 0x0A, 0x0A, 0xBF, 0xD5, 0x14, 0xE1, 0x30, 0x07, 0xA9, 0x00, 0xA2, 0x01, 0x20, 0xC1, 0x55, +0x60, 0x08, 0x78, 0x48, 0x8A, 0x99, 0xFD, 0xBF, 0x68, 0x99, 0xFD, 0xBF, 0x28, 0x60, 0x08, 0x78, +0x99, 0xFD, 0xBF, 0xB9, 0xFD, 0xBF, 0xEB, 0x28, 0xEB, 0x60, 0x20, 0x61, 0x4B, 0x90, 0x18, 0xBD, +0x38, 0x07, 0x89, 0x20, 0xF0, 0x11, 0x20, 0x24, 0x4B, 0x90, 0x0C, 0x9F, 0xD7, 0x14, 0xE1, 0xBD, +0xB8, 0x05, 0x09, 0x10, 0x9D, 0xB8, 0x05, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x20, 0xAF, 0x5D, 0x9C, 0x51, 0x0F, 0xA9, 0xA5, 0xCD, 0xB6, 0x0F, 0xF0, 0x23, 0x8D, 0xB6, 0x0F, +0xA9, 0x03, 0x20, 0xAE, 0x5F, 0x20, 0x52, 0x56, 0x38, 0x6E, 0x56, 0x0F, 0xA9, 0xFA, 0x8D, 0x26, +0x0F, 0x8D, 0x27, 0x0F, 0x20, 0x5D, 0x56, 0x20, 0x6B, 0x56, 0x20, 0xE0, 0x5D, 0x20, 0xAB, 0x64, +0x2C, 0x56, 0x0F, 0x30, 0x0C, 0xAE, 0x56, 0x0F, 0x8E, 0x28, 0x0F, 0x20, 0x16, 0x5E, 0x20, 0xCC, +0x5E, 0x20, 0x58, 0x58, 0x2C, 0xE8, 0xC0, 0x9C, 0x31, 0xC0, 0x18, 0xAD, 0x4B, 0x0F, 0xF0, 0x01, +0x38, 0x60, 0xA9, 0x04, 0x8D, 0x4F, 0x0F, 0xA9, 0x80, 0x8D, 0x50, 0x0F, 0x60, 0xA2, 0x41, 0xBF, +0x00, 0x58, 0xFF, 0x9F, 0x6D, 0x0F, 0xE1, 0xCA, 0x10, 0xF5, 0x60, 0xA2, 0x15, 0xBF, 0x42, 0x58, +0xFF, 0x9D, 0x57, 0x0F, 0xCA, 0x10, 0xF6, 0x60, 0xA9, 0x28, 0x38, 0x8D, 0x4B, 0x0F, 0x60, 0x20, +0xA4, 0x5C, 0xA9, 0x01, 0x85, 0x45, 0xA9, 0xFF, 0x8D, 0x51, 0x0F, 0x20, 0x7A, 0x59, 0xB0, 0x00, +0x60, 0x96, 0x19, 0x19, 0x19, 0x19, 0x00, 0x01, 0x98, 0x99, 0x02, 0x03, 0x9C, 0x04, 0x05, 0x06, +0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x07, 0x08, 0xA8, 0xA9, 0xAA, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, +0xB0, 0xB1, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xB8, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, +0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x1B, 0xCC, 0x1C, 0x1D, 0x1E, +0xD0, 0xD1, 0xD2, 0x1F, 0xD4, 0xD5, 0x20, 0x21, 0xD8, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, +0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x29, 0x2A, 0x2B, 0xE8, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, +0xF0, 0xF1, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xF8, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, +0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, +0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, +0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, +0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, +0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, +0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, +0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, +0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, +0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, +0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, +0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, +0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, +0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +0x40, 0x00, 0x5C, 0xC8, 0x61, 0xFF, 0x5C, 0xC8, 0x61, 0xFF, 0x5C, 0x44, 0x62, 0xFF, 0x5C, 0x44, +0x62, 0xFF, 0x5C, 0x9E, 0x63, 0xFF, 0x5C, 0x9E, 0x63, 0xFF, 0x5C, 0x29, 0x5E, 0xFF, 0x5C, 0x29, +0x5E, 0xFF, 0x5C, 0x37, 0x5A, 0xFF, 0x5C, 0x37, 0x5A, 0xFF, 0x5C, 0x8D, 0x5A, 0xFF, 0x5C, 0x8D, +0x5A, 0xFF, 0x5C, 0xFC, 0x5B, 0xFF, 0x5C, 0xFC, 0x5B, 0xFF, 0x5C, 0x5C, 0x58, 0xFF, 0x5C, 0x5C, +0x58, 0xFF, 0xFF, 0xAD, 0xAA, 0xD5, 0xFF, 0xFC, 0xF3, 0xCF, 0x3F, 0xFF, 0xFF, 0xAA, 0xDE, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0xAA, 0xD5, 0xFF, 0x5C, 0xA7, 0x0F, 0xE1, 0xAD, 0x39, 0x0F, 0xD0, +0x10, 0xA2, 0x00, 0xA5, 0x5A, 0xCD, 0x20, 0x0F, 0xF0, 0x01, 0xE8, 0x8E, 0x28, 0x0F, 0x20, 0x10, +0x5E, 0xA5, 0x45, 0xF0, 0x08, 0xA2, 0x06, 0x9E, 0x43, 0x0F, 0xCA, 0x10, 0xFA, 0x9C, 0x4B, 0x0F, +0xA5, 0x45, 0xC9, 0x0A, 0x90, 0x05, 0xA9, 0x01, 0x82, 0xEF, 0xFD, 0xAA, 0xBF, 0xB6, 0x58, 0xFF, +0x29, 0x7F, 0xC5, 0x46, 0xF0, 0x05, 0xA9, 0x04, 0x82, 0xDF, 0xFD, 0x8A, 0x0A, 0xAA, 0x7C, 0xA2, +0x58, 0x60, 0xC0, 0x58, 0x7A, 0x59, 0x7D, 0x59, 0x33, 0x5A, 0x28, 0x5C, 0x69, 0x5C, 0x86, 0x58, +0x86, 0x58, 0x7F, 0x56, 0x95, 0x5C, 0x03, 0x03, 0x83, 0x01, 0x83, 0x02, 0x01, 0x01, 0x04, 0x84, +0xA5, 0x48, 0xC9, 0x08, 0x90, 0x03, 0x82, 0x65, 0x03, 0x0A, 0xAA, 0xBF, 0xD7, 0x58, 0xFF, 0x48, +0xBF, 0xD6, 0x58, 0xFF, 0x48, 0x60, 0x1F, 0x59, 0x2D, 0x5C, 0x2D, 0x5C, 0xE5, 0x58, 0x2D, 0x5C, +0x10, 0x59, 0xFA, 0x64, 0x1A, 0x65, 0x20, 0x20, 0x59, 0x9B, 0xA2, 0x00, 0xBF, 0xFC, 0x58, 0xFF, +0x97, 0x42, 0xC8, 0xE8, 0xE0, 0x15, 0x90, 0xF4, 0xBB, 0xA0, 0x00, 0x60, 0x08, 0x44, 0x49, 0x53, +0x4B, 0x20, 0x33, 0x2E, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xC0, 0x00, +0x10, 0xA0, 0x08, 0xB9, 0x43, 0x0F, 0x97, 0x42, 0x88, 0xD0, 0xF8, 0x9C, 0x4B, 0x0F, 0x18, 0x60, +0x38, 0x20, 0x38, 0x5F, 0xA0, 0x00, 0x9C, 0x4B, 0x0F, 0xA9, 0xFC, 0xA2, 0x02, 0x06, 0x68, 0x90, +0x04, 0x5F, 0x77, 0x59, 0xFF, 0xCA, 0x10, 0xF5, 0x2C, 0x1E, 0x0F, 0x70, 0x02, 0x29, 0xFE, 0x97, +0x42, 0xC8, 0xAE, 0x28, 0x0F, 0x3C, 0x24, 0x0F, 0x30, 0x0C, 0xA9, 0x20, 0x97, 0x42, 0xC8, 0xA9, +0x03, 0x97, 0x42, 0xC8, 0x80, 0x0A, 0xA9, 0x40, 0x97, 0x42, 0xC8, 0xA9, 0x06, 0x97, 0x42, 0xC8, +0xA9, 0x00, 0x97, 0x42, 0xC8, 0x2C, 0x1E, 0x0F, 0x50, 0x03, 0x97, 0x42, 0xC8, 0xBB, 0xA0, 0x00, +0x8C, 0x31, 0xC0, 0x8C, 0xEA, 0xC0, 0x60, 0x01, 0x10, 0x04, 0x18, 0x80, 0x1C, 0xA2, 0xAF, 0xA0, +0x00, 0xAD, 0x51, 0x0F, 0xD0, 0x0F, 0xA0, 0x04, 0x9E, 0x00, 0x0C, 0x9E, 0x00, 0x0D, 0x9E, 0x00, +0x0E, 0xCA, 0x88, 0xD0, 0xF3, 0x20, 0x20, 0x63, 0x38, 0x20, 0x38, 0x5F, 0x90, 0x01, 0x60, 0x20, +0x9B, 0x60, 0xB0, 0xFA, 0x20, 0xE6, 0x5F, 0xA9, 0x04, 0x8D, 0x35, 0x0F, 0xA9, 0x96, 0x8D, 0x37, +0x0F, 0xAD, 0x35, 0x0F, 0xC9, 0x02, 0xD0, 0x03, 0x20, 0xA6, 0x5E, 0x20, 0x25, 0x5E, 0x90, 0x16, +0xCE, 0x35, 0x0F, 0xD0, 0xEC, 0xF0, 0x62, 0xEE, 0x45, 0x0F, 0xCE, 0x37, 0x0F, 0xF0, 0x5A, 0xAD, +0x37, 0x0F, 0xC9, 0x4B, 0xF0, 0xE2, 0x20, 0xC4, 0x61, 0xB0, 0xEC, 0xAD, 0x32, 0x0F, 0x85, 0x68, +0xAD, 0x34, 0x0F, 0x0A, 0x0A, 0x46, 0x68, 0x6A, 0x4A, 0xCD, 0x29, 0x0F, 0xF0, 0x0E, 0xAE, 0x28, +0x0F, 0x9D, 0x22, 0x0F, 0xA9, 0x04, 0x0C, 0x44, 0x0F, 0x4C, 0xC0, 0x59, 0xA5, 0x68, 0x0A, 0x0A, +0x0A, 0x4D, 0x2B, 0x0F, 0x30, 0xC1, 0xAD, 0x33, 0x0F, 0xCD, 0x2A, 0x0F, 0xD0, 0xB9, 0xA5, 0x45, +0xC9, 0x01, 0xD0, 0x1A, 0x20, 0x40, 0x62, 0xB0, 0xAE, 0x20, 0x59, 0x64, 0x18, 0xAD, 0x44, 0x0F, +0xF0, 0x05, 0xA9, 0x67, 0x82, 0x53, 0xFC, 0x18, 0x60, 0xA9, 0x27, 0x82, 0x4C, 0xFC, 0x20, 0x9A, +0x63, 0x18, 0x60, 0x5C, 0x8F, 0x0F, 0xE1, 0xA9, 0x03, 0x20, 0xAE, 0x5F, 0x38, 0x20, 0x38, 0x5F, +0xB0, 0x46, 0x20, 0xA6, 0x5E, 0xB0, 0x39, 0x9C, 0x2B, 0x0F, 0x9C, 0x29, 0x0F, 0xA9, 0x0A, 0x85, +0x6A, 0x20, 0x89, 0x5A, 0xB0, 0x2A, 0x20, 0xF8, 0x5B, 0x90, 0x07, 0xC6, 0x6A, 0xD0, 0xF2, 0x4C, +0x80, 0x5A, 0x20, 0x43, 0x65, 0x2C, 0x50, 0x0F, 0x10, 0x0A, 0xA9, 0x80, 0x4D, 0x2B, 0x0F, 0x8D, +0x2B, 0x0F, 0xD0, 0xD9, 0xEE, 0x29, 0x0F, 0xAD, 0x29, 0x0F, 0xC9, 0x50, 0x90, 0xCF, 0x18, 0x60, +0x20, 0xCC, 0x5E, 0xA9, 0x27, 0x82, 0xF2, 0xFB, 0x60, 0x5C, 0x97, 0x0F, 0xE1, 0x20, 0x25, 0x5E, +0x20, 0x41, 0x5B, 0x20, 0x7A, 0x5B, 0x20, 0x24, 0x5F, 0xAD, 0x2B, 0x0F, 0xD0, 0x16, 0xAD, 0x29, +0x0F, 0x29, 0x0F, 0xD0, 0x0F, 0xAD, 0x29, 0x0F, 0x4A, 0x4A, 0x4A, 0x4A, 0xAA, 0xBF, 0x91, 0x56, +0xFF, 0x20, 0x84, 0x5E, 0x20, 0x2D, 0x62, 0x64, 0x68, 0x2C, 0xED, 0xC0, 0x8D, 0xEF, 0xC0, 0xA9, +0x00, 0xA2, 0xC8, 0x85, 0x69, 0xA0, 0x04, 0xB9, 0x5C, 0x0F, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, +0xED, 0xC0, 0x88, 0x10, 0xF2, 0xCA, 0xD0, 0xED, 0xC6, 0x69, 0x10, 0xE9, 0xC2, 0x10, 0xE2, 0x20, +0xA0, 0x18, 0x03, 0xB9, 0x00, 0x0C, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0x88, 0xD0, +0xF2, 0xE2, 0x10, 0xE6, 0x68, 0xA4, 0x68, 0xCC, 0x2C, 0x0F, 0xB0, 0x38, 0xA9, 0xFF, 0x2C, 0xEC, +0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0xB6, 0x4E, 0xBF, 0x00, 0x57, 0xFF, 0x8D, 0xD2, 0x0E, 0x8D, +0xC2, 0x0E, 0xA9, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0x8A, 0x45, 0x5B, 0xAA, +0xBF, 0x00, 0x57, 0xFF, 0x8D, 0xCF, 0x0E, 0xA9, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, +0xC0, 0x4C, 0xDC, 0x5A, 0x2C, 0xEC, 0xC0, 0x70, 0xFB, 0xAD, 0xEE, 0xC0, 0xAD, 0xEC, 0xC0, 0x18, +0x60, 0xA9, 0x96, 0xA2, 0x00, 0x9D, 0x00, 0x0C, 0x9D, 0x00, 0x0D, 0x9D, 0x00, 0x0E, 0xCA, 0xD0, +0xF4, 0xA2, 0x15, 0xBD, 0x57, 0x0F, 0x9D, 0xC2, 0x0E, 0xCA, 0x10, 0xF7, 0xA2, 0x40, 0xA0, 0x04, +0xB9, 0x5C, 0x0F, 0x9D, 0xD8, 0x0E, 0xCA, 0x30, 0x05, 0x88, 0x10, 0xF4, 0x30, 0xF0, 0xA2, 0x02, +0xBD, 0x61, 0x0F, 0x9D, 0x00, 0x0C, 0xCA, 0x10, 0xF7, 0x60, 0xA9, 0xFF, 0xA2, 0x0B, 0x95, 0x4E, +0xCA, 0x10, 0xFB, 0xE8, 0xA0, 0x00, 0x94, 0x4E, 0xC8, 0xCC, 0x2C, 0x0F, 0xB0, 0x17, 0x8A, 0x18, +0x6D, 0x4F, 0x0F, 0xAA, 0xEC, 0x2C, 0x0F, 0x90, 0x05, 0x8A, 0xED, 0x2C, 0x0F, 0xAA, 0x34, 0x4E, +0x30, 0xE4, 0xE8, 0x80, 0xEF, 0xAD, 0x29, 0x0F, 0x29, 0x3F, 0x85, 0x5B, 0xAA, 0xBF, 0x00, 0x57, +0xFF, 0x8D, 0xD3, 0x0E, 0xAD, 0x29, 0x0F, 0x0A, 0x0A, 0xA9, 0x00, 0x2A, 0x2C, 0x2B, 0x0F, 0x10, +0x02, 0x49, 0x20, 0xAA, 0x45, 0x5B, 0x85, 0x5B, 0xBF, 0x00, 0x57, 0xFF, 0x8D, 0xD1, 0x0E, 0xAD, +0x4F, 0x0F, 0x2C, 0x50, 0x0F, 0x10, 0x02, 0x09, 0x20, 0xAA, 0x45, 0x5B, 0x85, 0x5B, 0x48, 0xBF, +0x00, 0x57, 0xFF, 0x8D, 0xD0, 0x0E, 0x68, 0xAA, 0xBF, 0x00, 0x57, 0xFF, 0x8D, 0xCF, 0x0E, 0xA9, +0x96, 0x8D, 0xD2, 0x0E, 0x8D, 0xC2, 0x0E, 0x60, 0x5C, 0x9F, 0x0F, 0xE1, 0xA9, 0x02, 0x20, 0x89, +0x5E, 0xAD, 0x2C, 0x0F, 0x85, 0x69, 0x20, 0xC4, 0x61, 0xB0, 0x1B, 0xAE, 0x33, 0x0F, 0xEC, 0x2C, +0x0F, 0xB0, 0x13, 0xB5, 0x4E, 0x30, 0x0F, 0xA9, 0xFF, 0x95, 0x4E, 0x20, 0x40, 0x62, 0xB0, 0x06, +0xC6, 0x69, 0xD0, 0xE2, 0x18, 0x60, 0x38, 0x60, 0xA5, 0x48, 0xC9, 0x0B, 0x90, 0x05, 0xA9, 0x21, +0x82, 0x47, 0xFA, 0x0A, 0xAA, 0xBF, 0x41, 0x5C, 0xFF, 0x48, 0xBF, 0x40, 0x5C, 0xFF, 0x48, 0x60, +0x58, 0x5C, 0x55, 0x5C, 0x55, 0x5C, 0x55, 0x5C, 0x65, 0x5C, 0xAF, 0x5C, 0x0E, 0x5D, 0x37, 0x5D, +0x4E, 0x5D, 0x83, 0x5D, 0x94, 0x5D, 0x4C, 0x2E, 0x5C, 0x20, 0x52, 0x56, 0x20, 0x5D, 0x56, 0x4C, +0x6B, 0x56, 0x4C, 0x2E, 0x5C, 0x60, 0x4C, 0xCC, 0x5E, 0xAD, 0x39, 0x0F, 0xD0, 0x06, 0xA9, 0x40, +0x8D, 0x4B, 0x0F, 0x60, 0x9C, 0x28, 0x0F, 0xA5, 0x5A, 0xAC, 0x20, 0x0F, 0xF0, 0xF0, 0xC0, 0x40, +0x90, 0x05, 0x8D, 0x20, 0x0F, 0x80, 0x0A, 0xAC, 0x21, 0x0F, 0xC0, 0x40, 0x90, 0xE0, 0x8D, 0x21, +0x0F, 0xCE, 0x39, 0x0F, 0x60, 0x20, 0xA4, 0x5C, 0xA9, 0x02, 0x85, 0x45, 0xA9, 0xFF, 0x8D, 0x51, +0x0F, 0x4C, 0x7D, 0x59, 0xA2, 0x00, 0xB5, 0x4A, 0x95, 0x48, 0xE8, 0xE0, 0x04, 0x90, 0xF7, 0x60, +0xA9, 0x04, 0x20, 0xF9, 0x5C, 0xB0, 0x52, 0xB7, 0x42, 0x48, 0x29, 0x7F, 0xF0, 0x35, 0x3A, 0xC9, +0x08, 0xB0, 0x30, 0x0A, 0x0A, 0x0A, 0xAA, 0xA9, 0x22, 0x9F, 0x6F, 0x0F, 0xE1, 0x80, 0x06, 0xB7, +0x42, 0x9F, 0x6F, 0x0F, 0xE1, 0xE8, 0xC8, 0xC0, 0x06, 0x90, 0xF4, 0x68, 0x10, 0x12, 0xA9, 0xFF, +0x9F, 0x72, 0x0F, 0xE1, 0xA9, 0xAF, 0x9F, 0x70, 0x0F, 0xE1, 0xA9, 0x5C, 0x9F, 0x71, 0x0F, 0xE1, +0x82, 0x12, 0x00, 0x68, 0xA9, 0x30, 0x82, 0x81, 0xF9, 0xA0, 0x00, 0xD7, 0x42, 0xD0, 0x0B, 0xC8, +0xB7, 0x42, 0xD0, 0x06, 0xC8, 0x18, 0x9C, 0x4B, 0x0F, 0x60, 0xA9, 0x22, 0x82, 0x6B, 0xF9, 0xA9, +0x04, 0x20, 0xF9, 0x5C, 0xB0, 0xF3, 0xB7, 0x42, 0xF0, 0x19, 0xC9, 0x09, 0xB0, 0xD5, 0x0A, 0x0A, +0x0A, 0x1A, 0xAA, 0xA0, 0x08, 0xBF, 0x00, 0x58, 0xFF, 0x9F, 0x6D, 0x0F, 0xE1, 0xCA, 0x88, 0xD0, +0xF4, 0x80, 0xBD, 0x20, 0x5D, 0x56, 0x80, 0xB8, 0x20, 0x66, 0x5D, 0xB0, 0x0F, 0xB7, 0x42, 0xAA, +0xC8, 0xB7, 0x42, 0x9D, 0x57, 0x0F, 0xC8, 0xE8, 0xC6, 0x68, 0xD0, 0xF5, 0x82, 0xB6, 0xFF, 0x20, +0x66, 0x5D, 0xB0, 0x0F, 0xB7, 0x42, 0xAA, 0xBF, 0x42, 0x58, 0xFF, 0x9D, 0x57, 0x0F, 0xE8, 0xC6, +0x68, 0xD0, 0xF4, 0x82, 0x9F, 0xFF, 0xA0, 0x01, 0xB7, 0x42, 0xD0, 0x0F, 0x88, 0xB7, 0x42, 0x3A, +0x85, 0x68, 0xA0, 0x02, 0x18, 0x77, 0x42, 0xC9, 0x17, 0x90, 0x05, 0xA9, 0x22, 0x82, 0xFA, 0xF8, +0x9C, 0x4B, 0x0F, 0x60, 0xA9, 0x01, 0x20, 0xF9, 0x5C, 0xB0, 0xF0, 0xB7, 0x42, 0x29, 0x80, 0x8D, +0x50, 0x0F, 0x82, 0x70, 0xFF, 0xA9, 0x01, 0x20, 0xF9, 0x5C, 0xB0, 0xDF, 0xB7, 0x42, 0xF0, 0x0A, +0xC9, 0x0D, 0xB0, 0x06, 0x8D, 0x4F, 0x0F, 0x82, 0x5B, 0xFF, 0xA9, 0x32, 0x82, 0xCB, 0xF8, 0xA9, +0xE1, 0x48, 0xAB, 0xAD, 0x36, 0xC0, 0x29, 0xFB, 0x09, 0x80, 0x8D, 0x36, 0xC0, 0x86, 0x5A, 0xA9, +0x40, 0x8D, 0x31, 0xC0, 0xA5, 0x45, 0x29, 0x40, 0x8D, 0x1E, 0x0F, 0xA5, 0x45, 0x29, 0xBF, 0x85, +0x45, 0xA9, 0x0F, 0xA8, 0x8B, 0x20, 0x46, 0x65, 0xAB, 0xAD, 0xEC, 0xC0, 0xAD, 0xE9, 0xC0, 0x60, +0x9C, 0x28, 0x0F, 0xAE, 0x28, 0x0F, 0x20, 0x16, 0x5E, 0x20, 0xDA, 0x64, 0xB0, 0x14, 0xA9, 0x02, +0x20, 0xA4, 0x5F, 0x30, 0x0D, 0x20, 0x78, 0x5F, 0x20, 0xC4, 0x61, 0x24, 0x68, 0x10, 0x03, 0x20, +0xCC, 0x5E, 0xEE, 0x28, 0x0F, 0xAD, 0x28, 0x0F, 0xC9, 0x02, 0x90, 0xD7, 0x60, 0xAE, 0x28, 0x0F, +0x38, 0xBD, 0x20, 0x0F, 0xF0, 0x07, 0xBD, 0xEA, 0xC0, 0xAD, 0xE9, 0xC0, 0x18, 0x60, 0xAD, 0xE8, +0xC0, 0x60, 0x8D, 0x29, 0x0F, 0x5C, 0x87, 0x0F, 0xE1, 0xAE, 0x28, 0x0F, 0x3C, 0x22, 0x0F, 0x10, +0x05, 0x20, 0xA6, 0x5E, 0xB0, 0x32, 0x20, 0x78, 0x5F, 0x38, 0xAE, 0x28, 0x0F, 0xBD, 0x22, 0x0F, +0xED, 0x29, 0x0F, 0xF0, 0x12, 0xA0, 0x01, 0xB0, 0x06, 0xA0, 0x00, 0x49, 0xFF, 0x69, 0x01, 0xAA, +0x98, 0x20, 0xAE, 0x5F, 0x20, 0x71, 0x5E, 0xAE, 0x28, 0x0F, 0xAD, 0x29, 0x0F, 0x9D, 0x22, 0x0F, +0x20, 0x41, 0x60, 0x8D, 0x2C, 0x0F, 0x18, 0x60, 0xA9, 0x02, 0x0D, 0x44, 0x0F, 0x8D, 0x44, 0x0F, +0x60, 0xA9, 0x04, 0x20, 0xAE, 0x5F, 0x20, 0xA7, 0x5F, 0x10, 0xFB, 0xCA, 0xD0, 0xF3, 0xA2, 0x4F, +0xCA, 0xD0, 0xFD, 0x60, 0x48, 0x20, 0x89, 0x5E, 0x68, 0x85, 0x69, 0xAD, 0x36, 0xC0, 0x48, 0x29, +0x7F, 0x8D, 0x36, 0xC0, 0xA9, 0x64, 0x85, 0x68, 0xC6, 0x68, 0xEA, 0xD0, 0xFB, 0xC6, 0x69, 0xD0, +0xF3, 0x68, 0x8D, 0x36, 0xC0, 0x60, 0xA9, 0x01, 0x20, 0xAE, 0x5F, 0xA2, 0x50, 0x20, 0x71, 0x5E, +0xA2, 0x50, 0xA9, 0x07, 0x20, 0x89, 0x5E, 0xA9, 0x0A, 0x20, 0xA4, 0x5F, 0x10, 0x06, 0xCA, 0xD0, +0xF1, 0x38, 0x80, 0x01, 0x18, 0xAE, 0x28, 0x0F, 0x9E, 0x22, 0x0F, 0x60, 0xA9, 0x02, 0x20, 0xA4, +0x5F, 0x30, 0x4F, 0xA9, 0x09, 0x20, 0xAE, 0x5F, 0xA9, 0xC8, 0x20, 0x89, 0x5E, 0xA9, 0x03, 0x8D, +0x35, 0x0F, 0xAE, 0x28, 0x0F, 0x8E, 0x56, 0x0F, 0xA9, 0x0D, 0x20, 0xAE, 0x5F, 0xA9, 0xC3, 0x8D, +0x37, 0x0F, 0xA9, 0x0A, 0x20, 0x89, 0x5E, 0xA9, 0x02, 0x20, 0xA4, 0x5F, 0x30, 0x0F, 0xCE, 0x37, +0x0F, 0xD0, 0xEF, 0xCE, 0x35, 0x0F, 0xD0, 0xE0, 0xA9, 0x27, 0x82, 0x6D, 0xF7, 0xAE, 0x28, 0x0F, +0x38, 0x6E, 0x56, 0x0F, 0x38, 0x7E, 0x22, 0x0F, 0xA9, 0xFA, 0x9D, 0x26, 0x0F, 0xA9, 0x01, 0x20, +0x89, 0x5E, 0x18, 0x60, 0xA9, 0x0B, 0x20, 0xA4, 0x5F, 0x2C, 0xEE, 0xC0, 0x30, 0xFB, 0x60, 0x20, +0xA4, 0x5F, 0x2C, 0xEE, 0xC0, 0x10, 0xFB, 0x60, 0x08, 0xA2, 0x02, 0xBF, 0x75, 0x5F, 0xFF, 0x20, +0xA4, 0x5F, 0x0A, 0x66, 0x68, 0xCA, 0x10, 0xF3, 0x28, 0xA9, 0x2F, 0x24, 0x68, 0x70, 0x21, 0x08, +0xA5, 0x45, 0xF0, 0x15, 0xAD, 0x1E, 0x0F, 0xF0, 0x10, 0xA5, 0x68, 0x29, 0x20, 0xF0, 0x0A, 0xA9, +0x03, 0x20, 0xAE, 0x5F, 0x28, 0xA9, 0x2E, 0x80, 0x07, 0x28, 0x90, 0x08, 0x30, 0x05, 0xA9, 0x2B, +0x82, 0x07, 0xF7, 0x18, 0x60, 0x06, 0x02, 0x0C, 0xA9, 0x08, 0x20, 0xA4, 0x5F, 0x10, 0x14, 0x20, +0xB1, 0x5F, 0xAE, 0x28, 0x0F, 0xBD, 0x26, 0x0F, 0x20, 0x84, 0x5E, 0xA9, 0x19, 0x9D, 0x26, 0x0F, +0x20, 0x84, 0x5E, 0x60, 0xAD, 0x31, 0xC0, 0x29, 0x7F, 0x2C, 0x2B, 0x0F, 0x10, 0x02, 0x09, 0x80, +0x8D, 0x31, 0xC0, 0x60, 0x20, 0xB8, 0x5F, 0x2C, 0xED, 0xC0, 0xAD, 0xEE, 0xC0, 0x60, 0x20, 0xB8, +0x5F, 0x2C, 0xE7, 0xC0, 0x2C, 0xE6, 0xC0, 0x60, 0x2C, 0xE0, 0xC0, 0x2C, 0xE3, 0xC0, 0x2C, 0xE6, +0xC0, 0x2C, 0xE4, 0xC0, 0x4A, 0x90, 0x03, 0x2C, 0xE5, 0xC0, 0x4A, 0x48, 0xAD, 0x31, 0xC0, 0x29, +0x7F, 0x90, 0x02, 0x09, 0x80, 0x8D, 0x31, 0xC0, 0x68, 0x4A, 0x90, 0x03, 0x2C, 0xE1, 0xC0, 0x4A, +0xB0, 0x03, 0x2C, 0xE2, 0xC0, 0x60, 0xA5, 0x48, 0x29, 0x3F, 0x8D, 0x2A, 0x0F, 0xA5, 0x48, 0xA2, +0x06, 0x46, 0x49, 0x6A, 0xCA, 0xD0, 0xFA, 0xAE, 0x28, 0x0F, 0x3C, 0x24, 0x0F, 0x10, 0x03, 0x18, +0x69, 0x0D, 0xDA, 0xAA, 0xBF, 0x75, 0x60, 0xFF, 0x48, 0xBF, 0x4F, 0x60, 0xFF, 0xA8, 0x68, 0xFA, +0x18, 0xAE, 0x28, 0x0F, 0x6D, 0x2A, 0x0F, 0x48, 0x20, 0x3A, 0x60, 0x85, 0x68, 0x68, 0xC5, 0x68, +0x90, 0x06, 0xC8, 0xE5, 0x68, 0x4C, 0x17, 0x60, 0x8C, 0x29, 0x0F, 0x8D, 0x2A, 0x0F, 0x3C, 0x24, +0x0F, 0x10, 0x03, 0x4E, 0x29, 0x0F, 0x6E, 0x2B, 0x0F, 0x60, 0x98, 0x3C, 0x24, 0x0F, 0x10, 0x01, +0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x38, 0x8D, 0x2D, 0x0F, 0xA9, 0x0C, 0xED, 0x2D, 0x0F, 0x60, 0x00, +0x05, 0x0A, 0x10, 0x15, 0x1B, 0x21, 0x28, 0x2E, 0x35, 0x3C, 0x44, 0x4C, 0x00, 0x05, 0x0A, 0x10, +0x15, 0x1A, 0x20, 0x25, 0x2B, 0x31, 0x37, 0x3D, 0x43, 0x49, 0x50, 0x56, 0x5C, 0x63, 0x6A, 0x71, +0x78, 0x80, 0x88, 0x90, 0x98, 0x00, 0x04, 0x08, 0x00, 0x09, 0x07, 0x06, 0x00, 0x04, 0x03, 0x04, +0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x04, 0x08, 0x00, 0x09, 0x07, 0x05, 0x03, 0x01, 0x02, 0x06, +0x00, 0x04, 0x08, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x00, 0xAE, 0x28, 0x0F, +0x3C, 0x24, 0x0F, 0x10, 0x01, 0x1A, 0xAA, 0xC2, 0x10, 0xA6, 0x4A, 0xD0, 0x09, 0xA6, 0x48, 0xE0, +0x40, 0x06, 0xE2, 0x10, 0x90, 0x98, 0xE2, 0x10, 0xA9, 0x2D, 0x82, 0xBD, 0xF5, 0x20, 0x40, 0x03, +0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, +0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, +0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, +0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, +0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, +0xC0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, +0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, +0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, +0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, +0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, 0xC0, 0x00, 0x40, 0x80, +0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x6F, 0x0F, 0xE1, 0x20, 0x24, 0x5F, 0x20, 0x2D, 0x62, 0xA9, 0x07, +0x85, 0x68, 0xA0, 0x9E, 0xA2, 0x02, 0x88, 0xD0, 0x04, 0xC6, 0x68, 0x30, 0x49, 0xAD, 0xEC, 0xC0, +0x10, 0xFB, 0xDD, 0x69, 0x0F, 0xD0, 0xED, 0xCA, 0x10, 0xEC, 0xA0, 0x04, 0x64, 0x5B, 0xAE, 0xEC, +0xC0, 0x10, 0xFB, 0xBF, 0x00, 0x56, 0xFF, 0x99, 0x30, 0x0F, 0x45, 0x5B, 0x85, 0x5B, 0x88, 0x10, +0xED, 0xA8, 0xD0, 0x22, 0xAD, 0xEC, 0xC0, 0x10, 0xFB, 0xCD, 0x63, 0x0F, 0xD0, 0x18, 0xAD, 0xEC, +0xC0, 0x10, 0xFB, 0xCD, 0x62, 0x0F, 0xD0, 0x0E, 0xAE, 0x28, 0x0F, 0xAD, 0x31, 0x0F, 0x0A, 0x0A, +0x0A, 0x7E, 0x24, 0x0F, 0x18, 0x60, 0xA9, 0x20, 0x0C, 0x44, 0x0F, 0x38, 0x60, 0xA9, 0x01, 0x2C, +0x2B, 0x0F, 0x10, 0x02, 0xA9, 0x03, 0x20, 0xA4, 0x5F, 0xAD, 0xEC, 0xC0, 0xAD, 0xEC, 0xC0, 0x60, +0x5C, 0x77, 0x0F, 0xE1, 0x64, 0x5E, 0x64, 0x5D, 0x64, 0x5C, 0xA0, 0x19, 0xA2, 0x02, 0x88, 0xF0, +0x1B, 0xAD, 0xEC, 0xC0, 0x10, 0xFB, 0xDD, 0x58, 0x0F, 0xD0, 0xF1, 0xCA, 0x10, 0xF0, 0xAE, 0xEC, +0xC0, 0x10, 0xFB, 0xBF, 0x00, 0x56, 0xFF, 0xCD, 0x33, 0x0F, 0xF0, 0x03, 0x4C, 0x1E, 0x63, 0xA0, +0xAF, 0x4C, 0x8C, 0x62, 0xAE, 0xEC, 0xC0, 0x10, 0xFB, 0xBF, 0x00, 0x56, 0xFF, 0xA6, 0x66, 0x1F, +0x41, 0x61, 0xFF, 0x45, 0x5D, 0x99, 0x01, 0x0E, 0x65, 0x5C, 0x85, 0x5C, 0xAE, 0xEC, 0xC0, 0x10, +0xFB, 0xBF, 0x00, 0x56, 0xFF, 0x85, 0x66, 0x06, 0x5C, 0x90, 0x02, 0xE6, 0x5C, 0xAE, 0xEC, 0xC0, +0x10, 0xFB, 0xBF, 0x00, 0x56, 0xFF, 0xA6, 0x66, 0x1F, 0xC1, 0x60, 0xFF, 0x45, 0x5C, 0x99, 0x00, +0x0C, 0x65, 0x5E, 0xAE, 0xEC, 0xC0, 0x10, 0xFB, 0x85, 0x5E, 0xBF, 0x00, 0x56, 0xFF, 0xA6, 0x66, +0x1F, 0x01, 0x61, 0xFF, 0x45, 0x5E, 0x99, 0x00, 0x0D, 0x65, 0x5D, 0x85, 0x5D, 0x88, 0xD0, 0xA4, +0xAE, 0xEC, 0xC0, 0x10, 0xFB, 0xBF, 0x00, 0x56, 0xFF, 0xAA, 0xBF, 0x41, 0x61, 0xFF, 0x85, 0x66, +0xBF, 0x01, 0x61, 0xFF, 0x85, 0x67, 0xBF, 0xC1, 0x60, 0xFF, 0xA0, 0x02, 0xAE, 0xEC, 0xC0, 0x10, +0xFB, 0x29, 0xC0, 0x1F, 0x00, 0x56, 0xFF, 0xBB, 0xD5, 0x5C, 0xD0, 0x16, 0xB5, 0x65, 0x88, 0x10, +0xEB, 0xA0, 0x02, 0xAD, 0xEC, 0xC0, 0x10, 0xFB, 0xD9, 0x61, 0x0F, 0xD0, 0x09, 0x88, 0xD0, 0xF3, +0x18, 0x60, 0xA9, 0x10, 0xD0, 0x02, 0xA9, 0x08, 0x0D, 0x44, 0x0F, 0x8D, 0x44, 0x0F, 0x38, 0x60, +0xC2, 0x10, 0x64, 0x5E, 0x64, 0x5D, 0x64, 0x5C, 0x80, 0x0E, 0xB7, 0x42, 0x65, 0x5C, 0x85, 0x5C, +0xB7, 0x42, 0x45, 0x5D, 0x9D, 0x01, 0x0E, 0xC8, 0x06, 0x5C, 0x90, 0x02, 0xE6, 0x5C, 0xB7, 0x42, +0x65, 0x5E, 0x85, 0x5E, 0xB7, 0x42, 0x45, 0x5C, 0x9D, 0x00, 0x0C, 0xC8, 0xB7, 0x42, 0x65, 0x5D, +0x85, 0x5D, 0xB7, 0x42, 0x45, 0x5E, 0x9D, 0x00, 0x0D, 0xC8, 0xCA, 0xD0, 0xCD, 0xE2, 0x10, 0xA5, +0x5C, 0x4A, 0x4A, 0x45, 0x5D, 0x29, 0x3F, 0x45, 0x5D, 0x4A, 0x4A, 0x45, 0x5E, 0x29, 0x3F, 0x45, +0x5E, 0x4A, 0x4A, 0x85, 0x5F, 0xA9, 0x00, 0xEB, 0xAD, 0xAF, 0x0C, 0x85, 0x63, 0xC2, 0x20, 0x0A, +0x0A, 0xE2, 0x20, 0xAD, 0xAF, 0x0D, 0x85, 0x64, 0xC2, 0x20, 0x0A, 0x0A, 0xE2, 0x20, 0xAD, 0xAF, +0x0E, 0x85, 0x65, 0xC2, 0x20, 0x0A, 0x0A, 0xE2, 0x20, 0x60, 0x5C, 0x7F, 0x0F, 0xE1, 0x2C, 0xED, +0xC0, 0xA9, 0xFF, 0x8D, 0xEF, 0xC0, 0xA0, 0x07, 0xB9, 0x58, 0x0F, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, +0x8D, 0xED, 0xC0, 0x88, 0x10, 0xF2, 0xAE, 0x33, 0x0F, 0xBF, 0x00, 0x57, 0xFF, 0x09, 0x80, 0x2C, +0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0xA0, 0xAE, 0x80, 0x19, 0xA6, 0x65, 0xB9, 0x01, 0x0E, +0x85, 0x65, 0xC2, 0x20, 0x0A, 0x0A, 0xE2, 0x20, 0xBF, 0x00, 0x57, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, +0xFB, 0x8D, 0xED, 0xC0, 0xEB, 0xAA, 0xBF, 0x00, 0x57, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, +0xED, 0xC0, 0xA6, 0x63, 0xB9, 0x00, 0x0C, 0x85, 0x63, 0xC2, 0x20, 0x0A, 0x0A, 0xE2, 0x20, 0xBF, +0x00, 0x57, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0xA6, 0x64, 0xB9, 0x00, 0x0D, +0x85, 0x64, 0xC2, 0x20, 0x0A, 0x0A, 0xE2, 0x20, 0xBF, 0x00, 0x57, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, +0xFB, 0x8D, 0xED, 0xC0, 0x88, 0xC0, 0xFF, 0xD0, 0xA2, 0xA0, 0x03, 0xBB, 0xB5, 0x5C, 0x29, 0x3F, +0xAA, 0xBF, 0x00, 0x57, 0xFF, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0x88, 0x10, 0xEB, +0xA0, 0x02, 0xB9, 0x61, 0x0F, 0x2C, 0xEC, 0xC0, 0x10, 0xFB, 0x8D, 0xED, 0xC0, 0x88, 0x10, 0xF2, +0x2C, 0xEC, 0xC0, 0x70, 0xFB, 0x2C, 0xEE, 0xC0, 0x60, 0x08, 0xFB, 0x08, 0x18, 0xFB, 0xC2, 0x10, +0xE2, 0x20, 0xA0, 0x00, 0x00, 0xA2, 0xAB, 0x00, 0xAD, 0x51, 0x0F, 0xF0, 0x03, 0xA2, 0xAF, 0x00, +0xBD, 0x00, 0x0C, 0x97, 0x42, 0xC8, 0x20, 0x9D, 0x64, 0xB0, 0x17, 0xBD, 0x00, 0x0D, 0x97, 0x42, +0xC8, 0x20, 0x9D, 0x64, 0xB0, 0x0C, 0xBD, 0x00, 0x0E, 0x97, 0x42, 0xCA, 0xC8, 0x20, 0x9D, 0x64, +0x90, 0xDE, 0x5A, 0x68, 0xEB, 0x68, 0x28, 0xFB, 0x28, 0xA8, 0xEB, 0xAA, 0x60, 0xAD, 0x51, 0x0F, +0xD0, 0x05, 0xC0, 0x00, 0x02, 0x80, 0x03, 0xC0, 0x0C, 0x02, 0x60, 0xA9, 0x80, 0x8D, 0x24, 0x0F, +0x8D, 0x25, 0x0F, 0x9C, 0x20, 0x0F, 0x9C, 0x21, 0x0F, 0x9C, 0x39, 0x0F, 0xA2, 0x01, 0x8E, 0x28, +0x0F, 0x20, 0x16, 0x5E, 0x20, 0xDA, 0x64, 0xB0, 0x08, 0xEE, 0x39, 0x0F, 0xA9, 0x40, 0x9D, 0x20, +0x0F, 0xCA, 0x8E, 0x28, 0x0F, 0x10, 0xEA, 0x4C, 0x1E, 0x5E, 0xA9, 0x00, 0x20, 0xAE, 0x5F, 0x20, +0xA4, 0x5F, 0x30, 0x15, 0xA9, 0x01, 0x20, 0xAE, 0x5F, 0x20, 0xA4, 0x5F, 0x10, 0x0B, 0xA9, 0x00, +0x20, 0xAE, 0x5F, 0x20, 0xA4, 0x5F, 0x18, 0x10, 0x01, 0x38, 0x60, 0x18, 0xFB, 0x08, 0xC2, 0x30, +0xA0, 0x00, 0x00, 0xA9, 0x1E, 0x0F, 0x97, 0x42, 0xC8, 0xC8, 0xA9, 0xE1, 0x00, 0x97, 0x42, 0x28, +0xC8, 0xC8, 0xBB, 0xA0, 0x00, 0x9C, 0x4B, 0x0F, 0xFB, 0x18, 0x60, 0x18, 0xFB, 0x08, 0xC2, 0x30, +0xA0, 0x00, 0x00, 0xA9, 0x00, 0x0C, 0x97, 0x42, 0xC8, 0xC8, 0xA9, 0xE1, 0x00, 0x97, 0x42, 0x80, +0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x4C, 0x6F, 0x70, 0x4C, 0x62, 0x68, 0x4C, 0x54, 0x6A, 0xA9, 0x60, 0xAA, 0x86, 0x2B, 0x85, 0x4F, +0xBD, 0x8E, 0xC0, 0xBD, 0x8C, 0xC0, 0xB9, 0xEA, 0xC0, 0xBD, 0x89, 0xC0, 0xA0, 0x50, 0xBD, 0x80, +0xC0, 0x98, 0x29, 0x03, 0x0A, 0x05, 0x2B, 0xAA, 0xBD, 0x81, 0xC0, 0xA9, 0x56, 0x08, 0x78, 0x20, +0xA8, 0xFC, 0x28, 0x88, 0x10, 0xE8, 0x85, 0x26, 0x85, 0x3D, 0x85, 0x41, 0x18, 0xA0, 0x32, 0xBD, +0x8C, 0xC0, 0x30, 0x04, 0x88, 0x10, 0xF8, 0x38, 0x08, 0xA2, 0x03, 0xA0, 0x00, 0x86, 0x3C, 0x8A, +0x0A, 0x24, 0x3C, 0xF0, 0x11, 0x05, 0x3C, 0x49, 0xFF, 0x29, 0x7E, 0xB0, 0x09, 0x4A, 0xD0, 0xFB, +0x98, 0x9F, 0x56, 0x03, 0x00, 0xC8, 0xE8, 0x10, 0xE4, 0xA9, 0x08, 0x85, 0x27, 0xA0, 0x7F, 0x28, +0x6B, 0xA9, 0x00, 0x8F, 0xB1, 0x0F, 0xE1, 0x4C, 0x16, 0x70, 0x20, 0x84, 0x69, 0xA2, 0x60, 0xA0, +0x07, 0x20, 0x54, 0x6A, 0x20, 0x42, 0x6F, 0xBD, 0x8A, 0xC0, 0xBD, 0x89, 0xC0, 0xBD, 0x88, 0xC0, +0x20, 0xC8, 0x68, 0x20, 0x42, 0x6F, 0xBD, 0x8A, 0xC0, 0xBD, 0x89, 0xC0, 0xA0, 0x8C, 0xBD, 0x8E, +0xC0, 0x30, 0x07, 0x88, 0xD0, 0xF8, 0x38, 0x4C, 0xFD, 0x66, 0xBD, 0x81, 0xC0, 0xA0, 0x05, 0xA9, +0xFF, 0x9D, 0x8F, 0xC0, 0xB9, 0xE7, 0xC5, 0x1E, 0x8C, 0xC0, 0x90, 0xFB, 0x9D, 0x8D, 0xC0, 0x88, +0x10, 0xF2, 0xA5, 0x60, 0x09, 0x80, 0x20, 0x90, 0x68, 0x20, 0x8E, 0x68, 0xA5, 0x61, 0x20, 0x90, +0x68, 0x20, 0x8E, 0x68, 0x20, 0x8E, 0x68, 0xA5, 0x4F, 0x09, 0x80, 0x20, 0x90, 0x68, 0xA5, 0x4E, +0x09, 0x80, 0x20, 0x90, 0x68, 0xA5, 0x4F, 0xF0, 0x10, 0xA0, 0xFF, 0xA5, 0x5F, 0x20, 0x10, 0x67, +0xC8, 0xB7, 0x57, 0x09, 0x80, 0xC4, 0x4F, 0x90, 0xF4, 0xA5, 0x4E, 0xD0, 0x03, 0x4C, 0xCD, 0x66, +0xA0, 0x00, 0xA5, 0x41, 0x20, 0x10, 0x67, 0xA5, 0x50, 0x09, 0x80, 0x20, 0x10, 0x67, 0xB7, 0x5B, +0x85, 0x50, 0x0A, 0x26, 0x41, 0xC8, 0xD0, 0x04, 0xE6, 0x5C, 0x80, 0x02, 0x48, 0x68, 0xA9, 0x02, +0x05, 0x41, 0x85, 0x41, 0xA5, 0x51, 0x09, 0x80, 0x20, 0x10, 0x67, 0xB7, 0x5B, 0x85, 0x51, 0x0A, +0x26, 0x41, 0xC8, 0xA5, 0x52, 0x09, 0x80, 0x20, 0x10, 0x67, 0xB7, 0x5B, 0x85, 0x52, 0x0A, 0x26, +0x41, 0xC8, 0xA5, 0x53, 0x09, 0x80, 0x20, 0x10, 0x67, 0xB7, 0x5B, 0x85, 0x53, 0x0A, 0x26, 0x41, +0xC8, 0xD0, 0x04, 0xE6, 0x5C, 0x80, 0x02, 0x48, 0x68, 0xA5, 0x54, 0x09, 0x80, 0x20, 0x10, 0x67, +0xB7, 0x5B, 0x85, 0x54, 0x0A, 0x26, 0x41, 0xC8, 0xA5, 0x55, 0x09, 0x80, 0x20, 0x10, 0x67, 0xB7, +0x5B, 0x85, 0x55, 0x0A, 0x26, 0x41, 0xC8, 0xA5, 0x56, 0x09, 0x80, 0x20, 0x10, 0x67, 0xB7, 0x5B, +0x85, 0x56, 0x0A, 0x26, 0x41, 0xC8, 0xC6, 0x4E, 0xF0, 0x03, 0x4C, 0x42, 0x66, 0xA5, 0x40, 0x09, +0xAA, 0x20, 0x10, 0x67, 0xA5, 0x40, 0x4A, 0x09, 0xAA, 0x20, 0x90, 0x68, 0xA9, 0xC8, 0x20, 0x90, +0x68, 0xBD, 0x8C, 0xC0, 0x29, 0x40, 0xD0, 0xF9, 0x9D, 0x8D, 0xC0, 0xA0, 0x1C, 0x88, 0xD0, 0x07, +0xA9, 0x01, 0xA2, 0x60, 0x38, 0xB0, 0x06, 0xBD, 0x8E, 0xC0, 0x30, 0xF1, 0x18, 0xBD, 0x80, 0xC0, +0xBD, 0x8C, 0xC0, 0x4B, 0xAB, 0x60, 0x20, 0x0B, 0x67, 0xEA, 0xEA, 0xEA, 0x60, 0x4C, 0xF2, 0x66, +0x1E, 0x8C, 0xC0, 0x90, 0xFB, 0x9D, 0x8D, 0xC0, 0x60, 0xA9, 0x00, 0x85, 0x40, 0xA5, 0x57, 0x85, +0x5B, 0xA5, 0x58, 0x85, 0x5C, 0xA5, 0x59, 0x85, 0x5D, 0x20, 0xC8, 0x68, 0x20, 0x42, 0x6F, 0xBD, +0x8D, 0xC0, 0xBD, 0x8E, 0xC0, 0x30, 0x07, 0x20, 0x62, 0x68, 0xA2, 0x60, 0x80, 0xF4, 0xBD, 0x81, +0xC0, 0xA0, 0x00, 0xAF, 0xEC, 0xC0, 0xE1, 0x88, 0xF0, 0xC3, 0xC9, 0xC3, 0xD0, 0xF5, 0xA0, 0x06, +0x20, 0x57, 0x68, 0x29, 0x7F, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0x99, 0x4E, 0x00, 0x49, 0x80, 0x45, +0x40, 0x85, 0x40, 0x88, 0x10, 0xEA, 0xA5, 0x4F, 0xF0, 0x27, 0x18, 0x65, 0x57, 0x85, 0x5B, 0xA5, +0x58, 0x69, 0x00, 0x85, 0x5C, 0xA0, 0x00, 0x20, 0x57, 0x68, 0x0A, 0x85, 0x41, 0x20, 0x57, 0x68, +0x06, 0x41, 0xB0, 0x02, 0x49, 0x80, 0x97, 0x57, 0x45, 0x40, 0x85, 0x40, 0xC8, 0xC4, 0x4F, 0x90, +0xEC, 0xA0, 0x00, 0xA5, 0x4E, 0x48, 0xD0, 0x03, 0x4C, 0x1F, 0x68, 0x20, 0x57, 0x68, 0x85, 0x5F, +0x4A, 0x4A, 0x4A, 0x29, 0x0F, 0xAA, 0xA5, 0x5F, 0x29, 0x07, 0x85, 0x5F, 0x20, 0x57, 0x68, 0x5F, +0xA7, 0xC5, 0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0xD0, 0x02, 0xE6, 0x5C, 0x20, 0x57, +0x68, 0x5F, 0xB7, 0xC5, 0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0x20, 0x57, 0x68, 0x5F, +0xC7, 0xC5, 0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0x20, 0x57, 0x68, 0x5F, 0xD7, 0xC5, +0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0xD0, 0x02, 0xE6, 0x5C, 0xA6, 0x5F, 0x20, 0x57, +0x68, 0x5F, 0xB7, 0xC5, 0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0x20, 0x57, 0x68, 0x5F, +0xC7, 0xC5, 0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0x20, 0x57, 0x68, 0x5F, 0xD7, 0xC5, +0x00, 0x97, 0x5B, 0x45, 0x40, 0x85, 0x40, 0xC8, 0xC6, 0x4E, 0xF0, 0x03, 0x4C, 0x9B, 0x67, 0x20, +0x57, 0x68, 0x85, 0x5F, 0x68, 0x85, 0x4E, 0x20, 0x57, 0x68, 0x38, 0x2A, 0x25, 0x5F, 0x45, 0x40, +0xAA, 0x20, 0x57, 0x68, 0xC9, 0xC8, 0xD0, 0x16, 0x8A, 0xAA, 0xD0, 0x16, 0x20, 0x42, 0x6F, 0xAD, +0xED, 0xC0, 0xAD, 0xEE, 0xC0, 0x30, 0xFB, 0xAD, 0xE0, 0xC0, 0x18, 0x4B, 0xAB, 0x60, 0xA9, 0x20, +0xD0, 0x02, 0xA9, 0x10, 0x38, 0x80, 0xF4, 0xF4, 0xE1, 0xFF, 0xAB, 0xAD, 0xEC, 0xC0, 0x10, 0xFB, +0xAB, 0x60, 0xAD, 0xC5, 0x0F, 0x29, 0x04, 0xD0, 0x24, 0x20, 0x8C, 0x6F, 0x20, 0x70, 0x6F, 0xAD, +0xC8, 0x0F, 0x8D, 0x36, 0xC0, 0x58, 0xEA, 0x78, 0xAD, 0x36, 0xC0, 0x8D, 0xC8, 0x0F, 0x29, 0xFB, +0x09, 0x80, 0x8D, 0x36, 0xC0, 0xE2, 0x30, 0x20, 0x4D, 0x6F, 0x20, 0x9F, 0x6F, 0x60, 0xA9, 0x80, +0xBC, 0x8C, 0xC0, 0x10, 0xFB, 0x9D, 0x8D, 0xC0, 0x45, 0x40, 0x85, 0x40, 0x60, 0x20, 0xD6, 0x68, +0x20, 0x42, 0x6F, 0xBD, 0x81, 0xC0, 0xBD, 0x85, 0xC0, 0xA0, 0x50, 0x20, 0xB5, 0x68, 0x20, 0xD6, +0x68, 0x4B, 0xAB, 0xA0, 0x0A, 0x20, 0xBC, 0x68, 0x88, 0xD0, 0xFA, 0x60, 0xA2, 0xBB, 0xCA, 0xEA, +0x80, 0x00, 0xEA, 0x80, 0x00, 0xD0, 0xF7, 0x60, 0xA2, 0x60, 0x20, 0x42, 0x6F, 0xBD, 0x83, 0xC0, +0xBD, 0x87, 0xC0, 0x4B, 0xAB, 0x60, 0xA2, 0x60, 0x20, 0x42, 0x6F, 0xBD, 0x80, 0xC0, 0xBD, 0x82, +0xC0, 0xBD, 0x84, 0xC0, 0xBD, 0x86, 0xC0, 0x4B, 0xAB, 0x60, 0xA9, 0x05, 0xA0, 0x00, 0x20, 0x13, +0x69, 0x90, 0x09, 0xA9, 0x80, 0x8F, 0xFD, 0x06, 0x00, 0x20, 0x1A, 0x6E, 0x60, 0x20, 0x13, 0x69, +0x90, 0xFA, 0x20, 0xF3, 0x68, 0x4B, 0xAB, 0xAF, 0xB9, 0x0F, 0xE1, 0x85, 0x50, 0xAF, 0xBA, 0x0F, +0xE1, 0x85, 0x51, 0xA9, 0xE8, 0xA0, 0x03, 0x8F, 0xB1, 0x0F, 0xE1, 0x98, 0x8F, 0xB3, 0x0F, 0xE1, +0xA5, 0x50, 0x8F, 0xB9, 0x0F, 0xE1, 0xA5, 0x51, 0x8F, 0xBA, 0x0F, 0xE1, 0x20, 0xBA, 0x65, 0xAF, +0xB9, 0x0F, 0xE1, 0x85, 0x50, 0xAF, 0xBA, 0x0F, 0xE1, 0x85, 0x51, 0x90, 0x0F, 0x8B, 0x20, 0x42, +0x6F, 0xCE, 0xB1, 0x0F, 0xD0, 0x07, 0xCE, 0xB3, 0x0F, 0x10, 0x02, 0xAB, 0x60, 0xAB, 0x80, 0xD0, +0xA9, 0x05, 0x8F, 0xB1, 0x0F, 0xE1, 0x20, 0x19, 0x67, 0x90, 0x13, 0xA0, 0x01, 0x20, 0xB5, 0x68, +0x20, 0xF2, 0x66, 0xAF, 0xB1, 0x0F, 0xE1, 0x3A, 0x8F, 0xB1, 0x0F, 0xE1, 0xD0, 0xE8, 0x60, 0x00, +0x24, 0x49, 0x00, 0x04, 0x01, 0x00, 0x01, 0x02, 0x04, 0x09, 0x12, 0x00, 0x01, 0x02, 0x04, 0x01, +0x02, 0x00, 0x7F, 0xFF, 0xA6, 0x51, 0xF0, 0x17, 0xA5, 0x58, 0x85, 0x5C, 0xA9, 0x80, 0xE0, 0x01, +0xF0, 0x04, 0xE6, 0x5C, 0xA9, 0x00, 0x18, 0x65, 0x57, 0x85, 0x5B, 0x90, 0x02, 0xE6, 0x5C, 0xBD, +0x6F, 0x69, 0x85, 0x4E, 0xBD, 0x72, 0x69, 0x85, 0x4F, 0xA2, 0x05, 0xA5, 0x50, 0x85, 0x5F, 0x29, +0x07, 0xA8, 0x06, 0x5F, 0x90, 0x15, 0xBD, 0x7B, 0x69, 0x18, 0x65, 0x4F, 0xC9, 0x07, 0x90, 0x02, +0xE9, 0x07, 0x85, 0x4F, 0xBD, 0x75, 0x69, 0x65, 0x4E, 0x85, 0x4E, 0xCA, 0x30, 0x06, 0xD0, 0xE2, +0x98, 0x4C, 0xB9, 0x69, 0xA5, 0x58, 0x48, 0xA9, 0x00, 0xA6, 0x51, 0xF0, 0x16, 0xBC, 0x81, 0x69, +0x57, 0x57, 0x57, 0x5B, 0x88, 0xD0, 0xF9, 0x57, 0x57, 0x57, 0x5B, 0xE0, 0x01, 0xF0, 0x02, 0xE6, +0x58, 0xE6, 0x58, 0xA4, 0x50, 0xF0, 0x09, 0x57, 0x57, 0x57, 0x57, 0x88, 0xD0, 0xFB, 0x57, 0x57, +0x85, 0x40, 0x68, 0x85, 0x58, 0xA4, 0x4F, 0x88, 0xA9, 0x00, 0x85, 0x5F, 0xB7, 0x57, 0x0A, 0x66, +0x5F, 0x88, 0x10, 0xF8, 0x38, 0x66, 0x5F, 0xA5, 0x4F, 0x18, 0x65, 0x57, 0x85, 0x5B, 0xA5, 0x58, +0x69, 0x00, 0x85, 0x5C, 0xA5, 0x59, 0x69, 0x00, 0x85, 0x5D, 0xA5, 0x5A, 0x69, 0x00, 0x85, 0x5E, +0x20, 0x47, 0x6F, 0xA0, 0x06, 0x38, 0xB7, 0x5B, 0x99, 0x50, 0x00, 0x30, 0x01, 0x18, 0x66, 0x41, +0x88, 0x10, 0xF2, 0x4B, 0xAB, 0x38, 0x66, 0x41, 0xA5, 0x5B, 0x18, 0x69, 0x07, 0x85, 0x5B, 0x90, +0x02, 0xE6, 0x5C, 0x60, 0x20, 0x42, 0x6F, 0xAD, 0xE8, 0xC0, 0xAD, 0xED, 0xC0, 0x80, 0x04, 0x98, +0x8D, 0xEF, 0xC0, 0x98, 0x4D, 0xEE, 0xC0, 0x29, 0x1F, 0xD0, 0xF4, 0x4B, 0xAB, 0x60, 0xA2, 0x60, +0x20, 0x42, 0x6F, 0xBD, 0x8E, 0xC0, 0xBD, 0x8D, 0xC0, 0xBD, 0x8E, 0xC0, 0x29, 0x20, 0xD0, 0xF9, +0xBD, 0x8C, 0xC0, 0x5A, 0xA0, 0xD9, 0x88, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xD0, 0xF7, 0x7A, +0x4B, 0xAB, 0x60, 0xA5, 0x4E, 0xA8, 0xA2, 0x00, 0x86, 0x4E, 0xA2, 0x03, 0x0A, 0x26, 0x4E, 0xCA, +0xD0, 0xFA, 0x18, 0x65, 0x4F, 0x90, 0x02, 0xE6, 0x4E, 0x84, 0x4F, 0x38, 0xE5, 0x4F, 0xB0, 0x02, +0xC6, 0x4E, 0xA4, 0x4E, 0x60, 0x4B, 0xAB, 0x90, 0x03, 0x4C, 0xC8, 0x6F, 0xD8, 0xAF, 0xB0, 0x0F, +0xE1, 0x30, 0x28, 0xC2, 0x20, 0xA3, 0x07, 0x8F, 0xB4, 0x0F, 0xE1, 0x85, 0x57, 0x64, 0x59, 0xA0, +0x01, 0xE2, 0x20, 0xB7, 0x57, 0x29, 0x40, 0x08, 0x68, 0xC2, 0x20, 0x29, 0x02, 0x00, 0x49, 0x02, +0x00, 0x18, 0x69, 0x03, 0x00, 0x63, 0x07, 0x83, 0x07, 0xE2, 0x20, 0x08, 0xA3, 0x01, 0x8F, 0xC5, +0x0F, 0xE1, 0x78, 0x20, 0x4D, 0x6F, 0x20, 0x6E, 0x6A, 0xAF, 0xFD, 0x06, 0x00, 0xC9, 0xA5, 0xD0, +0x10, 0xAF, 0xB6, 0x0F, 0xE1, 0xC9, 0xA5, 0xD0, 0x08, 0x49, 0xFF, 0x4F, 0xB7, 0x0F, 0xE1, 0xF0, +0x05, 0xA9, 0x00, 0x20, 0x1A, 0x6E, 0xAF, 0xB0, 0x0F, 0xE1, 0x10, 0x0F, 0xA2, 0x05, 0xB5, 0x42, +0x95, 0x45, 0xCA, 0x10, 0xF9, 0x64, 0x4B, 0x64, 0x4C, 0x64, 0x4D, 0xA5, 0x46, 0x2A, 0x08, 0x2A, +0x2A, 0x28, 0x2A, 0x29, 0x03, 0x49, 0x02, 0xAA, 0xE8, 0x86, 0x46, 0x64, 0x59, 0xAF, 0xB0, 0x0F, +0xE1, 0x10, 0x03, 0x4C, 0x1C, 0x6C, 0xA0, 0x01, 0xB7, 0x57, 0x85, 0x45, 0xC8, 0xC2, 0x30, 0xB7, +0x57, 0xAA, 0xE2, 0x20, 0x24, 0x45, 0x50, 0x08, 0xC2, 0x20, 0xC8, 0xC8, 0xB7, 0x57, 0x85, 0x59, +0x86, 0x57, 0xE2, 0x30, 0xA5, 0x45, 0x29, 0xBF, 0xAA, 0xA9, 0x01, 0xE0, 0x0A, 0x90, 0x03, 0x4C, +0x7E, 0x6D, 0xA0, 0x00, 0xB7, 0x57, 0x85, 0x60, 0xC8, 0xB7, 0x57, 0x85, 0x46, 0xC2, 0x20, 0xA5, +0x45, 0x85, 0x42, 0xE2, 0x20, 0xA2, 0x0B, 0xA0, 0x0B, 0x70, 0x02, 0xA0, 0x08, 0xB7, 0x57, 0x95, +0x42, 0xCA, 0x88, 0xC0, 0x01, 0xD0, 0xF6, 0x50, 0x10, 0xC2, 0x30, 0xA6, 0x42, 0xA5, 0x44, 0x85, +0x42, 0xA5, 0x45, 0x85, 0x43, 0x86, 0x45, 0xE2, 0x30, 0x4B, 0xAB, 0xA5, 0x46, 0xD0, 0x6D, 0x24, +0x45, 0x70, 0x03, 0x20, 0xC2, 0x6D, 0xA5, 0x45, 0x29, 0xBF, 0xAA, 0xBF, 0x9D, 0xC5, 0x00, 0x29, +0x7F, 0xA8, 0xA9, 0x04, 0xC4, 0x60, 0xD0, 0xA7, 0xE0, 0x05, 0xD0, 0x15, 0xA9, 0xFF, 0x8F, 0xB6, +0x0F, 0xE1, 0xA9, 0x00, 0x20, 0x1A, 0x6E, 0xA9, 0x00, 0x20, 0x42, 0x6F, 0x4C, 0xA4, 0x6D, 0x80, +0x8E, 0x8A, 0xD0, 0x21, 0xA9, 0x21, 0xA6, 0x48, 0xD0, 0x85, 0x8A, 0xA0, 0x07, 0x97, 0x42, 0x88, +0xD0, 0xFB, 0xAF, 0xB8, 0x0F, 0xE1, 0x97, 0x42, 0xC8, 0xA9, 0x00, 0x97, 0x42, 0xA9, 0x08, 0x88, +0x20, 0x38, 0x6F, 0x80, 0xD2, 0xC9, 0x04, 0xD0, 0x0B, 0xA6, 0x48, 0xF0, 0x0B, 0xCA, 0xF0, 0x08, +0xA9, 0x21, 0xD0, 0xCB, 0xA9, 0x11, 0xD0, 0xC7, 0xA9, 0x1F, 0xD0, 0xC3, 0xAF, 0xB8, 0x0F, 0xE1, +0xAA, 0xA9, 0x28, 0xE4, 0x46, 0x90, 0xEB, 0xA9, 0x09, 0x85, 0x50, 0x64, 0x51, 0xA9, 0x45, 0x85, +0x57, 0x64, 0x58, 0x64, 0x59, 0x64, 0x5A, 0xAF, 0xB0, 0x0F, 0xE1, 0x10, 0x12, 0xA6, 0x45, 0xBF, +0x9D, 0xC5, 0x00, 0x29, 0x7F, 0x85, 0x60, 0xA5, 0x45, 0xD0, 0x04, 0x85, 0x48, 0x85, 0x49, 0xA5, +0x60, 0xA6, 0x46, 0x86, 0x60, 0x85, 0x46, 0x8A, 0xC9, 0x05, 0xB0, 0x4E, 0xCA, 0x20, 0x42, 0x6F, +0xBD, 0xC0, 0x0F, 0x85, 0x60, 0xCD, 0xBF, 0x0F, 0xB0, 0x40, 0x24, 0x45, 0x70, 0x03, 0x20, 0xC2, +0x6D, 0xA5, 0x60, 0xCD, 0xBC, 0x0F, 0xF0, 0x16, 0xCD, 0xBD, 0x0F, 0xF0, 0x25, 0x20, 0xB2, 0x6F, +0x20, 0x00, 0x56, 0x85, 0x50, 0x8E, 0xB4, 0x0F, 0x8C, 0xB5, 0x0F, 0x4C, 0x58, 0x6D, 0x20, 0xB2, +0x6F, 0x20, 0xAA, 0x70, 0xA5, 0x51, 0x8F, 0xB4, 0x0F, 0xE1, 0xA5, 0x52, 0x8F, 0xB5, 0x0F, 0xE1, +0x80, 0xE9, 0x20, 0xB2, 0x6F, 0x20, 0x12, 0x71, 0x80, 0xEA, 0xA5, 0x45, 0x29, 0x40, 0x09, 0x80, +0x85, 0x61, 0x20, 0xD6, 0x68, 0x20, 0xFD, 0x68, 0xB0, 0x61, 0xC2, 0x20, 0xA5, 0x47, 0x85, 0x57, +0x64, 0x59, 0xE2, 0x20, 0x24, 0x45, 0x50, 0x13, 0xC2, 0x20, 0xA5, 0x42, 0x85, 0x57, 0xE2, 0x20, +0xA5, 0x47, 0xEB, 0xA5, 0x44, 0xC2, 0x20, 0x85, 0x59, 0xE2, 0x20, 0xA5, 0x45, 0x29, 0xBF, 0xAA, +0xBD, 0x9D, 0xC5, 0x10, 0x3D, 0xE0, 0x04, 0xD0, 0x17, 0xA0, 0x01, 0xB7, 0x57, 0xAA, 0x88, 0xB7, +0x57, 0x48, 0x18, 0xA9, 0x02, 0x65, 0x57, 0x85, 0x57, 0x68, 0x90, 0x12, 0xE6, 0x58, 0x80, 0x0E, +0xE0, 0x02, 0xD0, 0x06, 0xA9, 0x00, 0xA2, 0x02, 0xD0, 0x04, 0xA6, 0x4A, 0xA5, 0x49, 0x86, 0x51, +0x85, 0x50, 0xA9, 0x82, 0x85, 0x61, 0x20, 0xEA, 0x68, 0x90, 0x07, 0x20, 0x42, 0x6F, 0xA9, 0x06, +0xD0, 0x5C, 0xAF, 0xB0, 0x0F, 0xE1, 0x10, 0x0C, 0xA5, 0x45, 0xD0, 0x08, 0xA9, 0x48, 0xA2, 0x00, +0x85, 0x57, 0x86, 0x58, 0x20, 0x50, 0x69, 0x90, 0x16, 0xAF, 0xC7, 0x0F, 0xE1, 0x3A, 0x8F, 0xC7, +0x0F, 0xE1, 0xF0, 0xD7, 0xA5, 0x60, 0xA6, 0x46, 0x86, 0x60, 0x85, 0x46, 0x82, 0xD8, 0xFE, 0x20, +0x93, 0x6A, 0x20, 0x38, 0x6F, 0x20, 0x42, 0x6F, 0xA5, 0x45, 0xD0, 0x20, 0xAD, 0xB0, 0x0F, 0x10, +0x1B, 0xA5, 0x49, 0x8D, 0xB4, 0x0F, 0xA5, 0x4A, 0x8D, 0xB5, 0x0F, 0xA5, 0x48, 0x4A, 0x4A, 0x4A, +0x90, 0x04, 0xA9, 0x2B, 0x80, 0x08, 0x4A, 0x4A, 0xA9, 0x2F, 0x90, 0x02, 0xA5, 0x50, 0x20, 0x42, +0x6F, 0x8D, 0xB1, 0x0F, 0xAA, 0xF0, 0x1D, 0x48, 0xAD, 0xB0, 0x0F, 0x2A, 0x68, 0x90, 0x15, 0xA2, +0x00, 0xC9, 0x40, 0xB0, 0x0E, 0xA2, 0x27, 0xC9, 0x2B, 0xF0, 0x09, 0xC9, 0x28, 0xF0, 0x05, 0xC9, +0x2F, 0xF0, 0x01, 0x8A, 0x8D, 0xB2, 0x0F, 0x8B, 0x20, 0xE7, 0x6D, 0x20, 0x70, 0x6F, 0xAB, 0x28, +0xAD, 0xB4, 0x0F, 0xAA, 0xAD, 0xB2, 0x0F, 0x48, 0xAD, 0xB5, 0x0F, 0xA8, 0x18, 0x68, 0xF0, 0x01, +0x38, 0x6B, 0xA5, 0x45, 0xC9, 0x08, 0xB0, 0x04, 0x64, 0x4C, 0x64, 0x4D, 0xC2, 0x20, 0xA5, 0x47, +0x85, 0x42, 0xA5, 0x49, 0x85, 0x48, 0xA5, 0x4B, 0x85, 0x4A, 0xA5, 0x4C, 0x85, 0x4B, 0xE2, 0x30, +0x64, 0x47, 0x64, 0x44, 0x64, 0x4D, 0x60, 0x20, 0x42, 0x6F, 0xAD, 0xE8, 0xC0, 0x2C, 0xED, 0xC0, +0xA9, 0x2B, 0x8D, 0xEF, 0xC0, 0xA0, 0x05, 0x88, 0xD0, 0xFD, 0xAD, 0xEE, 0xC0, 0x29, 0x20, 0xD0, +0xF9, 0xA0, 0x00, 0xA2, 0x60, 0x20, 0x54, 0x6A, 0x20, 0x42, 0x6F, 0xAD, 0xEC, 0xC0, 0xAD, 0xE2, +0xC0, 0xAD, 0xE6, 0xC0, 0xAD, 0xE8, 0xC0, 0x4B, 0xAB, 0x60, 0x48, 0x20, 0x9D, 0x68, 0x68, 0xAA, +0xA5, 0x45, 0x48, 0xA5, 0x46, 0x48, 0xA5, 0x48, 0x48, 0xA5, 0x60, 0x48, 0x86, 0x48, 0xA9, 0x05, +0x85, 0x45, 0x64, 0x60, 0xA9, 0x02, 0x85, 0x46, 0xAF, 0xFD, 0x06, 0x00, 0xC9, 0xA5, 0xF0, 0x08, +0xAF, 0xBF, 0x0F, 0xE1, 0x85, 0x60, 0x80, 0x4B, 0xA9, 0x00, 0xAA, 0x9F, 0xBC, 0x0F, 0xE1, 0xE8, +0xE0, 0x04, 0xD0, 0xF7, 0x8A, 0x9F, 0xBF, 0x0F, 0xE1, 0xCA, 0xD0, 0xF8, 0xE6, 0x60, 0x20, 0xAA, +0x70, 0xB0, 0x08, 0xA5, 0x60, 0x8F, 0xBC, 0x0F, 0xE1, 0xE6, 0x60, 0xA6, 0x60, 0xA9, 0x01, 0x20, +0x12, 0x71, 0xB0, 0x08, 0xA5, 0x60, 0x8F, 0xBD, 0x0F, 0xE1, 0xE6, 0x60, 0xA5, 0x60, 0x8F, 0xBE, +0x0F, 0xE1, 0x80, 0x02, 0xE6, 0x60, 0xA6, 0x60, 0xDA, 0xA9, 0x01, 0x20, 0x00, 0x56, 0xFA, 0x86, +0x60, 0x90, 0xF1, 0xA9, 0x45, 0x85, 0x57, 0x64, 0x58, 0x64, 0x59, 0xA5, 0x45, 0x29, 0x40, 0x09, +0x80, 0x85, 0x61, 0x20, 0xD6, 0x68, 0xA5, 0x60, 0x8F, 0xBF, 0x0F, 0xE1, 0x80, 0x02, 0xE6, 0x60, +0xA9, 0x09, 0x85, 0x50, 0x64, 0x51, 0x20, 0xBA, 0x65, 0x90, 0x05, 0xC6, 0x60, 0x4C, 0xC7, 0x6E, +0x20, 0x19, 0x67, 0xA5, 0x50, 0xF0, 0xE7, 0x20, 0x42, 0x6F, 0xA5, 0x60, 0x8D, 0xB8, 0x0F, 0x68, +0x85, 0x60, 0x68, 0x85, 0x48, 0x68, 0x85, 0x46, 0x68, 0x85, 0x45, 0xA9, 0xA5, 0x8D, 0xB6, 0x0F, +0x49, 0xFF, 0x8D, 0xB7, 0x0F, 0xA9, 0xA5, 0xCF, 0xFD, 0x06, 0x00, 0x8F, 0xFD, 0x06, 0x00, 0xD0, +0x46, 0xA2, 0x01, 0xAD, 0xB8, 0x0F, 0xCD, 0xBE, 0x0F, 0xB0, 0x03, 0x8E, 0xBE, 0x0F, 0xAD, 0xE8, +0x02, 0x8F, 0xC6, 0x0F, 0xE1, 0xC9, 0x08, 0xF0, 0x11, 0xC9, 0x09, 0xF0, 0x12, 0xA9, 0x01, 0xCD, +0xBC, 0x0F, 0xF0, 0x10, 0xCD, 0xBD, 0x0F, 0xF0, 0x0B, 0x60, 0xAD, 0xBC, 0x0F, 0x80, 0x08, 0xAD, +0xBD, 0x0F, 0x80, 0x03, 0xAD, 0xBE, 0x0F, 0x8D, 0xC0, 0x0F, 0xAA, 0xF0, 0x0A, 0xCA, 0xF0, 0x07, +0x8A, 0x9D, 0xC0, 0x0F, 0xCA, 0xD0, 0xF9, 0x60, 0x8F, 0xB4, 0x0F, 0xE1, 0x98, 0x8F, 0xB5, 0x0F, +0xE1, 0x60, 0xF4, 0xE1, 0xE1, 0x80, 0x03, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0x60, 0x8B, 0xC2, 0x30, +0xA9, 0x2E, 0x00, 0xA0, 0xE2, 0x14, 0xA2, 0x40, 0x00, 0x54, 0xE1, 0x00, 0xE2, 0x30, 0xF4, 0xE1, +0xE1, 0xAB, 0xAB, 0xAD, 0x2D, 0xC0, 0x8D, 0xC4, 0x0F, 0x29, 0x9F, 0x8D, 0x2D, 0xC0, 0xAB, 0x60, +0x8B, 0xC2, 0x30, 0xA9, 0x2E, 0x00, 0xA2, 0xE2, 0x14, 0xA0, 0x40, 0x00, 0x54, 0x00, 0xE1, 0xE2, +0x30, 0x20, 0x42, 0x6F, 0xAD, 0xC4, 0x0F, 0x8D, 0x2D, 0xC0, 0xAB, 0x60, 0x8B, 0xC2, 0x30, 0xA9, +0x2E, 0x00, 0xA0, 0x12, 0x15, 0xA2, 0x40, 0x00, 0x54, 0xE1, 0x00, 0xE2, 0x30, 0xAB, 0x60, 0x8B, +0xC2, 0x30, 0xA9, 0x2E, 0x00, 0xA2, 0x12, 0x15, 0xA0, 0x40, 0x00, 0x54, 0x00, 0xE1, 0xE2, 0x30, +0xAB, 0x60, 0xAD, 0xB0, 0x0F, 0x10, 0x0C, 0xA5, 0x45, 0xD0, 0x08, 0xA9, 0x48, 0xA2, 0x00, 0x85, +0x42, 0x86, 0x43, 0xA6, 0x60, 0xA5, 0x46, 0x60, 0xA9, 0xA5, 0x8F, 0xFD, 0x06, 0x00, 0xAF, 0xB6, +0x0F, 0xE1, 0xC9, 0xA5, 0xD0, 0x12, 0x49, 0xFF, 0x4F, 0xB7, 0x0F, 0xE1, 0xD0, 0x0A, 0xAF, 0xE8, +0x02, 0xE1, 0xCF, 0xC6, 0x0F, 0xE1, 0xF0, 0x06, 0xA9, 0xAA, 0x8F, 0xB6, 0x0F, 0xE1, 0xA0, 0x05, +0xB9, 0x69, 0x70, 0x20, 0x47, 0x6F, 0x99, 0x42, 0x00, 0x4B, 0xAB, 0x88, 0x10, 0xF2, 0x22, 0xBC, +0x6A, 0xFF, 0xB0, 0x12, 0xAF, 0x00, 0x08, 0x00, 0xAA, 0xCA, 0xD0, 0x0A, 0xAF, 0x01, 0x08, 0x00, +0xF0, 0x04, 0xA2, 0x50, 0x18, 0x6B, 0x18, 0xFB, 0x08, 0xE2, 0x30, 0xA5, 0x01, 0xCF, 0xF8, 0x07, +0x00, 0xF0, 0x40, 0x20, 0x47, 0x6F, 0xAD, 0x2D, 0xC0, 0x48, 0x29, 0x9F, 0x8D, 0x2D, 0xC0, 0xAD, +0x68, 0xC0, 0x48, 0xA9, 0x08, 0x8D, 0x68, 0xC0, 0x38, 0xFB, 0x08, 0x22, 0x87, 0xC5, 0x00, 0x28, +0xFB, 0xA2, 0x00, 0xAF, 0xB1, 0x0F, 0xE1, 0xD0, 0x02, 0xA2, 0x01, 0xC9, 0x28, 0xD0, 0x02, 0xA2, +0x02, 0xC9, 0x2F, 0xD0, 0x02, 0xA2, 0x03, 0x8A, 0x20, 0x80, 0xC0, 0x68, 0x8D, 0x68, 0xC0, 0x68, +0x8D, 0x2D, 0xC0, 0xA9, 0x27, 0x28, 0xFB, 0x38, 0x6B, 0x01, 0x50, 0x00, 0x08, 0x00, 0x00, 0x08, +0x78, 0xA3, 0x01, 0x8F, 0xC5, 0x0F, 0xE1, 0x8B, 0x20, 0x42, 0x6F, 0x20, 0x4D, 0x6F, 0xAF, 0x36, +0xC0, 0x00, 0x48, 0x29, 0xFB, 0x09, 0x80, 0x8D, 0x36, 0xC0, 0x8B, 0xA9, 0xFF, 0x8F, 0xB6, 0x0F, +0xE1, 0xA9, 0xA5, 0x8F, 0xFD, 0x06, 0x00, 0xA9, 0x00, 0x20, 0x1A, 0x6E, 0x20, 0xE7, 0x6D, 0xAB, +0x68, 0x8D, 0x36, 0xC0, 0x20, 0x70, 0x6F, 0xAB, 0x28, 0x60, 0x8B, 0x20, 0x42, 0x6F, 0xAD, 0x68, +0xC0, 0x48, 0xA5, 0x45, 0x29, 0x0F, 0xA8, 0xC2, 0x30, 0xA9, 0xFC, 0x02, 0x6A, 0x88, 0x10, 0xFC, +0xE2, 0x30, 0xAD, 0x68, 0xC0, 0x29, 0x30, 0xF0, 0x12, 0xB0, 0x09, 0x29, 0x10, 0xF0, 0x0C, 0x20, +0xF8, 0x70, 0x80, 0x07, 0x29, 0x20, 0xF0, 0x03, 0x20, 0xF8, 0x70, 0xC2, 0x30, 0xA2, 0x0D, 0x0A, +0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x68, 0x8D, 0x68, 0xC0, 0xAB, 0x90, 0x04, 0xA9, 0x27, 0x85, +0x50, 0x18, 0xA5, 0x50, 0xF0, 0x01, 0x38, 0x60, 0xA5, 0x44, 0xF0, 0x04, 0xC9, 0xE0, 0xD0, 0x11, +0xA9, 0x30, 0x1C, 0x68, 0xC0, 0xA5, 0x43, 0xC9, 0xD0, 0xB0, 0x06, 0xC9, 0x02, 0x90, 0x02, 0xE6, +0x44, 0x60, 0xA5, 0x45, 0x29, 0x3F, 0xC9, 0x05, 0xD0, 0x0F, 0xA2, 0x05, 0xBF, 0x00, 0x00, 0xF0, +0xDF, 0x3A, 0x71, 0xFF, 0xD0, 0x0E, 0xCA, 0x10, 0xF3, 0x22, 0x07, 0x00, 0xF0, 0x18, 0xA5, 0x50, +0xF0, 0x01, 0x38, 0x60, 0x38, 0xA9, 0x27, 0x85, 0x50, 0x60, 0xD2, 0xCF, 0xCD, 0xC4, 0xC9, 0xD3, +0x80, 0x1B, 0x16, 0xE7, 0x79, 0xAC, 0x74, 0x97, 0x77, 0x86, 0x7C, 0x32, 0x78, 0x42, 0x76, 0x32, +0x7A, 0x0B, 0x7B, 0x01, 0x7C, 0x97, 0x7A, 0x74, 0x78, 0x35, 0x7D, 0xEB, 0x71, 0x78, 0xC2, 0x30, +0xA2, 0x00, 0x08, 0x9F, 0x00, 0x00, 0xE0, 0x9F, 0x00, 0x00, 0xE1, 0xE8, 0xE0, 0x00, 0xC0, 0x90, +0xF2, 0xA9, 0x2B, 0x74, 0x8F, 0x1D, 0x00, 0xE1, 0xE2, 0x30, 0xA9, 0xFF, 0x8F, 0x1F, 0x00, 0xE1, +0x20, 0x25, 0x74, 0x9C, 0x34, 0xC0, 0x9C, 0x21, 0xC0, 0x0E, 0xF4, 0x03, 0x9C, 0x2D, 0xC0, 0xA9, +0x04, 0x8D, 0x3C, 0xC0, 0x9C, 0x59, 0xC0, 0x9C, 0xE2, 0xC0, 0x9C, 0x5B, 0xC0, 0x9C, 0xE4, 0xC0, +0xAD, 0x46, 0xC0, 0x10, 0x41, 0x20, 0xF6, 0x73, 0xAD, 0x0E, 0x03, 0x8D, 0x21, 0x03, 0xE2, 0x30, +0xAD, 0x61, 0xC0, 0x30, 0x27, 0xC2, 0x30, 0x9C, 0x1B, 0x03, 0xAD, 0x10, 0x03, 0xCF, 0x50, 0x73, +0xFF, 0xD0, 0x0E, 0xAD, 0x11, 0x03, 0xCF, 0x51, 0x73, 0xFF, 0xD0, 0x05, 0xAD, 0x13, 0x03, 0x80, +0x1A, 0xA9, 0xFF, 0xFF, 0x8D, 0x15, 0x03, 0xE2, 0x30, 0x82, 0x86, 0x00, 0xC2, 0x30, 0x9C, 0x1B, +0x03, 0xAD, 0x13, 0x03, 0x80, 0x05, 0xC2, 0x30, 0xA9, 0xFF, 0xFF, 0x8D, 0x1F, 0x03, 0xA9, 0x42, +0x71, 0x85, 0xF9, 0xAF, 0x42, 0x71, 0xFF, 0x29, 0xFF, 0x00, 0x4A, 0x8D, 0x23, 0x03, 0x8D, 0x25, +0x03, 0x18, 0xFB, 0xC2, 0x30, 0xA2, 0xFF, 0x01, 0x9A, 0x9C, 0x29, 0x03, 0x9C, 0x15, 0x03, 0x9C, +0x17, 0x03, 0xE6, 0xF9, 0x4B, 0xAB, 0xB2, 0xF9, 0x20, 0x25, 0x74, 0x85, 0xFB, 0xE6, 0xF9, 0x38, +0xAD, 0x25, 0x03, 0xED, 0x23, 0x03, 0x1A, 0x8D, 0x15, 0x03, 0x22, 0x05, 0x73, 0xFF, 0x78, 0x20, +0x25, 0x74, 0x90, 0x7C, 0x18, 0xFB, 0xE2, 0x30, 0xA9, 0x00, 0x8F, 0x35, 0xC0, 0xE0, 0xA9, 0xFF, +0x8D, 0x1B, 0x03, 0x20, 0x7B, 0x73, 0xAE, 0x15, 0x03, 0x8E, 0x00, 0x03, 0xAE, 0x17, 0x03, 0x8E, +0x02, 0x03, 0xE2, 0x10, 0x20, 0xDF, 0x73, 0x9C, 0x59, 0xC0, 0x9C, 0xE2, 0xC0, 0xAD, 0x46, 0xC0, +0x30, 0x4E, 0xA2, 0x00, 0x9C, 0x27, 0x03, 0x9C, 0x5A, 0xC0, 0x9C, 0xE5, 0xC0, 0xBF, 0xA3, 0x72, +0xFF, 0xF0, 0x05, 0x20, 0x9C, 0x73, 0x80, 0xF5, 0xA9, 0xFF, 0x8D, 0x1D, 0x03, 0x20, 0xDF, 0x73, +0x20, 0x42, 0x74, 0xA9, 0xFF, 0x8D, 0x29, 0x03, 0x20, 0xDF, 0x73, 0xA9, 0x8D, 0x20, 0x89, 0x74, +0xA9, 0x8A, 0x20, 0x89, 0x74, 0x18, 0xFB, 0xE2, 0x30, 0xC2, 0x10, 0xA2, 0x10, 0x27, 0xA9, 0x05, +0x82, 0xB7, 0x00, 0xA0, 0xD3, 0xF9, 0xF3, 0xF4, 0xE5, 0xED, 0xA0, 0xC2, 0xE1, 0xE4, 0xBA, 0x00, +0x18, 0xFB, 0xE2, 0x30, 0xA9, 0x00, 0x8F, 0x35, 0xC0, 0xE0, 0x20, 0xDF, 0x73, 0xCE, 0x23, 0x03, +0x30, 0x03, 0x82, 0x3C, 0xFF, 0xAD, 0x46, 0xC0, 0x10, 0x58, 0xAD, 0x1B, 0x03, 0x30, 0x28, 0x9C, +0x58, 0xC0, 0x9C, 0xE3, 0xC0, 0xC2, 0x30, 0xEE, 0x08, 0x03, 0xEE, 0x06, 0x03, 0xCE, 0x21, 0x03, +0xF0, 0x03, 0x82, 0xD0, 0xFE, 0x20, 0x0B, 0x74, 0x9C, 0x5A, 0xC0, 0x9C, 0xE5, 0xC0, 0xAD, 0x61, +0xC0, 0x10, 0x03, 0x82, 0x67, 0xFE, 0xDB, 0xC2, 0x30, 0xEE, 0x0A, 0x03, 0xAD, 0x06, 0x03, 0x8D, +0x0C, 0x03, 0x80, 0xD6, 0x60, 0x9C, 0x1D, 0x03, 0x6E, 0x1F, 0x03, 0x90, 0xF7, 0xE2, 0x30, 0xEE, +0x34, 0xC0, 0x20, 0x7B, 0x73, 0xE2, 0x30, 0x20, 0xDF, 0x73, 0xA9, 0x80, 0x8D, 0x36, 0xC0, 0x6C, +0xFB, 0x00, 0x20, 0x7B, 0x73, 0xE2, 0x30, 0x9C, 0x58, 0xC0, 0x9C, 0xE3, 0xC0, 0x9C, 0x5A, 0xC0, +0x9C, 0xE5, 0xC0, 0xA2, 0x00, 0x9C, 0x27, 0x03, 0xBF, 0x43, 0x73, 0xFF, 0xF0, 0x15, 0x20, 0x9C, +0x73, 0x80, 0xF5, 0xA0, 0xD3, 0xF9, 0xF3, 0xF4, 0xE5, 0xED, 0xA0, 0xC7, 0xEF, 0xEF, 0xE4, 0x00, +0xCB, 0xD2, 0xC7, 0xC2, 0x10, 0xA2, 0xE8, 0x03, 0xA9, 0x11, 0xA8, 0x98, 0x20, 0xA8, 0xFC, 0x2C, +0x30, 0xC0, 0xCA, 0xD0, 0xF6, 0xAD, 0x1D, 0x03, 0xF0, 0x01, 0xDB, 0x0E, 0x46, 0xC0, 0xAD, 0x61, +0xC0, 0xB0, 0x03, 0x2D, 0x62, 0xC0, 0x10, 0xF3, 0x82, 0xE2, 0xFD, 0xC2, 0x10, 0xE2, 0x20, 0x9C, +0x00, 0xC0, 0x9C, 0x0C, 0xC0, 0x9C, 0x51, 0xC0, 0x9C, 0x54, 0xC0, 0xA9, 0x01, 0x8D, 0x29, 0xC0, +0xA0, 0x00, 0x04, 0xA9, 0xA0, 0x99, 0x00, 0x04, 0x88, 0x10, 0xFA, 0x60, 0xE2, 0x30, 0xAE, 0x27, +0x03, 0x9D, 0xD0, 0x07, 0xAE, 0x1D, 0x03, 0xE0, 0x00, 0xF0, 0x18, 0xAE, 0x27, 0x03, 0x9D, 0xF1, +0x03, 0x9D, 0x72, 0x04, 0x9D, 0xF3, 0x04, 0xAE, 0x29, 0x03, 0xE0, 0x00, 0xF0, 0x05, 0x20, 0x89, +0x74, 0x18, 0xFB, 0xAE, 0x27, 0x03, 0xEE, 0x27, 0x03, 0x60, 0x48, 0x6A, 0x6A, 0x6A, 0x6A, 0x20, +0xD3, 0x73, 0x68, 0x29, 0x0F, 0xC9, 0x0A, 0x90, 0x02, 0x69, 0x06, 0x69, 0xB0, 0x80, 0xBD, 0xA9, +0x0F, 0x8D, 0x27, 0x03, 0xA0, 0x00, 0x5A, 0xB9, 0x15, 0x03, 0x20, 0xCA, 0x73, 0x7A, 0xC8, 0x5A, +0xC0, 0x04, 0xD0, 0xF3, 0x7A, 0x60, 0xE2, 0x30, 0x22, 0x84, 0x00, 0xE1, 0xC2, 0x30, 0xA2, 0x61, +0x03, 0xA0, 0x00, 0x03, 0xA9, 0x15, 0x00, 0x54, 0x00, 0xE1, 0x60, 0xA2, 0x00, 0x03, 0xA0, 0x61, +0x03, 0xA9, 0x15, 0x00, 0x54, 0xE1, 0x00, 0xE2, 0x30, 0xAD, 0x61, 0xC0, 0x30, 0x04, 0x22, 0x80, +0x00, 0xE1, 0xE2, 0x30, 0x60, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0x60, 0x18, 0xFB, 0xC2, 0x30, 0xA2, +0xFF, 0x01, 0x9A, 0x20, 0x25, 0x74, 0xA9, 0x00, 0x00, 0x5B, 0x1A, 0x8F, 0x18, 0x03, 0x00, 0x82, +0xF2, 0xFD, 0xA9, 0x04, 0x8D, 0x68, 0xC0, 0xA2, 0x0C, 0xBF, 0x92, 0x74, 0xFF, 0x9F, 0xC0, 0x02, +0xE1, 0xCA, 0x10, 0xF5, 0xA9, 0xC1, 0x8D, 0xF8, 0x07, 0xAD, 0xFF, 0xCF, 0xAD, 0x0D, 0xC1, 0x85, +0x10, 0xA9, 0xC1, 0x85, 0x11, 0xAD, 0x0F, 0xC1, 0x85, 0x12, 0xA9, 0xC1, 0x85, 0x13, 0xA9, 0x0E, +0xAA, 0xBF, 0x9E, 0x74, 0xFF, 0x9D, 0x00, 0x20, 0xCA, 0x10, 0xF6, 0xA2, 0xC1, 0xA0, 0x10, 0x22, +0x00, 0x20, 0x00, 0xA9, 0xAA, 0x20, 0x89, 0x74, 0x60, 0xA2, 0xC1, 0xA0, 0x10, 0x22, 0x07, 0x20, +0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x06, 0x02, 0x01, 0x01, 0x00, 0x20, 0x04, +0x20, 0x6B, 0x6C, 0x10, 0x00, 0x20, 0x0B, 0x20, 0x6B, 0x6C, 0x12, 0x00, 0x2C, 0x50, 0xC0, 0x2C, +0x52, 0xC0, 0x2C, 0x57, 0xC0, 0x20, 0xAB, 0x75, 0xB0, 0x52, 0xC2, 0x10, 0xE2, 0x20, 0xEE, 0x34, +0xC0, 0xA9, 0x00, 0x20, 0x0D, 0x75, 0xB0, 0x3A, 0xEE, 0x34, 0xC0, 0xA9, 0xC1, 0x8D, 0x29, 0xC0, +0xA9, 0x01, 0x20, 0x0D, 0x75, 0xB0, 0x2B, 0x20, 0x07, 0x76, 0xB0, 0x26, 0xEE, 0x34, 0xC0, 0xA9, +0x01, 0x8D, 0x29, 0xC0, 0xA9, 0xE0, 0x20, 0x0D, 0x75, 0xB0, 0x17, 0x20, 0x07, 0x76, 0xB0, 0x12, +0xEE, 0x34, 0xC0, 0xA9, 0xC1, 0x8D, 0x29, 0xC0, 0xA9, 0xE1, 0x20, 0x0D, 0x75, 0xB0, 0x03, 0x20, +0x07, 0x76, 0xE2, 0x30, 0xB0, 0x01, 0x6B, 0xA5, 0xF0, 0x8D, 0x16, 0x03, 0x6B, 0x85, 0xF0, 0xC2, +0x10, 0xE2, 0x20, 0xA2, 0x00, 0x04, 0xA0, 0xFF, 0xBF, 0x20, 0x3F, 0x75, 0xB0, 0x20, 0xAD, 0x8B, +0xC0, 0xAD, 0x8B, 0xC0, 0xA2, 0x00, 0xD0, 0xA0, 0xFF, 0xDF, 0x20, 0x3F, 0x75, 0xB0, 0x0F, 0xAD, +0x83, 0xC0, 0xAD, 0x83, 0xC0, 0xA2, 0x00, 0xD0, 0xA0, 0xFF, 0xFF, 0x20, 0x3F, 0x75, 0x60, 0x84, +0xF2, 0x86, 0xF4, 0xA2, 0x00, 0x00, 0x86, 0x04, 0xA5, 0xF0, 0x85, 0x06, 0xA9, 0x00, 0x85, 0x07, +0xA2, 0x02, 0x00, 0x86, 0x09, 0xA4, 0xF4, 0xA5, 0x07, 0x49, 0xFF, 0x85, 0x0B, 0x97, 0x04, 0xC8, +0xC4, 0xF2, 0x90, 0xF9, 0xA6, 0x09, 0xA4, 0xF4, 0xA5, 0x07, 0xCA, 0x10, 0x05, 0xA2, 0x02, 0x00, +0x97, 0x04, 0xC8, 0xC4, 0xF2, 0x90, 0xF3, 0xA5, 0x09, 0xD0, 0x08, 0xA5, 0x07, 0xC9, 0xFF, 0xD0, +0x02, 0x18, 0x60, 0xA6, 0x09, 0xA4, 0xF4, 0xA5, 0x0B, 0xCA, 0x10, 0x05, 0xA2, 0x02, 0x00, 0xA5, +0x07, 0xD7, 0x04, 0xD0, 0x0F, 0xC8, 0xC4, 0xF2, 0x90, 0xED, 0xC6, 0x09, 0x10, 0xB7, 0xA5, 0x07, +0x49, 0xFF, 0x80, 0xAA, 0x57, 0x04, 0x8D, 0x17, 0x03, 0x38, 0x60, 0x9C, 0x16, 0x03, 0x9C, 0x17, +0x03, 0xC2, 0x10, 0xA0, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x48, 0xA9, 0xFE, 0xA2, 0x00, 0x00, 0x99, +0x00, 0x00, 0xD9, 0x00, 0x00, 0xD0, 0x25, 0x38, 0x2A, 0xE8, 0xE0, 0x08, 0x00, 0xD0, 0xF0, 0xCA, +0xA9, 0x80, 0x99, 0x00, 0x00, 0xD9, 0x00, 0x00, 0xD0, 0x12, 0x4A, 0xCA, 0x10, 0xF4, 0x68, 0x99, +0x00, 0x00, 0xC8, 0xC0, 0x00, 0x04, 0xD0, 0xCE, 0xE2, 0x10, 0x18, 0x60, 0xE2, 0x10, 0x59, 0x00, +0x00, 0x8D, 0x17, 0x03, 0x9C, 0x16, 0x03, 0x38, 0x60, 0xE2, 0x10, 0x57, 0x04, 0x8D, 0x17, 0x03, +0xA5, 0xF0, 0x8D, 0x16, 0x03, 0x38, 0x60, 0xC2, 0x10, 0xA0, 0x00, 0x00, 0x86, 0x04, 0xA5, 0xF0, +0x85, 0x06, 0xB7, 0x04, 0x48, 0xA9, 0xFE, 0xA2, 0x00, 0x00, 0x97, 0x04, 0xD7, 0x04, 0xD0, 0xD9, +0x38, 0x2A, 0xE8, 0xE0, 0x08, 0x00, 0xD0, 0xF2, 0xCA, 0xA9, 0x80, 0x97, 0x04, 0xD7, 0x04, 0xD0, +0xC8, 0x4A, 0xCA, 0x10, 0xF6, 0x68, 0x97, 0x04, 0xC8, 0xC0, 0x00, 0x04, 0xD0, 0xD4, 0xE2, 0x10, +0x18, 0x60, 0x20, 0x4B, 0x76, 0xB0, 0x03, 0x20, 0xC9, 0x76, 0x6B, 0x78, 0x9C, 0x0C, 0x08, 0x9C, +0x16, 0x03, 0x20, 0x7A, 0x77, 0xA9, 0xFF, 0x8D, 0x0E, 0x08, 0xA9, 0x02, 0x8D, 0x0D, 0x08, 0x20, +0x95, 0x76, 0x30, 0x23, 0xA9, 0x0C, 0x8D, 0x0D, 0x08, 0x20, 0x8E, 0x76, 0x30, 0x19, 0xEE, 0x0D, +0x08, 0x20, 0x8E, 0x76, 0x30, 0x11, 0xA9, 0xFA, 0x8D, 0x0E, 0x08, 0xA9, 0x0F, 0x8D, 0x0D, 0x08, +0x20, 0x8E, 0x76, 0x30, 0x02, 0x18, 0x60, 0xA9, 0x01, 0x8D, 0x16, 0x03, 0x38, 0x60, 0xA0, 0x3B, +0x20, 0x9F, 0x76, 0x30, 0x09, 0xA0, 0x3C, 0x20, 0x9F, 0x76, 0x30, 0x02, 0xA9, 0x00, 0x60, 0xAD, +0x0D, 0x08, 0x99, 0xFD, 0xBF, 0xAD, 0x0C, 0x08, 0x2D, 0x0E, 0x08, 0x8D, 0x0F, 0x08, 0x99, 0xFD, +0xBF, 0xAD, 0x0D, 0x08, 0x99, 0xFD, 0xBF, 0xB9, 0xFD, 0xBF, 0xCD, 0x0F, 0x08, 0xD0, 0x07, 0xCE, +0x0C, 0x08, 0xD0, 0xDB, 0xF0, 0xD6, 0xA9, 0x80, 0x60, 0x78, 0x20, 0x7A, 0x77, 0xA0, 0x3C, 0x20, +0x63, 0x77, 0x20, 0xE8, 0x76, 0xD0, 0x0C, 0xA0, 0x3B, 0x20, 0x63, 0x77, 0x20, 0xE8, 0x76, 0xD0, +0x02, 0x18, 0x60, 0x8D, 0x16, 0x03, 0x38, 0x60, 0x9C, 0x0C, 0x08, 0x9C, 0x00, 0x08, 0x9C, 0x01, +0x08, 0xA9, 0x00, 0x99, 0xFD, 0xBF, 0xB9, 0xFD, 0xBF, 0x29, 0x04, 0xD0, 0x08, 0xCE, 0x00, 0x08, +0xD0, 0xEF, 0xA9, 0x05, 0x60, 0xAD, 0x0C, 0x08, 0x99, 0xFF, 0xBF, 0x9C, 0x00, 0x08, 0xA9, 0x01, +0x99, 0xFD, 0xBF, 0xB9, 0xFD, 0xBF, 0x29, 0x01, 0xD0, 0x0D, 0xCE, 0x00, 0x08, 0xD0, 0xEF, 0xCE, +0x01, 0x08, 0xD0, 0xEA, 0xA9, 0x06, 0x60, 0x9C, 0x00, 0x08, 0x9C, 0x01, 0x08, 0xA9, 0x00, 0x99, +0xFD, 0xBF, 0xB9, 0xFD, 0xBF, 0x29, 0x01, 0xD0, 0x08, 0xCE, 0x00, 0x08, 0xD0, 0xEF, 0xA9, 0x07, +0x60, 0xB9, 0xFF, 0xBF, 0xCD, 0x0C, 0x08, 0xF0, 0x03, 0xA9, 0x08, 0x60, 0xA9, 0x01, 0x99, 0xFD, +0xBF, 0xB9, 0xFD, 0xBF, 0x29, 0x70, 0xF0, 0x03, 0xA9, 0x09, 0x60, 0xCE, 0x0C, 0x08, 0xD0, 0x8B, +0xA9, 0x00, 0x60, 0xA2, 0x00, 0xBF, 0x87, 0x77, 0xFF, 0x99, 0xFD, 0xBF, 0xE8, 0xBF, 0x87, 0x77, +0xFF, 0x99, 0xFD, 0xBF, 0xE8, 0xE0, 0x10, 0xD0, 0xEC, 0x60, 0xA0, 0x3C, 0xA9, 0x09, 0x99, 0xFD, +0xBF, 0xA9, 0xC0, 0x99, 0xFD, 0xBF, 0x60, 0x09, 0x00, 0x04, 0x4C, 0x0B, 0xD0, 0x0C, 0x5E, 0x0D, +0x00, 0x0E, 0x13, 0x03, 0xC1, 0x05, 0x6A, 0x4B, 0xAB, 0xA9, 0x01, 0xA0, 0x29, 0xBE, 0x07, 0x78, +0xE0, 0xFF, 0xF0, 0x4A, 0x9F, 0x00, 0xC0, 0x00, 0xBE, 0x08, 0x78, 0x20, 0x25, 0x74, 0x1E, 0x00, +0xC0, 0x90, 0x47, 0xC9, 0x00, 0xF0, 0x20, 0x89, 0x0C, 0xD0, 0x19, 0x20, 0x25, 0x74, 0x1C, 0x68, +0xC0, 0xF0, 0x37, 0x1E, 0x00, 0xC0, 0xB0, 0x32, 0x0C, 0x68, 0xC0, 0xD0, 0x2D, 0x1E, 0x00, 0xC0, +0x90, 0x28, 0x80, 0x03, 0x0C, 0x68, 0xC0, 0x4B, 0xAB, 0xBE, 0x06, 0x78, 0x9F, 0x00, 0xC0, 0x00, +0xBE, 0x08, 0x78, 0x20, 0x25, 0x74, 0x1E, 0x00, 0xC0, 0xB0, 0x0F, 0x4B, 0xAB, 0x88, 0x88, 0x0A, +0x88, 0x10, 0xAA, 0xA9, 0x0C, 0x8D, 0x68, 0xC0, 0x18, 0x6B, 0x8D, 0x16, 0x03, 0x8E, 0x17, 0x03, +0x22, 0xF3, 0x77, 0xFF, 0x38, 0x6B, 0x0A, 0x0B, 0x17, 0x00, 0x01, 0x18, 0x50, 0x51, 0x1A, 0x52, +0x53, 0x1B, 0x56, 0x57, 0x1D, 0x0E, 0x0F, 0x1E, 0x0C, 0x0D, 0x1F, 0x08, 0x09, 0x16, 0x54, 0x55, +0x1C, 0x02, 0x03, 0x13, 0x04, 0x05, 0x14, 0x8B, 0x83, 0x11, 0x81, 0x8B, 0x12, 0xFF, 0x28, 0x06, +0x07, 0x15, 0xA9, 0x80, 0x8D, 0x36, 0xC0, 0x20, 0x5C, 0x78, 0xA0, 0x01, 0xE0, 0x19, 0xF0, 0x04, +0xE0, 0x1A, 0xD0, 0x10, 0x9C, 0x36, 0xC0, 0x20, 0x5C, 0x78, 0xA0, 0x02, 0xE0, 0x0C, 0xF0, 0xA8, +0xE0, 0x0D, 0xF0, 0xA4, 0x8C, 0x16, 0x03, 0x8E, 0x17, 0x03, 0x38, 0x6B, 0xA2, 0x00, 0xAF, 0x2E, +0xC0, 0x00, 0xCF, 0x2E, 0xC0, 0x00, 0xF0, 0xFA, 0xAF, 0x2E, 0xC0, 0x00, 0xE8, 0xCF, 0x2E, 0xC0, +0x00, 0xF0, 0xF9, 0x60, 0x20, 0x7D, 0x78, 0xB0, 0x03, 0x20, 0x35, 0x79, 0x6B, 0x78, 0xAF, 0x11, +0x00, 0xE1, 0x8D, 0x0C, 0x70, 0xAF, 0x12, 0x00, 0xE1, 0x8D, 0x08, 0x70, 0xAF, 0x13, 0x00, 0xE1, +0x8D, 0x0A, 0x70, 0xA9, 0x28, 0x8F, 0x11, 0x00, 0xE1, 0xA9, 0x79, 0x8F, 0x12, 0x00, 0xE1, 0xA9, +0xFF, 0x8F, 0x13, 0x00, 0xE1, 0x9C, 0x41, 0xC0, 0x9C, 0x00, 0x08, 0x9C, 0x01, 0x08, 0x9C, 0x00, +0x70, 0x58, 0x9C, 0x47, 0xC0, 0xA9, 0x08, 0x8D, 0x41, 0xC0, 0xAD, 0x00, 0x70, 0xC9, 0x01, 0xF0, +0x0E, 0xCE, 0x00, 0x08, 0xD0, 0xF4, 0xCE, 0x01, 0x08, 0xD0, 0xEF, 0xA9, 0x01, 0x80, 0x37, 0xAD, +0x02, 0x70, 0x29, 0x08, 0xD0, 0x04, 0xA9, 0x02, 0x80, 0x2C, 0x9C, 0x00, 0x08, 0x9C, 0x01, 0x08, +0x9C, 0x47, 0xC0, 0xA9, 0x10, 0x8D, 0x41, 0xC0, 0xAD, 0x00, 0x70, 0xC9, 0x02, 0xF0, 0x0E, 0xCE, +0x00, 0x08, 0xD0, 0xF4, 0xCE, 0x01, 0x08, 0xD0, 0xEF, 0xA9, 0x03, 0x80, 0x09, 0xAD, 0x02, 0x70, +0x29, 0x10, 0xD0, 0x05, 0xA9, 0x04, 0x8D, 0x16, 0x03, 0x78, 0xAD, 0x0C, 0x70, 0x8F, 0x11, 0x00, +0xE1, 0xAD, 0x08, 0x70, 0x8F, 0x12, 0x00, 0xE1, 0xAD, 0x0A, 0x70, 0x8F, 0x13, 0x00, 0xE1, 0xAD, +0x16, 0x03, 0xF0, 0x02, 0x38, 0x60, 0x18, 0x60, 0x9C, 0x41, 0xC0, 0xAD, 0x46, 0xC0, 0x8D, 0x02, +0x70, 0xEE, 0x00, 0x70, 0x40, 0xE2, 0x30, 0x78, 0xAF, 0x11, 0x00, 0xE1, 0x8D, 0x0C, 0x70, 0xAF, +0x12, 0x00, 0xE1, 0x8D, 0x08, 0x70, 0xAF, 0x13, 0x00, 0xE1, 0x8D, 0x0A, 0x70, 0xA9, 0xC8, 0x8F, +0x11, 0x00, 0xE1, 0xA9, 0x79, 0x8F, 0x12, 0x00, 0xE1, 0xA9, 0xFF, 0x8F, 0x13, 0x00, 0xE1, 0x9C, +0x23, 0xC0, 0x9C, 0x32, 0xC0, 0x9C, 0x06, 0x70, 0x9C, 0x00, 0x70, 0x9C, 0x01, 0x08, 0xA9, 0x10, +0x8D, 0x02, 0x08, 0x58, 0xA9, 0x04, 0x8D, 0x23, 0xC0, 0xAD, 0x00, 0x70, 0xC9, 0x01, 0xF0, 0x13, +0xCE, 0x00, 0x08, 0xD0, 0xF4, 0xCE, 0x01, 0x08, 0xD0, 0xEF, 0xCE, 0x02, 0x08, 0xD0, 0xEA, 0xA9, +0x05, 0x80, 0x0B, 0xAD, 0x02, 0x70, 0x29, 0xC4, 0xC9, 0xC4, 0xF0, 0x05, 0xA9, 0x06, 0x8D, 0x16, +0x03, 0x78, 0x9C, 0x23, 0xC0, 0xA9, 0x01, 0x8D, 0x29, 0xC0, 0xAD, 0x0C, 0x70, 0x8F, 0x11, 0x00, +0xE1, 0xAD, 0x08, 0x70, 0x8F, 0x12, 0x00, 0xE1, 0xAD, 0x0A, 0x70, 0x8F, 0x13, 0x00, 0xE1, 0xAD, +0x16, 0x03, 0xF0, 0x02, 0x38, 0x60, 0x18, 0x60, 0xAD, 0x23, 0xC0, 0x8D, 0x02, 0x70, 0xAD, 0x06, +0x70, 0xF0, 0x0D, 0xAE, 0x04, 0x70, 0xA9, 0xBF, 0x3F, 0x00, 0x9D, 0x01, 0x9F, 0x00, 0x9D, 0x01, +0x9C, 0x23, 0xC0, 0xEE, 0x00, 0x70, 0x40, 0x20, 0xAB, 0x75, 0xC2, 0x30, 0xB0, 0x29, 0x64, 0xFD, +0xF4, 0xFE, 0xFE, 0xAB, 0xAB, 0xA0, 0xFF, 0xFF, 0x20, 0x22, 0x7A, 0x4B, 0xAB, 0xA0, 0xFF, 0xFF, +0x20, 0x26, 0x7A, 0xC9, 0x34, 0x12, 0xD0, 0x02, 0x18, 0x6B, 0x8F, 0x16, 0x03, 0x00, 0xA9, 0xD2, +0xCD, 0x8F, 0x00, 0x05, 0x00, 0x38, 0x6B, 0xA9, 0x01, 0x00, 0x8D, 0x18, 0x03, 0x8D, 0x16, 0x03, +0x38, 0x6B, 0xA9, 0x00, 0x00, 0x18, 0x88, 0x71, 0xFD, 0x88, 0xF0, 0x03, 0x88, 0xD0, 0xF8, 0x71, +0xFD, 0x60, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0x22, 0x8C, 0x00, 0xE1, 0xC2, 0x30, 0xAD, 0xE1, 0x03, +0x8D, 0x00, 0x09, 0xAD, 0xE3, 0x03, 0x8D, 0x02, 0x09, 0xA9, 0x01, 0x00, 0x8D, 0xE5, 0x03, 0x9C, +0xE7, 0x03, 0x20, 0x84, 0x7A, 0xF0, 0x05, 0x20, 0x84, 0x7A, 0xD0, 0x26, 0xAF, 0xE3, 0x03, 0xE1, +0xCD, 0xE7, 0x03, 0xD0, 0x1D, 0x18, 0x2E, 0xE5, 0x03, 0x2E, 0xE7, 0x03, 0x90, 0xE4, 0xAD, 0x00, +0x09, 0x8D, 0xE5, 0x03, 0xAD, 0x02, 0x09, 0x8D, 0xE7, 0x03, 0xE2, 0x30, 0x22, 0x88, 0x00, 0xE1, +0x18, 0x6B, 0x38, 0x6B, 0xE2, 0x30, 0x22, 0x88, 0x00, 0xE1, 0x22, 0x8C, 0x00, 0xE1, 0xC2, 0x30, +0xAD, 0xE1, 0x03, 0xCD, 0xE5, 0x03, 0x60, 0x9C, 0x35, 0xC0, 0xC2, 0x30, 0xA9, 0x00, 0x04, 0x85, +0x0A, 0x64, 0x0C, 0xA9, 0x5A, 0x5A, 0x20, 0xE9, 0x7A, 0xE6, 0x0C, 0x20, 0xE9, 0x7A, 0xE2, 0x20, +0xA9, 0x01, 0x8D, 0x35, 0xC0, 0xC2, 0x10, 0xA9, 0xA5, 0x8D, 0x00, 0x08, 0x20, 0xE9, 0x7A, 0xC6, +0x0C, 0x20, 0xE9, 0x7A, 0x20, 0xF6, 0x7A, 0xB0, 0x1A, 0xE6, 0x0C, 0x20, 0xF6, 0x7A, 0xB0, 0x13, +0xA9, 0x5A, 0x8D, 0x00, 0x08, 0xA9, 0xE0, 0x85, 0x0C, 0x20, 0xF6, 0x7A, 0xB0, 0x05, 0xE6, 0x0C, +0x20, 0xF6, 0x7A, 0xE2, 0x30, 0x9C, 0x35, 0xC0, 0x60, 0xA0, 0x00, 0x00, 0x97, 0x0A, 0xC8, 0xC8, +0xC0, 0x00, 0x04, 0xD0, 0xF7, 0x60, 0xA0, 0x00, 0x00, 0xB7, 0x0A, 0xCD, 0x00, 0x08, 0xD0, 0x09, +0xC8, 0xC8, 0xC0, 0x00, 0x04, 0xD0, 0xF2, 0x18, 0x60, 0x38, 0x60, 0xC2, 0x30, 0xA9, 0x00, 0x08, +0x85, 0x10, 0x64, 0x12, 0x20, 0x99, 0x7B, 0xA0, 0xFF, 0x98, 0x99, 0xFF, 0x08, 0x88, 0xD0, 0xF9, +0x20, 0x5D, 0x7B, 0xB0, 0x23, 0xA2, 0x05, 0x8E, 0x27, 0x03, 0xAE, 0x27, 0x03, 0xBF, 0x7E, 0x7B, +0xFF, 0xA0, 0xFF, 0x99, 0xFF, 0x08, 0x88, 0xD0, 0xFA, 0x20, 0x5D, 0x7B, 0xB0, 0x07, 0xCE, 0x27, +0x03, 0x10, 0xE7, 0x80, 0x0E, 0xEE, 0x16, 0x03, 0xEE, 0x16, 0x03, 0x8D, 0x17, 0x03, 0x8C, 0x18, +0x03, 0x38, 0x6B, 0xC2, 0x30, 0xA2, 0x00, 0x08, 0x20, 0x84, 0x7B, 0x18, 0x6B, 0xC2, 0x30, 0xA2, +0x00, 0x09, 0x20, 0x84, 0x7B, 0xA9, 0x00, 0x0A, 0x85, 0x10, 0x20, 0x99, 0x7B, 0xA0, 0xFC, 0xB9, +0xFF, 0x08, 0xD9, 0xFF, 0x09, 0xD0, 0x05, 0x88, 0xD0, 0xF5, 0x18, 0x60, 0x38, 0x60, 0xAA, 0x55, +0x00, 0xFF, 0xCC, 0x33, 0xA0, 0xC0, 0x02, 0xA9, 0xFF, 0x00, 0x54, 0xE1, 0x00, 0xE2, 0x30, 0x22, +0x80, 0x00, 0xE1, 0x20, 0x25, 0x74, 0xC2, 0x30, 0x60, 0xE2, 0x30, 0x8B, 0x08, 0x78, 0xA2, 0x00, +0x9B, 0xE2, 0x40, 0x20, 0xB5, 0x7B, 0x5A, 0x9B, 0x97, 0x10, 0x7A, 0xE8, 0xC8, 0xD0, 0xF2, 0x28, +0x18, 0xE2, 0x30, 0xAB, 0x60, 0x48, 0x98, 0x48, 0x29, 0xE0, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x09, +0x38, 0x50, 0x02, 0x09, 0x80, 0xEB, 0x68, 0x29, 0x1F, 0x0A, 0x0A, 0xEB, 0x08, 0x20, 0xE4, 0x7B, +0xEB, 0x20, 0xE4, 0x7B, 0x28, 0x68, 0x20, 0xE5, 0x7B, 0x48, 0xAD, 0x34, 0xC0, 0x29, 0xDF, 0x8D, +0x34, 0xC0, 0x68, 0x60, 0xB8, 0x8D, 0x33, 0xC0, 0xAD, 0x34, 0xC0, 0x29, 0x3F, 0x70, 0x04, 0x09, +0xA0, 0x80, 0x02, 0x09, 0xE0, 0x8D, 0x34, 0xC0, 0xAD, 0x34, 0xC0, 0x30, 0xFB, 0xAD, 0x33, 0xC0, +0x60, 0xC2, 0x30, 0xA9, 0x00, 0x14, 0x8D, 0x00, 0x0B, 0xA9, 0x04, 0x0B, 0x85, 0x10, 0xE2, 0x30, +0x20, 0x47, 0x7C, 0xB0, 0x28, 0x92, 0x10, 0xC2, 0x30, 0xE6, 0x10, 0xEE, 0x00, 0x0B, 0xAD, 0x00, +0x0B, 0xC9, 0x00, 0x20, 0x30, 0xE8, 0xA9, 0x04, 0x0B, 0x85, 0xFD, 0xA0, 0xFF, 0x0B, 0x20, 0x22, +0x7A, 0xC9, 0x72, 0xF7, 0xF0, 0x05, 0xC9, 0x72, 0x26, 0xD0, 0x07, 0x18, 0x6B, 0xA9, 0x01, 0x8D, +0x18, 0x03, 0x8D, 0x16, 0x03, 0x38, 0x6B, 0xC2, 0x20, 0xA9, 0x00, 0x00, 0x8F, 0xD6, 0x0F, 0xE1, +0x8F, 0xD8, 0x0F, 0xE1, 0x8F, 0xDA, 0x0F, 0xE1, 0xF4, 0x00, 0x00, 0xF4, 0x02, 0x0B, 0xF4, 0x00, +0x00, 0xF4, 0x00, 0x0B, 0xF4, 0x09, 0x00, 0x48, 0x8B, 0xA2, 0xFF, 0xDA, 0xF4, 0x7C, 0x7C, 0xAF, +0x2E, 0x80, 0xFF, 0xAA, 0xDA, 0xAF, 0x2C, 0x80, 0xFF, 0x48, 0xC2, 0x30, 0x6B, 0xE2, 0x30, 0x68, +0x68, 0x68, 0xAD, 0x02, 0x0B, 0x60, 0xF4, 0xE1, 0x00, 0xAB, 0xAD, 0x35, 0xC0, 0x48, 0xA9, 0x5F, +0x8D, 0x35, 0xC0, 0xA2, 0x03, 0xBF, 0x31, 0x7D, 0xFF, 0x85, 0xF0, 0x85, 0x06, 0xDA, 0xC2, 0x30, +0x64, 0x04, 0xA0, 0x00, 0x04, 0xA2, 0xFE, 0xBF, 0x20, 0x02, 0x7D, 0xE2, 0x20, 0xAD, 0x8B, 0xC0, +0xAD, 0x8B, 0xC0, 0xC2, 0x20, 0xA0, 0x00, 0xD0, 0xA2, 0xFE, 0xFF, 0x20, 0x02, 0x7D, 0xE2, 0x30, +0xFA, 0xCA, 0x10, 0xD1, 0xA2, 0x03, 0xBF, 0x31, 0x7D, 0xFF, 0x85, 0xF0, 0x85, 0x06, 0xDA, 0xC2, +0x30, 0x64, 0x04, 0xA0, 0x00, 0x04, 0xA2, 0xFE, 0xBF, 0x20, 0x13, 0x7D, 0xB0, 0x13, 0xE2, 0x20, +0xAD, 0x8B, 0xC0, 0xAD, 0x8B, 0xC0, 0xC2, 0x20, 0xA0, 0x00, 0xD0, 0xA2, 0xFE, 0xFF, 0x20, 0x13, +0x7D, 0xE2, 0x30, 0xFA, 0xB0, 0x03, 0xCA, 0x10, 0xCD, 0x2C, 0x81, 0xC0, 0x68, 0x8D, 0x35, 0xC0, +0xAB, 0x6B, 0x86, 0xF2, 0xBB, 0x98, 0x18, 0x65, 0xF0, 0x9B, 0x97, 0x04, 0xC8, 0xC8, 0xC4, 0xF2, +0x90, 0xF2, 0x60, 0x86, 0xF2, 0xBB, 0x98, 0x18, 0x65, 0xF0, 0x9B, 0xD7, 0x04, 0xD0, 0x08, 0xC8, +0xC8, 0xC4, 0xF2, 0x90, 0xF0, 0x18, 0x60, 0x8D, 0x16, 0x03, 0x98, 0xEB, 0x8D, 0x17, 0x03, 0x38, +0x60, 0x00, 0x01, 0xE0, 0xE1, 0x18, 0xFB, 0xC2, 0x30, 0x8B, 0x0B, 0x3B, 0x38, 0xE9, 0x10, 0x00, +0x1B, 0x1A, 0x48, 0x2B, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0x20, 0x2D, 0x7F, 0xE2, 0x30, 0x20, 0x94, +0x7D, 0x90, 0x04, 0xA9, 0x01, 0xB0, 0x1E, 0x20, 0xD9, 0x7D, 0x90, 0x04, 0xA9, 0x02, 0xB0, 0x15, +0x20, 0x37, 0x7E, 0x90, 0x04, 0xA9, 0x03, 0xB0, 0x0C, 0x20, 0x81, 0x7E, 0x90, 0x04, 0xA9, 0x04, +0xB0, 0x03, 0x20, 0xB6, 0x7E, 0xE2, 0x30, 0x9C, 0x16, 0x03, 0x9C, 0x17, 0x03, 0x8D, 0x18, 0x03, +0xA9, 0x0C, 0x8D, 0x15, 0x03, 0x08, 0x20, 0x2D, 0x7F, 0xFA, 0x3B, 0x18, 0x69, 0x10, 0x1B, 0xDA, +0x28, 0x2B, 0xAB, 0x6B, 0xC2, 0x10, 0x9C, 0x3E, 0xC0, 0x9C, 0x3F, 0xC0, 0xA9, 0x40, 0x8D, 0x3C, +0xC0, 0xAD, 0x3C, 0xC0, 0xAD, 0x3D, 0xC0, 0xA0, 0x00, 0x00, 0xA2, 0x07, 0x00, 0xBF, 0xD1, 0x7D, +0xFF, 0x8D, 0x3D, 0xC0, 0x20, 0xCA, 0x7D, 0xDF, 0xD1, 0x7D, 0xFF, 0xD0, 0x65, 0xCA, 0x10, 0xED, +0x88, 0x8C, 0x3E, 0xC0, 0xD0, 0xE4, 0xE2, 0x10, 0x18, 0x60, 0xAD, 0x3D, 0xC0, 0xAD, 0x3D, 0xC0, +0x60, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xA9, 0x60, 0x8D, 0x3C, 0xC0, 0xAD, 0x3C, +0xC0, 0xAD, 0x3D, 0xC0, 0xC2, 0x10, 0xA2, 0x01, 0x00, 0x20, 0x25, 0x7E, 0x8E, 0x3E, 0xC0, 0xA9, +0xA5, 0x8D, 0x3D, 0xC0, 0x9C, 0x3E, 0xC0, 0x9C, 0x3F, 0xC0, 0xA0, 0x00, 0x00, 0xAD, 0x3D, 0xC0, +0xAD, 0x3D, 0xC0, 0xC9, 0xA5, 0xF0, 0x10, 0x88, 0xD0, 0xF6, 0xC2, 0x20, 0x8A, 0x0A, 0xAA, 0xE2, +0x20, 0x90, 0xD6, 0xE2, 0x30, 0x18, 0x60, 0xE8, 0xE8, 0xEC, 0x3E, 0xC0, 0x08, 0xCA, 0xCA, 0x28, +0xF0, 0xE5, 0xE2, 0x31, 0x60, 0xDA, 0xA2, 0x00, 0x00, 0x9C, 0x3E, 0xC0, 0x9C, 0x3F, 0xC0, 0x9C, +0x3D, 0xC0, 0xCA, 0xD0, 0xFA, 0xFA, 0x60, 0x9C, 0x3E, 0xC0, 0x9C, 0x3C, 0xC0, 0xAD, 0x3D, 0xC0, +0xA0, 0x00, 0xA2, 0x07, 0xBF, 0xD1, 0x7D, 0xFF, 0xDA, 0xBB, 0x3F, 0x79, 0x7E, 0xFF, 0x85, 0x08, +0x8D, 0x3D, 0xC0, 0x20, 0xCA, 0x7D, 0x3F, 0x79, 0x7E, 0xFF, 0xFA, 0xC5, 0x08, 0xD0, 0x18, 0xCA, +0x10, 0xE2, 0xEE, 0x3E, 0xC0, 0xAD, 0x3E, 0xC0, 0xC9, 0xE0, 0xF0, 0x09, 0x2A, 0x2A, 0x2A, 0x2A, +0x29, 0x07, 0xA8, 0x80, 0xCD, 0x18, 0x60, 0x38, 0x60, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xF6, 0x7F, +0x00, 0x9C, 0x3E, 0xC0, 0x9C, 0x3F, 0xC0, 0x9C, 0x3C, 0xC0, 0xA9, 0xA5, 0x8D, 0x3D, 0xC0, 0xA9, +0x40, 0x8D, 0x3C, 0xC0, 0xA9, 0x5A, 0x8D, 0x3D, 0xC0, 0x9C, 0x3C, 0xC0, 0x20, 0xCA, 0x7D, 0xC9, +0xA5, 0xD0, 0x11, 0x8D, 0x3D, 0xC0, 0xA9, 0x40, 0x8D, 0x3C, 0xC0, 0x20, 0xCA, 0x7D, 0xC9, 0x5A, +0xD0, 0x02, 0x18, 0x60, 0x38, 0x60, 0x08, 0xE2, 0x30, 0x20, 0x2D, 0x7F, 0x20, 0xAD, 0x7F, 0x64, +0x00, 0x64, 0x02, 0x64, 0x03, 0xA9, 0x20, 0x85, 0x06, 0xC2, 0x20, 0xA9, 0xD5, 0x7F, 0x8F, 0x11, +0x00, 0xE1, 0xA9, 0x7F, 0xFF, 0x8F, 0x12, 0x00, 0xE1, 0xE2, 0x20, 0x58, 0xA9, 0x80, 0xA2, 0x40, +0xA0, 0x20, 0x20, 0x7A, 0x7F, 0xA9, 0x08, 0xA2, 0x20, 0x20, 0xA2, 0x7F, 0x1A, 0xE8, 0xC6, 0x06, +0xD0, 0xF7, 0x24, 0x06, 0xD0, 0x1B, 0xA5, 0x00, 0xC9, 0x20, 0x90, 0x06, 0xA2, 0x00, 0x28, 0x18, +0x90, 0x1B, 0xA5, 0x00, 0x18, 0x69, 0xA0, 0xAA, 0xA9, 0x08, 0x20, 0xA2, 0x7F, 0xA9, 0xFF, 0x85, +0x06, 0xC2, 0x20, 0xC6, 0x02, 0xE2, 0x20, 0xD0, 0xD9, 0xA2, 0x05, 0x28, 0x38, 0x08, 0xE2, 0x20, +0xAD, 0x3C, 0xC0, 0x29, 0xF0, 0x09, 0x08, 0x8D, 0x3C, 0xC0, 0x8A, 0x28, 0x60, 0x08, 0xE2, 0x30, +0xA9, 0x3E, 0xA2, 0xE1, 0x20, 0xA2, 0x7F, 0xA9, 0x00, 0xAA, 0xA0, 0x60, 0x20, 0x7A, 0x7F, 0xA9, +0x3F, 0xA2, 0xC0, 0xA0, 0x20, 0x20, 0x7A, 0x7F, 0xA9, 0x00, 0xA2, 0x80, 0xA0, 0x10, 0x20, 0x7A, +0x7F, 0xA9, 0x80, 0xA2, 0x90, 0xA0, 0x10, 0x20, 0x7A, 0x7F, 0xA9, 0x01, 0xA2, 0xA0, 0xA0, 0x20, +0x20, 0x7A, 0x7F, 0xA9, 0x04, 0x8D, 0x3C, 0xC0, 0xA9, 0xE0, 0x8D, 0x3E, 0xC0, 0xA2, 0x22, 0xAD, +0x3D, 0xC0, 0xCA, 0x10, 0xFA, 0x28, 0xEE, 0x34, 0xC0, 0x60, 0xDA, 0x08, 0xE2, 0x30, 0x8E, 0x3E, +0xC0, 0xA2, 0x24, 0x8E, 0x3C, 0xC0, 0x8D, 0x3D, 0xC0, 0x88, 0xD0, 0xFA, 0x28, 0xFA, 0x60, 0x08, +0xE2, 0x30, 0x8E, 0x3E, 0xC0, 0xA9, 0x24, 0x8D, 0x3C, 0xC0, 0xAD, 0x3D, 0xC0, 0xAD, 0x3D, 0xC0, +0x28, 0x60, 0x08, 0xC2, 0x30, 0xA0, 0x01, 0x00, 0x20, 0x7A, 0x7F, 0x28, 0x60, 0x48, 0xDA, 0x08, +0xC2, 0x10, 0xE2, 0x20, 0xA2, 0x00, 0x00, 0x8E, 0x3E, 0xC0, 0xA9, 0x64, 0x8D, 0x3C, 0xC0, 0xA9, +0x00, 0xC9, 0x00, 0xD0, 0x05, 0x1A, 0x8D, 0x3D, 0xC0, 0xCA, 0x8D, 0x3D, 0xC0, 0x1A, 0xCA, 0xD0, +0xF0, 0x28, 0xFA, 0x68, 0x60, 0x48, 0xDA, 0x08, 0xE2, 0x30, 0xA2, 0xE0, 0x20, 0x8F, 0x7F, 0x0A, +0xB0, 0x15, 0x4A, 0x4A, 0x29, 0x1F, 0x64, 0x02, 0x64, 0x03, 0x18, 0x69, 0xA0, 0xAA, 0xA9, 0x01, +0x20, 0xA2, 0x7F, 0xE6, 0x00, 0x64, 0x06, 0x28, 0xFA, 0x68, 0x18, 0x40, 0x00, 0x00, 0x42, 0x71, +0x17, 0x00, 0x00, 0x00, 0x5B, 0x80, 0xFF, 0x00, 0x94, 0x80, 0xFF, 0x00, 0x94, 0x80, 0xFF, 0x00, +0x96, 0x80, 0xFF, 0x00, 0x94, 0x80, 0xFF, 0x00, 0x9C, 0x80, 0xFF, 0x00, 0x94, 0x80, 0xFF, 0x00, +0x94, 0x80, 0xFF, 0x00, 0x9D, 0x82, 0xFF, 0x00, 0xBE, 0x82, 0xFF, 0x00, 0xDB, 0x82, 0xFF, 0x00, +0xFB, 0x84, 0xFF, 0x00, 0x14, 0x83, 0xFF, 0x00, 0x5E, 0x83, 0xFF, 0x00, 0xA2, 0x80, 0xFF, 0x00, +0xAE, 0x80, 0xFF, 0x00, 0xBA, 0x80, 0xFF, 0x00, 0xE3, 0x80, 0xFF, 0x00, 0xCF, 0x80, 0xFF, 0x00, +0xFB, 0x80, 0xFF, 0x00, 0x3D, 0x82, 0xFF, 0x00, 0x90, 0x82, 0xFF, 0x00, 0xE2, 0x10, 0x8B, 0x20, +0x82, 0xF8, 0xA9, 0x40, 0x00, 0x8D, 0xD6, 0x0F, 0x9C, 0xD8, 0x0F, 0x9C, 0xDA, 0x0F, 0xA2, 0x0A, +0x9E, 0xD0, 0x03, 0xCA, 0x10, 0xFA, 0xA2, 0x5C, 0x8E, 0xDC, 0x03, 0xA2, 0xFF, 0x8E, 0x47, 0x00, +0xA9, 0x8A, 0x81, 0x8D, 0x45, 0x00, 0xA2, 0xFF, 0x8E, 0x43, 0x00, 0xA9, 0x85, 0x84, 0x8D, 0x41, +0x00, 0xC2, 0x10, 0x80, 0x35, 0x80, 0x34, 0x8B, 0xA9, 0x00, 0x02, 0x80, 0x2B, 0x8B, 0xA9, 0xFF, +0xFF, 0x80, 0x25, 0x8B, 0x20, 0x82, 0xF8, 0xA9, 0x40, 0x00, 0x0C, 0xD6, 0x0F, 0x80, 0x1B, 0x8B, +0x20, 0x82, 0xF8, 0xA9, 0x40, 0x00, 0x1C, 0xD6, 0x0F, 0x80, 0x0F, 0x8B, 0x20, 0x82, 0xF8, 0xA9, +0x00, 0x00, 0x2C, 0xD5, 0x0F, 0x50, 0x01, 0x1A, 0x83, 0x08, 0xAB, 0xA9, 0x00, 0x00, 0x18, 0x6B, +0x0B, 0x08, 0x8B, 0x20, 0xAF, 0x84, 0x1B, 0xA0, 0x0B, 0x00, 0xB9, 0xD0, 0x03, 0x97, 0x20, 0x88, +0x10, 0xF8, 0x80, 0x12, 0x0B, 0x08, 0x8B, 0x20, 0xAF, 0x84, 0x1B, 0xA0, 0x0B, 0x00, 0xB7, 0x20, +0x99, 0xD0, 0x03, 0x88, 0x10, 0xF8, 0xA2, 0x04, 0x00, 0x4C, 0xBD, 0x84, 0x0B, 0x08, 0x8B, 0x20, +0xAF, 0x84, 0x1B, 0xA5, 0x25, 0xD0, 0x77, 0x20, 0xB2, 0x83, 0xB0, 0x72, 0xA5, 0x20, 0x29, 0x0F, +0x09, 0xF0, 0x20, 0xD6, 0x83, 0xB0, 0x67, 0xC2, 0x20, 0x7B, 0x69, 0x0A, 0x00, 0x5B, 0xE2, 0x20, +0x20, 0x56, 0x84, 0x08, 0xC2, 0x20, 0x7B, 0xE9, 0x09, 0x00, 0x5B, 0xE2, 0x20, 0x28, 0xB0, 0x4E, +0xA5, 0x0A, 0xF0, 0x3A, 0xAD, 0xD8, 0x0F, 0xC9, 0x10, 0xB0, 0x3B, 0xA8, 0x0A, 0x0A, 0xEB, 0xA9, +0x00, 0xEB, 0xAA, 0xC8, 0x98, 0x8D, 0xD9, 0x0F, 0x8D, 0xD8, 0x0F, 0xA5, 0x20, 0x9D, 0x4A, 0x15, +0xA5, 0x22, 0x9D, 0x4B, 0x15, 0xA5, 0x23, 0x9D, 0x4C, 0x15, 0xA5, 0x24, 0x9D, 0x4D, 0x15, 0x9C, +0xDA, 0x0F, 0x9C, 0xDB, 0x0F, 0x20, 0xEE, 0x83, 0xA2, 0x06, 0x00, 0x4C, 0xBD, 0x84, 0x20, 0xEE, +0x83, 0xA0, 0x83, 0x00, 0x80, 0x0E, 0x20, 0xEE, 0x83, 0xA0, 0x84, 0x00, 0x80, 0x06, 0x20, 0xEE, +0x83, 0xA0, 0x10, 0x00, 0xA2, 0x06, 0x00, 0x4C, 0xC4, 0x84, 0x0B, 0x08, 0x8B, 0xC2, 0x30, 0x20, +0xAF, 0x84, 0x1B, 0xAD, 0xD6, 0x0F, 0x30, 0x34, 0xCE, 0xD9, 0x0F, 0x30, 0x34, 0xAD, 0xDA, 0x0F, +0xCD, 0xD8, 0x0F, 0x90, 0x05, 0xA9, 0x00, 0x8D, 0xDA, 0x0F, 0xEE, 0xDA, 0x0F, 0x0A, 0x0A, 0xEB, +0xA9, 0x00, 0xEB, 0xAA, 0xA0, 0x17, 0x82, 0x8C, 0xDD, 0x03, 0xA9, 0xFF, 0x8D, 0xDF, 0x03, 0xBD, +0x4A, 0x15, 0x09, 0xC0, 0x8D, 0x26, 0xC0, 0xA9, 0x80, 0x0C, 0xD6, 0x0F, 0xC2, 0x30, 0x4C, 0xEE, +0x84, 0xA9, 0x0F, 0x8D, 0xDA, 0x0F, 0xAD, 0xDA, 0x0F, 0xC9, 0x02, 0xD0, 0x01, 0x3A, 0x09, 0x70, +0x20, 0xA2, 0x83, 0xCE, 0xDA, 0x0F, 0x10, 0xEE, 0xAD, 0xD8, 0x0F, 0x8D, 0xDA, 0x0F, 0xCE, 0xDA, +0x0F, 0xAD, 0xDA, 0x0F, 0x30, 0x13, 0x0A, 0x0A, 0xEB, 0xA9, 0x00, 0xEB, 0xA8, 0xB9, 0x4A, 0x15, +0x29, 0x0F, 0x09, 0x50, 0x20, 0xA2, 0x83, 0x80, 0xE5, 0xAD, 0xDB, 0x0F, 0x8D, 0xDA, 0x0F, 0xAD, +0xD8, 0x0F, 0x8D, 0xD9, 0x0F, 0x80, 0xB5, 0xA5, 0x00, 0xF0, 0x1F, 0x4B, 0x62, 0x1A, 0x00, 0xAD, +0xD8, 0x0F, 0x8D, 0xD9, 0x0F, 0xAD, 0xDA, 0x0F, 0x3A, 0x8D, 0xDB, 0x0F, 0x0A, 0x0A, 0xAA, 0xBD, +0x4D, 0x15, 0x48, 0xC2, 0x30, 0xBD, 0x4B, 0x15, 0x3A, 0x48, 0xE2, 0x30, 0x18, 0x6B, 0x0B, 0x08, +0x8B, 0x20, 0xAF, 0x84, 0x1B, 0xAD, 0xD6, 0x0F, 0xE2, 0x30, 0x30, 0x3A, 0xAE, 0xD8, 0x0F, 0xCA, +0x30, 0x3B, 0x8A, 0x0A, 0x0A, 0xA8, 0xB9, 0x4A, 0x15, 0xC5, 0x20, 0xD0, 0xF2, 0xC2, 0x20, 0xB9, +0x50, 0x15, 0x99, 0x4C, 0x15, 0xB9, 0x4E, 0x15, 0x99, 0x4A, 0x15, 0xC8, 0xC8, 0xC8, 0xC8, 0xE8, +0xEC, 0xD8, 0x0F, 0x90, 0xEA, 0xCE, 0xD8, 0x0F, 0xAE, 0xD8, 0x0F, 0x8E, 0xD9, 0x0F, 0x9C, 0xDA, +0x0F, 0xA2, 0x02, 0x4C, 0xBD, 0x84, 0xA0, 0x82, 0xA2, 0x02, 0x4C, 0xC4, 0x84, 0xA0, 0x10, 0x80, +0xF7, 0xA9, 0x00, 0x00, 0x8F, 0xD8, 0x0F, 0xE1, 0x8F, 0xDA, 0x0F, 0xE1, 0x18, 0x6B, 0x0B, 0x08, +0x8B, 0x20, 0xAF, 0x84, 0x1B, 0x20, 0x9B, 0x83, 0xB0, 0x0D, 0x20, 0xC3, 0x83, 0xB0, 0x08, 0x20, +0xEE, 0x83, 0xA2, 0x08, 0x00, 0x80, 0x4F, 0x20, 0xEE, 0x83, 0xA2, 0x08, 0x00, 0x80, 0x50, 0x0B, +0x08, 0x8B, 0x20, 0xAF, 0x84, 0x1B, 0x20, 0x9B, 0x83, 0xB0, 0xEC, 0xA0, 0x00, 0x00, 0xC4, 0x26, +0xB0, 0xDD, 0x20, 0x42, 0x84, 0xB0, 0xE0, 0x97, 0x22, 0xC8, 0x80, 0xF2, 0x0B, 0x08, 0x8B, 0x20, +0xAF, 0x84, 0x1B, 0x20, 0x9B, 0x83, 0xB0, 0x21, 0xA7, 0x22, 0x20, 0xD6, 0x83, 0xB0, 0x1A, 0xA0, +0x01, 0x00, 0xB7, 0x22, 0x20, 0xD6, 0x83, 0xB0, 0x10, 0x20, 0x42, 0x84, 0xB0, 0x0B, 0x87, 0x26, +0x20, 0xEE, 0x83, 0xA2, 0x0A, 0x00, 0x4C, 0xBD, 0x84, 0x20, 0xEE, 0x83, 0xA2, 0x0A, 0x00, 0xA0, +0x10, 0x00, 0x4C, 0xC4, 0x84, 0x08, 0xE2, 0x20, 0x8B, 0xA9, 0xE1, 0x48, 0xAB, 0xA3, 0x0E, 0xF0, +0x05, 0xA0, 0x10, 0x09, 0x80, 0x23, 0xA9, 0x80, 0x0C, 0xD6, 0x0F, 0xF0, 0x05, 0xA0, 0x82, 0x09, +0x80, 0x17, 0xA3, 0x0B, 0x8D, 0xDD, 0x03, 0xA3, 0x0C, 0x8D, 0xDE, 0x03, 0xA3, 0x0D, 0x8D, 0xDF, +0x03, 0xA3, 0x09, 0x8D, 0x26, 0xC0, 0xA0, 0x00, 0x00, 0xAB, 0x28, 0xA3, 0x05, 0x83, 0x0B, 0xA3, +0x03, 0x83, 0x09, 0xA3, 0x01, 0x83, 0x07, 0x68, 0x68, 0x68, 0x98, 0xC9, 0x01, 0x00, 0x6B, 0x0B, +0x08, 0x8B, 0x20, 0xAF, 0x84, 0x1B, 0xA5, 0x25, 0xD0, 0x47, 0xA9, 0x80, 0x0C, 0xD6, 0x0F, 0xD0, +0x19, 0xA4, 0x22, 0x8C, 0xDD, 0x03, 0xA5, 0x24, 0x8D, 0xDF, 0x03, 0x20, 0x9B, 0x83, 0xB0, 0x13, +0xA5, 0x26, 0x20, 0xD6, 0x83, 0xB0, 0x0C, 0x4C, 0xAF, 0x82, 0xA2, 0x08, 0x00, 0xA0, 0x82, 0x00, +0x4C, 0xC4, 0x84, 0xA9, 0x80, 0x1C, 0xD6, 0x0F, 0x4C, 0xB7, 0x82, 0x20, 0xB2, 0x83, 0xB0, 0x11, +0xA5, 0x20, 0x20, 0xD6, 0x83, 0xB0, 0x0A, 0x29, 0x10, 0xF0, 0x06, 0xAD, 0x26, 0xC0, 0x0C, 0xD7, +0x0F, 0x60, 0xAD, 0xD6, 0x0F, 0x10, 0x0A, 0x20, 0x56, 0x84, 0xB0, 0x06, 0xA9, 0x20, 0x0C, 0xD6, +0x0F, 0x18, 0x60, 0xA0, 0x00, 0x00, 0xC4, 0x26, 0xB0, 0x0A, 0xB7, 0x22, 0x20, 0xD6, 0x83, 0xB0, +0x04, 0xC8, 0x80, 0xF2, 0x18, 0x60, 0xAA, 0xAD, 0x27, 0xC0, 0x6A, 0x8A, 0xB0, 0x0F, 0x8D, 0x26, +0xC0, 0xA2, 0x4C, 0x1D, 0xCA, 0xF0, 0x6D, 0xAD, 0x27, 0xC0, 0x6A, 0xB0, 0xF7, 0x60, 0xE2, 0x30, +0xA9, 0x50, 0x2D, 0xD7, 0x0F, 0x8D, 0xD7, 0x0F, 0xF0, 0x27, 0xC9, 0x40, 0xD0, 0x0A, 0x8B, 0xA9, +0x00, 0x48, 0xAB, 0x22, 0x50, 0x00, 0xE1, 0xAB, 0xAD, 0xD7, 0x0F, 0x0A, 0x0A, 0xF0, 0x12, 0x90, +0x03, 0x8D, 0x10, 0xC0, 0xA9, 0x00, 0x8D, 0xD7, 0x0F, 0x8B, 0x48, 0xAB, 0x22, 0x4C, 0x00, 0xE1, +0xAB, 0xA9, 0x20, 0x1C, 0xD6, 0x0F, 0xF0, 0x15, 0xA9, 0x80, 0x1C, 0xD6, 0x0F, 0xF0, 0x0E, 0xF4, +0x00, 0x00, 0x0B, 0xE2, 0x30, 0x22, 0xDC, 0x03, 0xE1, 0xC2, 0x30, 0x68, 0x68, 0xE2, 0x20, 0xC2, +0x10, 0x60, 0x18, 0xA2, 0x4C, 0x1D, 0xCA, 0xF0, 0x0B, 0xAD, 0x27, 0xC0, 0x29, 0x20, 0xF0, 0xF6, +0xAD, 0x26, 0xC0, 0x60, 0x38, 0x60, 0x20, 0x42, 0x84, 0xB0, 0x24, 0x30, 0x05, 0x0C, 0xD7, 0x0F, +0x80, 0xF4, 0x29, 0x7F, 0x0C, 0xD7, 0x0F, 0x29, 0x07, 0x85, 0x00, 0xEB, 0xA9, 0x00, 0xEB, 0xA8, +0xF0, 0x0C, 0xC8, 0x20, 0x42, 0x84, 0xB0, 0x07, 0xBB, 0x95, 0x00, 0x88, 0xD0, 0xF5, 0x60, 0xA9, +0x80, 0x1C, 0xD6, 0x0F, 0x60, 0xA8, 0x0B, 0x08, 0x8B, 0xC2, 0x30, 0x20, 0xAF, 0x84, 0x1B, 0xA9, +0x80, 0x1C, 0xD6, 0x0F, 0x98, 0x20, 0x67, 0x84, 0x90, 0x04, 0xA9, 0x00, 0x85, 0x00, 0xF4, 0x00, +0x00, 0x0B, 0xE2, 0x30, 0x22, 0xDC, 0x03, 0xE1, 0xC2, 0x30, 0x68, 0x68, 0x4C, 0xEE, 0x84, 0x78, +0x3B, 0x38, 0xE9, 0x13, 0x00, 0x5B, 0x3A, 0x20, 0x82, 0xF8, 0xE2, 0x20, 0x60, 0xC2, 0x30, 0xA0, +0x00, 0x00, 0x80, 0x07, 0xC2, 0x30, 0x98, 0x09, 0x00, 0x09, 0xA8, 0xA5, 0x1E, 0x95, 0x1E, 0xA5, +0x1C, 0x95, 0x1C, 0xA5, 0x1A, 0x95, 0x1A, 0x86, 0x14, 0x3B, 0x18, 0x69, 0x16, 0x00, 0x1B, 0x65, +0x14, 0x69, 0x04, 0x00, 0xAA, 0xAB, 0x28, 0x2B, 0x98, 0xC9, 0x01, 0x00, 0x9A, 0x6B, 0x3B, 0x18, +0x69, 0x16, 0x00, 0x1B, 0xAB, 0x28, 0x2B, 0x18, 0x6B, 0x4C, 0xE5, 0x85, 0xC2, 0x10, 0xA2, 0x70, +0x17, 0xCA, 0xF0, 0x09, 0xAD, 0x26, 0xC0, 0xAD, 0x27, 0xC0, 0x6A, 0xB0, 0xF4, 0xA2, 0x4C, 0x1D, +0xA9, 0x07, 0x8D, 0x26, 0xC0, 0xCA, 0xF0, 0x09, 0xAD, 0x26, 0xC0, 0xAD, 0x27, 0xC0, 0x6A, 0xB0, +0xF4, 0x20, 0x6A, 0x86, 0xB0, 0xD3, 0x20, 0x81, 0x86, 0xB0, 0xCE, 0xA9, 0x00, 0x8D, 0xD7, 0x0F, +0x8D, 0xD6, 0x0F, 0xA9, 0xFF, 0x20, 0xA8, 0xFC, 0xAD, 0x61, 0xC0, 0x8D, 0x40, 0x01, 0x2A, 0xAD, +0x62, 0xC0, 0x8D, 0x41, 0x01, 0x10, 0x0B, 0x90, 0x09, 0xE2, 0x30, 0x20, 0xB8, 0xA1, 0x5C, 0x40, +0x71, 0xFF, 0xAD, 0x46, 0xC0, 0x30, 0xF2, 0xAD, 0x40, 0x01, 0x0D, 0x41, 0x01, 0x10, 0x0A, 0xA9, +0x00, 0x8F, 0xF4, 0x03, 0x00, 0x8F, 0xF3, 0x03, 0x00, 0xA9, 0x73, 0x20, 0xA2, 0x83, 0xC2, 0x30, +0xA9, 0xB5, 0xFF, 0x8F, 0x4E, 0x00, 0xE1, 0x8F, 0x52, 0x00, 0xE1, 0xA9, 0x5C, 0xDE, 0x8F, 0x4C, +0x00, 0xE1, 0x8F, 0x50, 0x00, 0xE1, 0xF4, 0xE1, 0x00, 0xF4, 0x68, 0x01, 0xF4, 0xFF, 0x00, 0xF4, +0xA8, 0x86, 0xF4, 0x09, 0x00, 0x4B, 0x62, 0x04, 0x00, 0x22, 0xDC, 0x82, 0xFF, 0x6B, 0xE2, 0x20, +0xAD, 0x68, 0x01, 0xC9, 0xA5, 0xF0, 0x24, 0x9C, 0xFF, 0x15, 0x9C, 0x7D, 0x01, 0xC2, 0x30, 0xA9, +0x00, 0x00, 0x8F, 0xF3, 0x03, 0x00, 0xF4, 0x02, 0x00, 0xF4, 0xFF, 0x00, 0xF4, 0xA6, 0x86, 0xF4, +0x08, 0x00, 0x4B, 0x62, 0x04, 0x00, 0x22, 0x9E, 0x82, 0xFF, 0x6B, 0xE2, 0x30, 0x20, 0x77, 0xA6, +0xF4, 0x01, 0x00, 0x4B, 0x62, 0x04, 0x00, 0x22, 0x9E, 0x82, 0xFF, 0x6B, 0xB0, 0x07, 0xE2, 0x20, +0xA9, 0x0F, 0x20, 0xA2, 0x83, 0xB0, 0x72, 0xA0, 0x00, 0x00, 0x20, 0x42, 0x84, 0xB0, 0x6A, 0x99, +0x01, 0x03, 0xC8, 0x98, 0xCD, 0x01, 0x03, 0x90, 0xF1, 0xF0, 0xEF, 0xA9, 0x0E, 0x20, 0xA2, 0x83, +0xB0, 0x57, 0xA0, 0x00, 0x00, 0x20, 0x42, 0x84, 0xB0, 0x4F, 0x99, 0xF8, 0x02, 0xC8, 0x98, 0xCD, +0xF8, 0x02, 0x90, 0xF1, 0xF0, 0xEF, 0xA9, 0xB3, 0x20, 0xA2, 0x83, 0xB0, 0x3C, 0xA9, 0x03, 0x20, +0xD6, 0x83, 0xB0, 0x35, 0xAD, 0xF3, 0x02, 0x1A, 0x20, 0xD6, 0x83, 0xB0, 0x2C, 0xA9, 0x05, 0x20, +0xA2, 0x83, 0xB0, 0x25, 0xA9, 0xFF, 0x20, 0xD6, 0x83, 0xB0, 0x1E, 0xA9, 0x04, 0x20, 0xA2, 0x83, +0xB0, 0x17, 0x20, 0x6A, 0x86, 0xB0, 0x12, 0xA9, 0x06, 0x20, 0xA2, 0x83, 0xB0, 0x0B, 0x20, 0x81, +0x86, 0xB0, 0x06, 0x20, 0xEE, 0x83, 0xE2, 0x30, 0x60, 0xE2, 0x30, 0x20, 0xB8, 0xA1, 0xF4, 0x11, +0x09, 0x20, 0x77, 0xA6, 0x8B, 0x38, 0x5C, 0xE6, 0xA4, 0xFF, 0xA9, 0x00, 0x0D, 0xF0, 0x02, 0x0A, +0x0A, 0x0D, 0xEB, 0x02, 0x0A, 0x0D, 0xF2, 0x02, 0x0A, 0x0D, 0xF1, 0x02, 0x0A, 0x0A, 0x4C, 0xD6, +0x83, 0xA9, 0x32, 0x20, 0xD6, 0x83, 0xB0, 0xD0, 0xAD, 0xE9, 0x02, 0x0A, 0x0A, 0x0A, 0x0A, 0x0D, +0xEA, 0x02, 0x20, 0xD6, 0x83, 0xB0, 0xC1, 0xAD, 0xED, 0x02, 0x0A, 0x0A, 0x0A, 0x0A, 0x0D, 0xEC, +0x02, 0x49, 0x07, 0x4C, 0xD6, 0x83, 0x51, 0xA5, 0x51, 0x00, 0xA0, 0xA0, 0xA0, 0xCD, 0xE1, 0xF2, +0xE3, 0xE8, 0xA0, 0xB1, 0xB7, 0xAC, 0xA0, 0xB1, 0xB9, 0xB8, 0xB7, 0x29, 0x8A, 0x37, 0x8A, 0x4E, +0x8A, 0x66, 0x8A, 0xDC, 0x89, 0xE2, 0x89, 0xE6, 0x89, 0xEB, 0x89, 0xF6, 0x89, 0x00, 0x8A, 0x03, +0x8A, 0x07, 0x8A, 0x7F, 0x8A, 0x70, 0x8B, 0x14, 0x8A, 0x22, 0x8A, 0xA0, 0x8A, 0xA5, 0x8A, 0xAB, +0x8A, 0xB5, 0x8A, 0xBF, 0x8A, 0xCB, 0x8A, 0x96, 0x8A, 0x9B, 0x8A, 0xE0, 0x8A, 0x07, 0x8B, 0x95, +0x8C, 0x9C, 0x8C, 0xA1, 0x8C, 0xAD, 0x8C, 0xB2, 0x8C, 0xB9, 0x8C, 0xBE, 0x8C, 0xCA, 0x8C, 0xD4, +0x8C, 0x84, 0x8F, 0xDC, 0x8C, 0xE0, 0x8C, 0xF0, 0x8C, 0xFB, 0x8C, 0x13, 0x8D, 0x22, 0x8D, 0x26, +0x8D, 0x2F, 0x8D, 0x33, 0x8D, 0x41, 0x8D, 0x47, 0x8D, 0x54, 0x8D, 0x65, 0x8D, 0x77, 0x8D, 0x7B, +0x8D, 0xD0, 0x8A, 0x82, 0x8D, 0x86, 0x8D, 0x90, 0x8D, 0x96, 0x8D, 0x84, 0x8F, 0x4F, 0x8B, 0xA1, +0x8C, 0x1C, 0x8E, 0x23, 0x8E, 0x2A, 0x8E, 0x31, 0x8E, 0x38, 0x8E, 0x3F, 0x8E, 0x46, 0x8E, 0x84, +0x8F, 0x4D, 0x8E, 0x59, 0x8E, 0x69, 0x8E, 0x78, 0x8E, 0x8A, 0x8E, 0x96, 0x8E, 0xA2, 0x8E, 0xAE, +0x8E, 0x2E, 0x8B, 0xBA, 0x8E, 0xCE, 0x8E, 0xE4, 0x8E, 0xF3, 0x8E, 0x03, 0x8F, 0x08, 0x8F, 0x0B, +0x8F, 0x0F, 0x8F, 0x84, 0x8F, 0x15, 0x8F, 0x19, 0x8F, 0x1F, 0x8F, 0x0F, 0x8F, 0x25, 0x8F, 0x3A, +0x8F, 0x58, 0x8B, 0x84, 0x8F, 0x42, 0x8B, 0x4F, 0x8F, 0x60, 0x8F, 0x74, 0x8F, 0x86, 0x8F, 0x84, +0x8F, 0x8C, 0x8F, 0x92, 0x8F, 0x99, 0x8F, 0x9E, 0x8F, 0xA7, 0x8F, 0xA9, 0x8F, 0xAB, 0x8F, 0xAD, +0x8F, 0xB0, 0x8F, 0xB2, 0x8F, 0xB5, 0x8F, 0xB7, 0x8F, 0xB9, 0x8F, 0xBC, 0x8F, 0xC1, 0x8F, 0xC4, +0x8F, 0xC7, 0x8F, 0xCA, 0x8F, 0xCE, 0x8F, 0xD2, 0x8F, 0xD6, 0x8F, 0xDA, 0x8F, 0xDE, 0x8F, 0xE2, +0x8F, 0xE6, 0x8F, 0xEB, 0x8F, 0xEE, 0x8F, 0xF1, 0x8F, 0xF4, 0x8F, 0xF7, 0x8F, 0xFA, 0x8F, 0xFD, +0x8F, 0x00, 0x90, 0x03, 0x90, 0x06, 0x90, 0x0A, 0x90, 0x0E, 0x90, 0x13, 0x90, 0xA7, 0x8F, 0xAB, +0x8F, 0x9F, 0x8D, 0xA4, 0x8D, 0xAC, 0x8D, 0xB5, 0x8D, 0xBB, 0x8D, 0xC5, 0x8D, 0xCE, 0x8D, 0xD9, +0x8D, 0xE3, 0x8D, 0xE8, 0x8D, 0xEE, 0x8D, 0xF8, 0x8D, 0xFC, 0x8D, 0x07, 0x8E, 0x0D, 0x8E, 0x17, +0x8E, 0x1D, 0x90, 0xB5, 0x8F, 0x1F, 0x90, 0x25, 0x90, 0x29, 0x90, 0x2F, 0x90, 0x35, 0x90, 0x3C, +0x90, 0x43, 0x90, 0x49, 0x90, 0x50, 0x90, 0x56, 0x90, 0x65, 0x90, 0x6C, 0x90, 0x72, 0x90, 0x7A, +0x90, 0x80, 0x90, 0x85, 0x90, 0x8C, 0x90, 0x93, 0x90, 0x9D, 0x90, 0xA2, 0x90, 0xA7, 0x90, 0xA9, +0x90, 0xAB, 0x90, 0xAD, 0x90, 0xAF, 0x90, 0xB1, 0x90, 0xB3, 0x90, 0xB5, 0x90, 0xB7, 0x90, 0xB9, +0x90, 0xBB, 0x90, 0xBD, 0x90, 0x22, 0x8C, 0x2F, 0x8C, 0x3F, 0x8C, 0x4F, 0x8C, 0x5F, 0x8C, 0x6F, +0x8C, 0x7F, 0x8C, 0x8E, 0x8C, 0x22, 0x8C, 0x37, 0x8C, 0x57, 0x8C, 0x6F, 0x8C, 0x8E, 0x8C, 0xBF, +0x90, 0xC5, 0x90, 0x22, 0x8C, 0x28, 0x8C, 0x2F, 0x8C, 0x37, 0x8C, 0x3F, 0x8C, 0x47, 0x8C, 0x4F, +0x8C, 0x57, 0x8C, 0x5F, 0x8C, 0x67, 0x8C, 0x6F, 0x8C, 0x77, 0x8C, 0x7F, 0x8C, 0x87, 0x8C, 0x8E, +0x8C, 0xD2, 0x90, 0xC9, 0x90, 0xDE, 0x90, 0xC9, 0x90, 0xE8, 0x90, 0xC9, 0x90, 0xFD, 0x90, 0xC9, +0x90, 0x07, 0x91, 0xC9, 0x90, 0x11, 0x91, 0xC9, 0x90, 0x1A, 0x91, 0xC9, 0x90, 0x2C, 0x91, 0x21, +0x8E, 0x28, 0x8E, 0x2F, 0x8E, 0x36, 0x8E, 0x3D, 0x8E, 0x44, 0x8E, 0x4B, 0x8E, 0xD4, 0x8C, 0x30, +0x91, 0x38, 0x91, 0x40, 0x91, 0x48, 0x91, 0x50, 0x91, 0x55, 0x91, 0x5C, 0x91, 0x63, 0x91, 0x7A, +0x91, 0x7D, 0x91, 0x81, 0x91, 0x8C, 0x91, 0xFA, 0xBB, 0x11, 0xBB, 0x1E, 0xBB, 0x46, 0xBB, 0x58, +0xBB, 0x68, 0xBB, 0x7F, 0xBB, 0x1E, 0x30, 0x3C, 0x3A, 0x25, 0x32, 0x12, 0x12, 0x55, 0x5B, 0x5D, +0x75, 0x66, 0x5E, 0x3D, 0x3D, 0x73, 0xA2, 0xA8, 0xAA, 0xBE, 0xB3, 0xAB, 0x8A, 0x96, 0xC0, 0xD8, +0xDE, 0xE0, 0xF4, 0xE9, 0xE1, 0xC0, 0xCC, 0xF6, 0x84, 0xFF, 0xF2, 0xFF, 0xFE, 0xFF, 0x10, 0xFE, +0x80, 0xF0, 0x80, 0xFE, 0x00, 0xF0, 0x00, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0x00, 0xFA, 0xD9, 0x53, +0x11, 0xF9, 0x1C, 0x19, 0x1C, 0x1C, 0xD8, 0x00, 0x2B, 0x31, 0x61, 0x3A, 0x50, 0x44, 0x3B, 0x25, +0x25, 0x59, 0x64, 0x66, 0x6B, 0x6B, 0x6B, 0x6B, 0x6D, 0x7C, 0x84, 0x6B, 0x6B, 0x6B, 0x87, 0x89, +0x8B, 0x8B, 0x8B, 0x6B, 0x9B, 0x9D, 0x9D, 0x6B, 0xBD, 0xC5, 0xC5, 0xC5, 0x6B, 0x6B, 0xCA, 0x6B, +0xCC, 0xCC, 0xDB, 0xDD, 0xDF, 0xE1, 0xE3, 0xE5, 0xE7, 0xE9, 0xF3, 0xF6, 0xCA, 0x02, 0x05, 0x02, +0x02, 0x02, 0x02, 0x0F, 0x08, 0x03, 0x02, 0x02, 0x02, 0x02, 0x05, 0x02, 0x02, 0x02, 0x02, 0x0F, +0x08, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x02, 0x0F, 0x0F, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x0A, 0x80, 0xC0, 0x02, 0x08, 0x05, 0x05, 0x05, 0x02, 0x02, 0x02, +0x02, 0x03, 0x02, 0x80, 0x80, 0x0C, 0x1F, 0x64, 0x03, 0x18, 0x3C, 0x3C, 0x02, 0x1F, 0x1C, 0x1F, +0x1E, 0x1F, 0x1E, 0x1F, 0x1F, 0x1E, 0x1F, 0x1E, 0x1F, 0x1D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x0D, 0x06, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x02, 0x01, +0x01, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x06, 0x00, 0x05, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0A, 0x00, 0x01, 0x02, 0x03, +0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x54, 0x69, 0x6D, 0x65, +0x3D, 0xA0, 0x53, 0x74, 0x65, 0xF0, 0x54, 0x72, 0x61, 0x63, 0xE5, 0x43, 0x62, 0x61, 0x6E, 0x6B, +0x20, 0x28, 0x30, 0x2F, 0x31, 0xA9, 0x44, 0x65, 0x63, 0x69, 0x6D, 0x61, 0x6C, 0x2D, 0x3E, 0xA0, +0x48, 0x65, 0x78, 0x2D, 0x3E, 0x20, 0xA4, 0x54, 0x6F, 0x6F, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, +0x72, 0x2D, 0x3E, 0xA0, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x20, 0x50, 0x61, 0x6E, +0x65, 0xEC, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0xBA, 0x0E, 0xA0, 0xC9, 0xAF, 0xCF, 0xA0, 0xE5, +0xF2, 0xF2, 0xEF, 0xF2, 0xA1, 0x8D, 0x00, 0x0A, 0xA0, 0xCE, 0xEF, 0xF4, 0xA0, 0xE1, 0xA0, 0xF3, +0xF4, 0xE1, 0xF2, 0xF4, 0xF5, 0xF0, 0xA0, 0xE4, 0xE9, 0xF3, 0xEB, 0xA1, 0x8D, 0x00, 0x0A, 0xA0, +0xCE, 0xEF, 0xA0, 0xE4, 0xE5, 0xF6, 0xE9, 0xE3, 0xE5, 0xA0, 0xE3, 0xEF, 0xEE, 0xEE, 0xE5, 0xE3, +0xF4, 0xE5, 0xE4, 0xA1, 0x8D, 0x00, 0x0A, 0xA0, 0xC3, 0xE8, 0xE5, 0xE3, 0xEB, 0xA0, 0xF3, 0xF4, +0xE1, 0xF2, 0xF4, 0xF5, 0xF0, 0xA0, 0xE4, 0xE5, 0xF6, 0xE9, 0xE3, 0xE5, 0xA1, 0x8D, 0x00, 0x08, +0xA0, 0xC6, 0xE1, 0xF4, 0xE1, 0xEC, 0xA0, 0xF3, 0xF9, 0xF3, 0xF4, 0xE5, 0xED, 0xA0, 0xE5, 0xF2, +0xF2, 0xEF, 0xF2, 0xAD, 0xBE, 0xA0, 0x00, 0xA0, 0x0D, 0xDF, 0xA0, 0x00, 0xA0, 0x0D, 0x4C, 0xA0, +0x00, 0xA0, 0x4A, 0xA0, 0x4B, 0x00, 0xA0, 0x48, 0xA0, 0x55, 0x00, 0x12, 0xA0, 0xCF, 0xF0, 0xE5, +0xEE, 0xBA, 0xA0, 0x4D, 0x00, 0x02, 0xA0, 0xD3, 0xE1, 0xF6, 0xE5, 0xBA, 0xA0, 0x4D, 0x00, 0x02, +0xA0, 0xC3, 0xE1, 0xEE, 0xE3, 0xE5, 0xEC, 0xBA, 0xC5, 0xF3, 0xE3, 0x00, 0x5A, 0x0D, 0xA0, 0x5F, +0x00, 0x53, 0xD3, 0xE3, 0xF2, 0xE5, 0xE5, 0xEE, 0xA0, 0xC3, 0xEF, 0xEC, 0xEF, 0xF2, 0xF3, 0x53, +0x00, 0x53, 0xD7, 0xC1, 0xD2, 0xCE, 0xC9, 0xCE, 0xC7, 0xBA, 0xA0, 0xD0, 0xF2, 0xE9, 0xEE, 0xF4, +0xE5, 0xF2, 0xA0, 0xAF, 0xA0, 0xCD, 0xEF, 0xE4, 0xE5, 0xED, 0xA0, 0xAF, 0xA0, 0xC1, 0xF0, 0xF0, +0xEC, 0xE5, 0xD4, 0xE1, 0xEC, 0xEB, 0x53, 0x00, 0x53, 0xE3, 0xE1, 0xEE, 0xEE, 0xEF, 0xF4, 0xA0, +0xE2, 0xE5, 0xA0, 0xE1, 0xE3, 0xF4, 0xE9, 0xF6, 0xE5, 0xA0, 0xE1, 0xF4, 0xA0, 0xF4, 0xE8, 0xE5, +0xA0, 0xF3, 0xE1, 0xED, 0xE5, 0xA0, 0xF4, 0xE9, 0xED, 0xE5, 0xA1, 0xA1, 0xA1, 0x53, 0x00, 0x53, +0xC1, 0xE4, 0xF6, 0xE1, 0xEE, 0xE3, 0xE5, 0xE4, 0xA0, 0xC6, 0xE5, 0xE1, 0xF4, 0xF5, 0xF2, 0xE5, +0xF3, 0x53, 0x00, 0x53, 0xD2, 0xC1, 0xCD, 0xA0, 0xD3, 0xF4, 0xE1, 0xF4, 0xF5, 0xF3, 0x53, 0x00, +0x53, 0xC8, 0xE5, 0xF2, 0xF4, 0xFA, 0xBA, 0xA0, 0x00, 0x53, 0xCC, 0xE1, 0xF2, 0xE7, 0xE5, 0xF3, +0xF4, 0xA0, 0xD3, 0xE5, 0xEC, 0xE5, 0xE3, 0xF4, 0xE1, 0xE2, 0xEC, 0xE5, 0xBA, 0x03, 0xA0, 0x00, +0x02, 0xA0, 0xB1, 0xBD, 0xC5, 0xEE, 0xF4, 0xE5, 0xF2, 0xA0, 0xF4, 0xE8, 0xE5, 0xA0, 0xC3, 0xEF, +0xEE, 0xF4, 0xF2, 0xEF, 0xEC, 0xA0, 0xD0, 0xE1, 0xEE, 0xE5, 0xEC, 0xAE, 0x8D, 0x8D, 0xA0, 0xA0, +0xB2, 0xBD, 0xD3, 0xE5, 0xF4, 0xA0, 0xF3, 0xF9, 0xF3, 0xF4, 0xE5, 0xED, 0xA0, 0xF3, 0xF4, 0xE1, +0xEE, 0xE4, 0xE1, 0xF2, 0xE4, 0xF3, 0xA0, 0xE1, 0xEE, 0xE4, 0xA0, 0xB6, 0xB0, 0xA0, 0xE8, 0xE5, +0xF2, 0xF4, 0xFA, 0xAE, 0x8D, 0x8D, 0xA0, 0xA0, 0xB3, 0xBD, 0xD3, 0xE5, 0xF4, 0xA0, 0xF3, 0xF9, +0xF3, 0xF4, 0xE5, 0xED, 0xA0, 0xF3, 0xF4, 0xE1, 0xEE, 0xE4, 0xE1, 0xF2, 0xE4, 0xF3, 0xA0, 0xE1, +0xEE, 0xE4, 0xA0, 0xB5, 0xB0, 0xA0, 0xE8, 0xE5, 0xF2, 0xF4, 0xFA, 0xAE, 0x8D, 0x8D, 0xA0, 0xA0, +0xB4, 0xBD, 0xC3, 0xEF, 0xEE, 0xF4, 0xE9, 0xEE, 0xF5, 0xE5, 0xA0, 0xF2, 0xE5, 0xF3, 0xF4, 0xE1, +0xF2, 0xF4, 0xE9, 0xEE, 0xE7, 0xA0, 0xF4, 0xE8, 0xE5, 0xA0, 0xF3, 0xF9, 0xF3, 0xF4, 0xE5, 0xED, +0xAE, 0x08, 0x8D, 0x05, 0xA0, 0xD0, 0xF2, 0xE5, 0xF3, 0xF3, 0xA0, 0xB1, 0xAC, 0xB2, 0xAC, 0xB3, +0xA0, 0xEF, 0xF2, 0xA0, 0xB4, 0xA0, 0xF4, 0xEF, 0xA0, 0xE3, 0xEF, 0xEE, 0xF4, 0xE9, 0xEE, 0xF5, +0xE5, 0xAE, 0x00, 0x5A, 0xAA, 0x0E, 0x53, 0x5F, 0x00, 0x5A, 0x53, 0xAA, 0x0D, 0x53, 0x5F, 0x00, +0x5A, 0x53, 0x53, 0xAA, 0x0C, 0x53, 0x5F, 0x00, 0x5A, 0x03, 0x53, 0xAA, 0x0B, 0x53, 0x5F, 0x00, +0x5A, 0x04, 0x53, 0xAA, 0x0A, 0x53, 0x5F, 0x00, 0x5A, 0x05, 0x53, 0xAA, 0x09, 0x53, 0x5F, 0x00, +0x5A, 0x06, 0x53, 0xAA, 0x08, 0x53, 0x5F, 0x00, 0x5A, 0x07, 0x53, 0xAA, 0x07, 0x53, 0x5F, 0x00, +0x5A, 0x08, 0x53, 0xAA, 0x06, 0x53, 0x5F, 0x00, 0x5A, 0x09, 0x53, 0xAA, 0x05, 0x53, 0x5F, 0x00, +0x5A, 0x0A, 0x53, 0xAA, 0x04, 0x53, 0x5F, 0x00, 0x5A, 0x0B, 0x53, 0xAA, 0x03, 0x53, 0x5F, 0x00, +0x5A, 0x0C, 0x53, 0xAA, 0x53, 0x53, 0x5F, 0x00, 0x5A, 0x0D, 0x53, 0xAA, 0x53, 0x5F, 0x00, 0x5A, +0x0E, 0x53, 0xAA, 0x5F, 0x00, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0xF9, 0x53, 0x6F, 0x75, 0x6E, +0xE4, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x53, 0x70, 0x65, 0x65, 0xE4, 0x43, 0x6C, 0x6F, +0x63, 0xEB, 0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0xF3, 0x53, 0x6C, 0x6F, 0x74, 0xF3, 0x50, 0x72, +0x69, 0x6E, 0x74, 0x65, 0x72, 0x20, 0x50, 0x6F, 0x72, 0xF4, 0x4D, 0x6F, 0x64, 0x65, 0x6D, 0x20, +0x50, 0x6F, 0x72, 0xF4, 0x52, 0x41, 0x4D, 0x20, 0x44, 0x69, 0x73, 0xEB, 0x51, 0x75, 0x69, 0xF4, +0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x65, 0xE4, +0x4C, 0x69, 0x6E, 0x65, 0x20, 0x4C, 0x65, 0x6E, 0x67, 0x74, 0xE8, 0x44, 0x65, 0x6C, 0x65, 0x74, +0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x4C, 0x46, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, +0x20, 0x43, 0xD2, 0x41, 0x64, 0x64, 0x20, 0x4C, 0x46, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, +0x43, 0xD2, 0x45, 0x63, 0x68, 0xEF, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6E, 0xE7, 0x42, +0x61, 0x75, 0xE4, 0x44, 0x61, 0x74, 0x61, 0x2F, 0x53, 0x74, 0x6F, 0x70, 0x20, 0x42, 0x69, 0x74, +0xF3, 0x50, 0x61, 0x72, 0x69, 0x74, 0xF9, 0x44, 0x43, 0x44, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x73, +0x68, 0x61, 0x6B, 0xE5, 0x44, 0x53, 0x52, 0x2F, 0x44, 0x54, 0x52, 0x20, 0x48, 0x61, 0x6E, 0x64, +0x73, 0x68, 0x61, 0x6B, 0xE5, 0x58, 0x4F, 0x4E, 0x2F, 0x58, 0x4F, 0x46, 0x46, 0x20, 0x48, 0x61, +0x6E, 0x64, 0x73, 0x68, 0x61, 0x6B, 0xE5, 0x54, 0x79, 0x70, 0xE5, 0x43, 0x6F, 0x6C, 0x75, 0x6D, +0x6E, 0xF3, 0x54, 0x65, 0x78, 0xF4, 0x42, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0xE4, +0x42, 0x6F, 0x72, 0x64, 0x65, 0xF2, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0xF3, 0x42, +0x6C, 0x61, 0x63, 0xEB, 0x44, 0x65, 0x65, 0x70, 0x20, 0x52, 0x65, 0xE4, 0x44, 0x61, 0x72, 0x6B, +0x20, 0x42, 0x6C, 0x75, 0xE5, 0x50, 0x75, 0x72, 0x70, 0x6C, 0xE5, 0x44, 0x61, 0x72, 0x6B, 0x20, +0x47, 0x72, 0x65, 0x65, 0xEE, 0x44, 0x61, 0x72, 0x6B, 0x20, 0x47, 0x72, 0x61, 0xF9, 0x4D, 0x65, +0x64, 0x69, 0x75, 0x6D, 0x20, 0x42, 0x6C, 0x75, 0xE5, 0x4C, 0x69, 0x67, 0x68, 0x74, 0x20, 0x42, +0x6C, 0x75, 0xE5, 0x42, 0x72, 0x6F, 0x77, 0xEE, 0x4F, 0x72, 0x61, 0x6E, 0x67, 0xE5, 0x4C, 0x69, +0x67, 0x68, 0x74, 0x20, 0x47, 0x72, 0x61, 0xF9, 0x50, 0x69, 0x6E, 0xEB, 0x4C, 0x69, 0x67, 0x68, +0x74, 0x20, 0x47, 0x72, 0x65, 0x65, 0xEE, 0x59, 0x65, 0x6C, 0x6C, 0x6F, 0xF7, 0x41, 0x71, 0x75, +0x61, 0x6D, 0x61, 0x72, 0x69, 0x6E, 0xE5, 0x57, 0x68, 0x69, 0x74, 0xE5, 0x53, 0x6C, 0x6F, 0x74, +0x20, 0xB1, 0x00, 0x53, 0x6C, 0x6F, 0x74, 0x20, 0xB2, 0x00, 0x53, 0x6C, 0x6F, 0x74, 0x20, 0xB3, +0x00, 0x53, 0x6C, 0x6F, 0x74, 0x20, 0xB4, 0x00, 0x53, 0x6C, 0x6F, 0x74, 0x20, 0xB5, 0x00, 0x53, +0x6C, 0x6F, 0x74, 0x20, 0xB6, 0x00, 0x53, 0x6C, 0x6F, 0x74, 0x20, 0xB7, 0x00, 0x53, 0x74, 0x61, +0x72, 0x74, 0x75, 0x70, 0x20, 0x53, 0x6C, 0x6F, 0xF4, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, +0x20, 0x4C, 0x61, 0x6E, 0x67, 0x75, 0x61, 0x67, 0xE5, 0x4B, 0x65, 0x79, 0x62, 0x6F, 0x61, 0x72, +0x64, 0x20, 0x4C, 0x61, 0x79, 0x6F, 0x75, 0xF4, 0x4B, 0x65, 0x79, 0x62, 0x6F, 0x61, 0x72, 0x64, +0x20, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6E, 0xE7, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, +0x20, 0x53, 0x70, 0x65, 0x65, 0xE4, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x20, 0x44, 0x65, 0x6C, +0x61, 0xF9, 0x44, 0x6F, 0x75, 0x62, 0x6C, 0x65, 0x20, 0x43, 0x6C, 0x69, 0x63, 0xEB, 0x43, 0x75, +0x72, 0x73, 0x6F, 0x72, 0x20, 0x46, 0x6C, 0x61, 0x73, 0xE8, 0x53, 0x68, 0x69, 0x66, 0x74, 0x20, +0x43, 0x61, 0x70, 0x73, 0x2F, 0x4C, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0xE5, 0x46, 0x61, +0x73, 0x74, 0x20, 0x53, 0x70, 0x61, 0x63, 0x65, 0x2F, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, +0x4B, 0x65, 0x79, 0xF3, 0x44, 0x75, 0x61, 0x6C, 0x20, 0x53, 0x70, 0x65, 0x65, 0x64, 0x20, 0x4B, +0x65, 0x79, 0xF3, 0x48, 0x69, 0x67, 0x68, 0x20, 0x53, 0x70, 0x65, 0x65, 0x64, 0x20, 0x4D, 0x6F, +0x75, 0x73, 0xE5, 0x4D, 0x6F, 0x6E, 0x74, 0xE8, 0x44, 0x61, 0xF9, 0x59, 0x65, 0x61, 0xF2, 0x46, +0x6F, 0x72, 0x6D, 0x61, 0xF4, 0x48, 0x6F, 0x75, 0xF2, 0x4D, 0x69, 0x6E, 0x75, 0x74, 0xE5, 0x53, +0x65, 0x63, 0x6F, 0x6E, 0xE4, 0x4D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x20, 0x52, 0x41, 0x4D, +0x20, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x53, 0x69, 0x7A, 0xE5, 0x4D, 0x61, 0x78, 0x69, 0x6D, 0x75, +0x6D, 0x20, 0x52, 0x41, 0x4D, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x53, 0x69, 0x7A, 0xE5, 0x52, +0x41, 0x4D, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x53, 0x69, 0x7A, 0x65, 0x3A, 0x08, 0x20, 0xA0, +0x54, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x52, 0x41, 0x4D, 0x20, 0x69, 0x6E, 0x20, 0x55, 0x73, 0x65, +0x3A, 0x05, 0x20, 0xA0, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x52, +0x41, 0x4D, 0x3A, 0x07, 0x20, 0xA0, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0xE5, 0x20, 0x50, 0x69, 0x74, +0x63, 0xE8, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x65, 0xF2, 0x4D, 0x6F, 0x64, 0x65, 0xED, 0x55, 0x6E, +0x6C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0xE4, 0x34, 0xB0, 0x37, 0xB2, 0x38, 0xB0, 0x31, 0x33, 0xB2, +0x4E, 0xEF, 0x59, 0x65, 0xF3, 0x35, 0xB0, 0x37, 0xB5, 0x31, 0x31, 0xB0, 0x31, 0x33, 0x34, 0x2E, +0xB5, 0x31, 0x35, 0xB0, 0x33, 0x30, 0xB0, 0x36, 0x30, 0xB0, 0x31, 0x32, 0x30, 0xB0, 0x31, 0x38, +0x30, 0xB0, 0x32, 0x34, 0x30, 0xB0, 0x33, 0x36, 0x30, 0xB0, 0x34, 0x38, 0x30, 0xB0, 0x37, 0x32, +0x30, 0xB0, 0x39, 0x36, 0x30, 0xB0, 0x31, 0x39, 0x32, 0x30, 0xB0, 0x35, 0x2F, 0xB1, 0x35, 0x2F, +0xB2, 0x36, 0x2F, 0xB1, 0x36, 0x2F, 0xB2, 0x37, 0x2F, 0xB1, 0x37, 0x2F, 0xB2, 0x38, 0x2F, 0xB1, +0x38, 0x2F, 0xB2, 0x4F, 0x64, 0xE4, 0x45, 0x76, 0x65, 0xEE, 0x4E, 0x6F, 0x6E, 0xE5, 0x43, 0x6F, +0x6C, 0x6F, 0xF2, 0x4D, 0x6F, 0x6E, 0x6F, 0x63, 0x68, 0x72, 0x6F, 0x6D, 0xE5, 0x36, 0xB0, 0x55, +0x2E, 0x53, 0x2E, 0x41, 0xAE, 0x55, 0x2E, 0x4B, 0xAE, 0x46, 0x72, 0x65, 0x6E, 0x63, 0xE8, 0x44, +0x61, 0x6E, 0x69, 0x73, 0xE8, 0x53, 0x70, 0x61, 0x6E, 0x69, 0x73, 0xE8, 0x49, 0x74, 0x61, 0x6C, +0x69, 0x61, 0xEE, 0x47, 0x65, 0x72, 0x6D, 0x61, 0xEE, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0xE8, +0x44, 0x76, 0x6F, 0x72, 0x61, 0xEB, 0x46, 0x72, 0x65, 0x6E, 0x63, 0x68, 0x20, 0x43, 0x61, 0x6E, +0x61, 0x64, 0x69, 0x61, 0xEE, 0x46, 0x6C, 0x65, 0x6D, 0x69, 0x73, 0xE8, 0x48, 0x65, 0x62, 0x72, +0x65, 0xF7, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x65, 0x73, 0xE5, 0x41, 0x72, 0x61, 0x62, 0x69, 0xE3, +0x47, 0x72, 0x65, 0x65, 0xEB, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x73, 0xE8, 0x46, 0x69, 0x6E, 0x6E, +0x69, 0x73, 0xE8, 0x50, 0x6F, 0x72, 0x74, 0x75, 0x67, 0x75, 0x65, 0x73, 0xE5, 0x54, 0x61, 0x6D, +0x69, 0xEC, 0x48, 0x69, 0x6E, 0x64, 0xF5, 0x54, 0xB1, 0x54, 0xB2, 0x54, 0xB3, 0x54, 0xB4, 0x54, +0xB5, 0x54, 0xB6, 0x4C, 0xB1, 0x4C, 0xB2, 0x4C, 0xB3, 0x4C, 0xB4, 0x4C, 0xB5, 0x4C, 0xB6, 0x4E, +0x6F, 0x72, 0x6D, 0x61, 0xEC, 0x46, 0x61, 0x73, 0xF4, 0x59, 0x6F, 0x75, 0x72, 0x20, 0x43, 0x61, +0x72, 0xE4, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x20, 0x50, 0x6F, 0x72, 0xF4, 0x4D, 0x6F, +0x64, 0x65, 0x6D, 0x20, 0x50, 0x6F, 0x72, 0xF4, 0x42, 0x75, 0x69, 0x6C, 0x74, 0x2D, 0x69, 0x6E, +0x20, 0x54, 0x65, 0x78, 0x74, 0x20, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0xF9, 0x4D, 0x6F, 0x75, +0x73, 0x65, 0x20, 0x50, 0x6F, 0x72, 0xF4, 0x53, 0x6D, 0x61, 0x72, 0x74, 0x20, 0x50, 0x6F, 0x72, +0xF4, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x50, 0x6F, 0x72, 0xF4, 0x42, 0x75, 0x69, 0x6C, 0x74, 0x2D, +0x69, 0x6E, 0x20, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x54, 0x61, 0x6C, 0xEB, 0x53, 0x63, 0x61, 0xEE, +0x52, 0x4F, 0x4D, 0x20, 0x44, 0x69, 0x73, 0xEB, 0x4D, 0x4D, 0x2F, 0x44, 0x44, 0x2F, 0x59, 0xD9, +0x44, 0x44, 0x2F, 0x4D, 0x4D, 0x2F, 0x59, 0xD9, 0x59, 0x59, 0x2F, 0x4D, 0x4D, 0x2F, 0x44, 0xC4, +0x41, 0x4D, 0x2D, 0x50, 0xCD, 0x32, 0x34, 0x20, 0x48, 0x6F, 0x75, 0xF2, 0x03, 0xA0, 0xD4, 0xF5, +0xF2, 0xEE, 0x00, 0x20, 0x41, 0x6C, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x74, 0x65, 0x20, 0x44, 0x69, +0x73, 0x70, 0x6C, 0x61, 0x79, 0x20, 0x4D, 0x6F, 0x64, 0xE5, 0x20, 0x4F, 0xEE, 0x20, 0x4F, 0x66, +0xE6, 0x10, 0xA0, 0xC1, 0xE3, 0xE3, 0xE5, 0xF0, 0xF4, 0xA0, 0x4D, 0x00, 0x57, 0x65, 0x6C, 0x63, +0x6F, 0x6D, 0x65, 0x2E, 0x2E, 0x2E, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x2D, 0x59, 0x20, +0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x65, 0x78, 0x69, 0x74, 0xF3, 0xAD, 0x15, 0xC0, 0x48, +0x20, 0x76, 0xA9, 0x20, 0xC8, 0x9B, 0xA2, 0x01, 0xA0, 0x01, 0xA9, 0xF9, 0x20, 0x28, 0x96, 0x20, +0x39, 0x98, 0xA2, 0x01, 0xA0, 0x0B, 0xA9, 0xF8, 0x20, 0x28, 0x96, 0xA9, 0xF9, 0x20, 0x80, 0xC0, +0xAF, 0x7C, 0x01, 0xE1, 0xD0, 0x04, 0xA9, 0xFA, 0x80, 0x02, 0xA9, 0xFB, 0x20, 0x80, 0xC0, 0xA2, +0x01, 0xA0, 0x16, 0xA9, 0x14, 0x20, 0x28, 0x96, 0xA9, 0xFC, 0x20, 0x80, 0xC0, 0x20, 0x27, 0x98, +0x20, 0x74, 0xCF, 0x10, 0xFB, 0xC9, 0x8D, 0xF0, 0x09, 0xC9, 0x9B, 0xF0, 0x12, 0x20, 0x5D, 0xA0, +0x80, 0xEE, 0x20, 0xFC, 0xA8, 0xAF, 0x7C, 0x01, 0xE1, 0x49, 0xFF, 0x8F, 0x7C, 0x01, 0xE1, 0x4C, +0xBC, 0x93, 0x78, 0xA9, 0x10, 0x1C, 0x27, 0xC0, 0x58, 0x20, 0x2B, 0xFA, 0xF0, 0x03, 0x8D, 0x0A, +0xC0, 0xA9, 0x11, 0x20, 0x71, 0xA9, 0x20, 0xC8, 0x9B, 0xA9, 0x80, 0x8D, 0x36, 0xC0, 0x8F, 0x37, +0x01, 0xE1, 0x0A, 0x9C, 0xF3, 0x03, 0x9C, 0xF4, 0x03, 0xA0, 0x08, 0xA2, 0x00, 0xA9, 0x0D, 0x20, +0x28, 0x96, 0x20, 0x27, 0x98, 0x8D, 0x06, 0xC0, 0xAD, 0x00, 0xC0, 0x10, 0xFB, 0x8D, 0x10, 0xC0, +0xC9, 0xB1, 0xF0, 0x24, 0xC9, 0xB2, 0xF0, 0x0D, 0xC9, 0xB3, 0xF0, 0x0D, 0xC9, 0xB4, 0xF0, 0x17, +0x20, 0x5D, 0xA0, 0x80, 0xE3, 0x5C, 0x01, 0xB5, 0xFF, 0x22, 0x01, 0xB5, 0xFF, 0xA9, 0x01, 0x8F, +0xDD, 0x02, 0xE1, 0x5C, 0x1C, 0xB5, 0xFF, 0x6B, 0xAF, 0xD9, 0x02, 0xE1, 0xF0, 0x05, 0xA9, 0x1B, +0x20, 0x71, 0xA9, 0xAD, 0x15, 0xC0, 0x48, 0x08, 0x78, 0xAD, 0x27, 0xC0, 0x85, 0xB0, 0xAD, 0x23, +0xC0, 0x85, 0xB1, 0xA9, 0x04, 0x1C, 0x27, 0xC0, 0x0C, 0x23, 0xC0, 0x9C, 0x32, 0xC0, 0xC2, 0x20, +0xAF, 0x54, 0x00, 0xE1, 0x85, 0xB2, 0xAF, 0x56, 0x00, 0xE1, 0x85, 0xB4, 0x4B, 0xA2, 0x9B, 0xDA, +0x68, 0x8F, 0x56, 0x00, 0xE1, 0xA9, 0x5C, 0xE2, 0x8F, 0x54, 0x00, 0xE1, 0xE2, 0x30, 0x28, 0x22, +0x3E, 0xB5, 0xFF, 0x38, 0x22, 0x94, 0x00, 0xE1, 0xA2, 0x02, 0x20, 0x79, 0xA6, 0xA2, 0x0D, 0x0C, +0x22, 0x00, 0x00, 0xE1, 0xA3, 0x01, 0x85, 0x5C, 0xA3, 0x03, 0x85, 0x5E, 0xA2, 0x02, 0x1D, 0x22, +0x00, 0x00, 0xE1, 0xA3, 0x01, 0x85, 0x50, 0x85, 0x58, 0xA3, 0x03, 0x85, 0x52, 0x38, 0xE9, 0x04, +0x00, 0x85, 0x5A, 0xD0, 0x0C, 0x8F, 0xF6, 0x02, 0xE1, 0xE2, 0x30, 0x22, 0x80, 0x00, 0xE1, 0xC2, +0x30, 0xA2, 0x02, 0x1B, 0x22, 0x00, 0x00, 0xE1, 0xA3, 0x01, 0x85, 0x54, 0xA3, 0x03, 0x85, 0x56, +0xA5, 0x50, 0x38, 0xE5, 0x54, 0x85, 0x60, 0xA5, 0x52, 0xE5, 0x56, 0x85, 0x62, 0x68, 0x68, 0xE2, +0x30, 0x20, 0xC8, 0x9B, 0xA0, 0x00, 0x20, 0xA8, 0x9A, 0xA2, 0x01, 0xA0, 0x00, 0x20, 0x14, 0x96, +0xA9, 0xDF, 0x20, 0x1E, 0x97, 0xA9, 0x0A, 0x85, 0x00, 0x78, 0xA5, 0x00, 0x85, 0x01, 0xA9, 0x0A, +0x85, 0x00, 0xA0, 0x01, 0x20, 0xA8, 0x9A, 0x20, 0x2E, 0x96, 0x20, 0x39, 0x98, 0x20, 0xBB, 0x9A, +0x20, 0x5D, 0x96, 0xA9, 0x04, 0x85, 0x25, 0xA9, 0x1A, 0x48, 0xE6, 0x25, 0x38, 0xE9, 0x1A, 0xC5, +0x01, 0xD0, 0x03, 0x20, 0xD7, 0x9B, 0xA4, 0x25, 0xA2, 0x04, 0xA3, 0x01, 0x20, 0x28, 0x96, 0x20, +0xC8, 0x9B, 0x68, 0x1A, 0xC9, 0x25, 0x90, 0xE1, 0x20, 0x4F, 0x9A, 0xC9, 0x8D, 0xF0, 0x13, 0xC9, +0x9B, 0xF0, 0x09, 0xC9, 0x00, 0xF0, 0xCC, 0x20, 0x5D, 0xA0, 0x80, 0xC7, 0xA9, 0x0A, 0x85, 0x01, +0x80, 0xC1, 0xA6, 0x01, 0x86, 0x00, 0xE0, 0x0A, 0xD0, 0x29, 0x08, 0x78, 0xA5, 0xB1, 0x8D, 0x23, +0xC0, 0xA5, 0xB0, 0x8D, 0x27, 0xC0, 0xC2, 0x30, 0xA5, 0xB2, 0x8F, 0x54, 0x00, 0xE1, 0xA5, 0xB4, +0x8F, 0x56, 0x00, 0xE1, 0xE2, 0x30, 0x28, 0x38, 0x22, 0x94, 0x00, 0xE1, 0x68, 0x30, 0x03, 0x8D, +0x06, 0xC0, 0x6B, 0x78, 0x20, 0x2E, 0x96, 0x20, 0x1A, 0x97, 0xA2, 0x00, 0xA0, 0x02, 0x20, 0x14, +0x96, 0x20, 0x0E, 0x97, 0xA2, 0x01, 0xA0, 0x04, 0x20, 0x12, 0x97, 0xA2, 0x01, 0xA0, 0x03, 0x20, +0x14, 0x96, 0x20, 0x08, 0xAC, 0x18, 0xA5, 0x00, 0x69, 0x1A, 0x20, 0x80, 0xC0, 0x20, 0x16, 0x97, +0x64, 0x01, 0xA0, 0x04, 0x20, 0xA8, 0x9A, 0xA0, 0x04, 0x20, 0x9F, 0x96, 0x20, 0xBB, 0x9A, 0x20, +0x5D, 0x96, 0xA2, 0x04, 0x20, 0x79, 0xA6, 0xA2, 0x03, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, +0x68, 0x85, 0x6A, 0x68, 0x85, 0x69, 0x68, 0x85, 0x68, 0x68, 0xC9, 0x64, 0x90, 0x02, 0xE9, 0x64, +0x85, 0x66, 0x68, 0x85, 0x65, 0x68, 0x85, 0x64, 0x68, 0x68, 0xAF, 0xF4, 0x02, 0xE1, 0x85, 0x67, +0xAF, 0xF5, 0x02, 0xE1, 0x85, 0x6B, 0x64, 0x02, 0x20, 0x51, 0x98, 0x64, 0x01, 0xA5, 0x01, 0x85, +0x02, 0x48, 0x20, 0x51, 0x98, 0x68, 0x85, 0x01, 0x20, 0x4F, 0x9A, 0xC9, 0x00, 0xF0, 0xEE, 0xC9, +0x9B, 0xD0, 0x08, 0x38, 0x22, 0x94, 0x00, 0xE1, 0x4C, 0x39, 0x93, 0xC9, 0x8D, 0xD0, 0x5A, 0xA5, +0x00, 0xC9, 0x06, 0xD0, 0x06, 0xA9, 0x00, 0x8F, 0x43, 0x01, 0xE1, 0xC9, 0x07, 0xD0, 0x06, 0xA9, +0x00, 0x8F, 0x44, 0x01, 0xE1, 0xC9, 0x03, 0xD0, 0x26, 0xA5, 0x64, 0x48, 0xA5, 0x65, 0x48, 0xA5, +0x66, 0xC9, 0x28, 0xB0, 0x03, 0x18, 0x69, 0x64, 0x48, 0xA5, 0x68, 0x48, 0xA5, 0x69, 0x48, 0xA5, +0x6A, 0x48, 0xC2, 0x30, 0xA2, 0x03, 0x0E, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x80, 0x0F, 0xC9, +0x08, 0xD0, 0x0B, 0xC2, 0x30, 0xA2, 0x0D, 0x0B, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x20, 0xE9, +0x97, 0xB0, 0x8A, 0x22, 0x80, 0x00, 0xE1, 0x80, 0x9A, 0x48, 0x24, 0x1F, 0x70, 0x2E, 0x20, 0x41, +0x9B, 0xFA, 0x20, 0xCB, 0x94, 0x20, 0xE9, 0x97, 0x4C, 0x3D, 0x94, 0xE0, 0x88, 0xF0, 0x15, 0x1A, +0xC5, 0x05, 0x90, 0x02, 0xA9, 0x00, 0x97, 0xAD, 0x18, 0xA5, 0x01, 0xAA, 0x65, 0xA3, 0x20, 0x79, +0x98, 0x4C, 0xAE, 0x98, 0xAA, 0xD0, 0x02, 0xA5, 0x05, 0x3A, 0x80, 0xEA, 0x20, 0x41, 0x9B, 0xA6, +0x00, 0xF0, 0x16, 0xE0, 0x01, 0xF0, 0x5E, 0xE0, 0x03, 0xF0, 0x08, 0xE0, 0x08, 0xF0, 0x07, 0x68, +0x4C, 0x39, 0x93, 0x4C, 0xB8, 0x95, 0x4C, 0x78, 0x95, 0xA5, 0x01, 0xC9, 0x06, 0xD0, 0x10, 0x68, +0xA2, 0x02, 0xBF, 0xA4, 0x89, 0xFF, 0x9F, 0xDA, 0x02, 0xE1, 0xCA, 0x10, 0xF5, 0x80, 0x1B, 0xC9, +0x02, 0xB0, 0x03, 0x4C, 0xBE, 0x94, 0x20, 0x41, 0x9B, 0xFA, 0xE0, 0x88, 0xF0, 0x1A, 0x1A, 0xC5, +0x05, 0x90, 0x02, 0xA9, 0x00, 0x20, 0xAB, 0x9B, 0xB0, 0xF4, 0xA5, 0x01, 0x48, 0xA0, 0x05, 0x84, +0x25, 0x64, 0x01, 0x20, 0xF8, 0x98, 0x80, 0x5E, 0xAA, 0xD0, 0x02, 0xA5, 0x05, 0x3A, 0x20, 0xAB, +0x9B, 0xB0, 0xF5, 0x80, 0xE5, 0xFA, 0x20, 0xCB, 0x94, 0xAD, 0x3C, 0xC0, 0x29, 0xF0, 0x0F, 0xDE, +0x02, 0xE1, 0x8D, 0x3C, 0xC0, 0x29, 0x0F, 0x8F, 0xCA, 0x00, 0xE1, 0x0A, 0x0A, 0x0A, 0x0A, 0x8F, +0xB0, 0x1D, 0xE1, 0x20, 0x5D, 0xA0, 0x80, 0x31, 0xFA, 0xE0, 0x88, 0xF0, 0x2F, 0x1A, 0xA6, 0x05, +0xF0, 0x06, 0xC5, 0x05, 0x90, 0x02, 0xA9, 0x00, 0x97, 0xAD, 0xC0, 0x01, 0xF0, 0x0B, 0xC8, 0xD7, +0xAD, 0x90, 0x0B, 0xF0, 0x09, 0x97, 0xAD, 0x80, 0x05, 0x88, 0xD7, 0xAD, 0x90, 0xF7, 0xA5, 0x01, +0x48, 0x64, 0x01, 0x20, 0x70, 0x99, 0x68, 0x85, 0x01, 0x4C, 0x3D, 0x94, 0xAA, 0xD0, 0x06, 0xA6, +0x05, 0xF0, 0x02, 0xA5, 0x05, 0x3A, 0x80, 0xD0, 0x20, 0xEE, 0x95, 0xB9, 0x64, 0x00, 0xFA, 0xE0, +0x88, 0xF0, 0x23, 0x1A, 0xC5, 0x05, 0x90, 0x02, 0xA9, 0x00, 0x99, 0x64, 0x00, 0xA5, 0x67, 0x8F, +0xF4, 0x02, 0xE1, 0xA5, 0x6B, 0x8F, 0xF5, 0x02, 0xE1, 0xA5, 0x01, 0x48, 0x64, 0x01, 0x20, 0xEE, +0x95, 0x20, 0xB5, 0x99, 0x80, 0xC0, 0xAA, 0xD0, 0x02, 0xA5, 0x05, 0x3A, 0x80, 0xDC, 0xC0, 0x03, +0xB0, 0x1F, 0xA6, 0x64, 0xA5, 0x66, 0x29, 0x03, 0xD0, 0x06, 0xE0, 0x01, 0xD0, 0x02, 0xA2, 0x0C, +0xBF, 0x7D, 0x89, 0xFF, 0xC0, 0x01, 0xD0, 0x02, 0x85, 0x05, 0x3A, 0xC5, 0x65, 0xB0, 0x02, 0x85, +0x65, 0x60, 0xA2, 0x00, 0x48, 0x8A, 0x18, 0x2C, 0x1F, 0xC0, 0x10, 0x02, 0x69, 0x14, 0xAA, 0x20, +0x68, 0xA9, 0x68, 0x60, 0xA9, 0x16, 0xA2, 0x17, 0x20, 0x14, 0x96, 0x4C, 0x80, 0xC0, 0xA2, 0x01, +0xA0, 0x01, 0xA9, 0x0E, 0x80, 0xF2, 0x18, 0xB7, 0xA4, 0x77, 0xAD, 0x80, 0xEE, 0xA0, 0x01, 0x5A, +0x20, 0x12, 0x96, 0xA9, 0x5A, 0x20, 0x59, 0xA9, 0x7A, 0x5A, 0xA2, 0x27, 0x20, 0x14, 0x96, 0xA9, +0x5F, 0x20, 0x59, 0xA9, 0x7A, 0xC8, 0xC0, 0x16, 0x90, 0xE5, 0xF0, 0xE3, 0x60, 0x20, 0x3D, 0x96, +0xA2, 0x02, 0xA0, 0x16, 0xA9, 0x0F, 0x20, 0x28, 0x96, 0xA5, 0x00, 0xC9, 0x0A, 0xF0, 0x0B, 0xA9, +0x11, 0x20, 0x80, 0xC0, 0xA5, 0x04, 0xC9, 0x01, 0xF0, 0x05, 0xA9, 0x10, 0x20, 0x80, 0xC0, 0xA5, +0x1F, 0x29, 0x30, 0x0A, 0x0A, 0x0A, 0x08, 0x30, 0x04, 0xA9, 0x12, 0x80, 0x07, 0xA9, 0x14, 0x20, +0x80, 0xC0, 0xA9, 0x13, 0x20, 0x80, 0xC0, 0x28, 0x90, 0x03, 0x20, 0xA9, 0x96, 0xA0, 0x17, 0xA2, +0x01, 0x20, 0x14, 0x96, 0xA9, 0x4C, 0x4C, 0x1E, 0x97, 0xA0, 0x05, 0x20, 0x24, 0x96, 0xA0, 0x06, +0xA9, 0x15, 0x20, 0x26, 0x96, 0xA0, 0x07, 0xA9, 0x15, 0x20, 0x26, 0x96, 0x08, 0x78, 0xC2, 0x30, +0xF4, 0x00, 0x00, 0xF4, 0x6F, 0x00, 0xA2, 0x03, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xA2, +0x19, 0xA0, 0x06, 0x20, 0x14, 0x96, 0xAF, 0xF5, 0x02, 0xE1, 0xF0, 0x03, 0x20, 0x08, 0xAC, 0xA2, +0x09, 0xBF, 0x6F, 0x00, 0x00, 0xDA, 0x20, 0x59, 0xA9, 0xFA, 0xE8, 0xE0, 0x14, 0x90, 0xF2, 0xA2, +0x1A, 0xA0, 0x07, 0x20, 0x14, 0x96, 0xA2, 0x00, 0xBF, 0x6F, 0x00, 0x00, 0xDA, 0x20, 0x59, 0xA9, +0xFA, 0xE8, 0xE0, 0x08, 0x90, 0xF2, 0x28, 0xA0, 0x08, 0xA9, 0x17, 0x4C, 0x26, 0x96, 0xA9, 0x5C, +0x80, 0x0F, 0xA9, 0x4C, 0x80, 0x12, 0xA9, 0x20, 0x80, 0x07, 0xA9, 0xA0, 0x80, 0x0A, 0x48, 0x80, +0x03, 0x48, 0xA9, 0x5A, 0x20, 0x59, 0xA9, 0x68, 0x48, 0xA5, 0x24, 0x2C, 0x1F, 0xC0, 0x10, 0x06, +0xAD, 0x7B, 0x05, 0x38, 0xE9, 0x14, 0xAA, 0x68, 0xE0, 0x27, 0xB0, 0x24, 0xDA, 0x48, 0x20, 0x59, +0xA9, 0x68, 0xFA, 0xE8, 0x80, 0xF2, 0x20, 0x43, 0x9B, 0xA8, 0xC2, 0x20, 0xE0, 0x02, 0x90, 0x23, +0xF0, 0x0F, 0xE0, 0x05, 0xF0, 0x0F, 0xE0, 0x06, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE2, 0x30, +0x60, 0xA5, 0x59, 0x80, 0x0A, 0xA5, 0x5D, 0x80, 0x06, 0xA5, 0x61, 0x80, 0x02, 0xA5, 0x55, 0x4A, +0x4A, 0x80, 0x2A, 0xC2, 0x20, 0xA9, 0x00, 0x80, 0x85, 0x1B, 0x64, 0x1D, 0xF4, 0x00, 0x00, 0xF4, +0x00, 0x00, 0x18, 0x88, 0xC0, 0xFF, 0xF0, 0x10, 0xA3, 0x01, 0x65, 0x1B, 0x83, 0x01, 0xA3, 0x03, +0x65, 0x1D, 0x83, 0x03, 0x63, 0x01, 0x80, 0xEB, 0xFA, 0x68, 0x4A, 0x4A, 0xFA, 0xE2, 0x30, 0xEB, +0xAA, 0xEB, 0x18, 0x85, 0x3E, 0x86, 0x3F, 0x66, 0x34, 0xA0, 0x05, 0xA2, 0x11, 0xA9, 0x00, 0x18, +0x2A, 0xC9, 0x0A, 0x90, 0x02, 0xE9, 0x0A, 0x26, 0x3E, 0x26, 0x3F, 0xCA, 0xD0, 0xF2, 0x09, 0xB0, +0x48, 0x88, 0xD0, 0xE7, 0xA0, 0x04, 0x68, 0xC9, 0xB0, 0xD0, 0x15, 0x24, 0x34, 0x30, 0x0A, 0xBB, +0xF0, 0x0A, 0x5A, 0x48, 0x20, 0x08, 0xAC, 0x68, 0x7A, 0x88, 0x10, 0xEA, 0x4C, 0x59, 0xA9, 0x68, +0x5A, 0x20, 0x59, 0xA9, 0x7A, 0x88, 0x10, 0xF7, 0x60, 0xA5, 0x00, 0xC9, 0x05, 0xD0, 0x31, 0xAF, +0xE1, 0x02, 0xE1, 0x0F, 0xE2, 0x02, 0xE1, 0x0F, 0xE7, 0x02, 0xE1, 0xD0, 0x12, 0xA9, 0x18, 0xA0, +0x0F, 0x20, 0x08, 0x98, 0xA9, 0x19, 0xA0, 0x10, 0xA2, 0x01, 0x20, 0x28, 0x96, 0x38, 0x60, 0xA0, +0x0F, 0x20, 0x16, 0x98, 0xA0, 0x10, 0xA2, 0x01, 0x20, 0x14, 0x96, 0xA9, 0xA0, 0x20, 0x1E, 0x97, +0x18, 0x60, 0xA9, 0x53, 0x4C, 0x59, 0xA9, 0xA2, 0x01, 0xA0, 0x00, 0x20, 0x14, 0x96, 0xA9, 0xDF, +0x20, 0x1E, 0x97, 0x20, 0x3D, 0x96, 0x4C, 0x9D, 0x96, 0x20, 0x16, 0x97, 0xA2, 0x01, 0xA0, 0x02, +0x20, 0x14, 0x96, 0xA9, 0x4C, 0x4C, 0x1E, 0x97, 0x4C, 0xF8, 0x98, 0x4C, 0xB5, 0x99, 0x4C, 0x70, +0x99, 0xA0, 0x05, 0x84, 0x25, 0xA6, 0x00, 0xF0, 0xEF, 0xE0, 0x03, 0xF0, 0xEE, 0xE0, 0x08, 0xF0, +0xED, 0x20, 0x38, 0x9B, 0xA2, 0x00, 0x20, 0x79, 0x98, 0x34, 0x83, 0x30, 0x03, 0x20, 0xAE, 0x98, +0xE6, 0x25, 0x1A, 0xE8, 0xE4, 0x04, 0x90, 0xEE, 0x60, 0x48, 0xDA, 0xB5, 0x83, 0x08, 0xA3, 0x02, +0xC5, 0x02, 0xD0, 0x03, 0x20, 0xD7, 0x9B, 0x18, 0xA9, 0x05, 0x63, 0x02, 0xA8, 0xA2, 0x04, 0xA3, +0x03, 0x20, 0x28, 0x96, 0x28, 0x08, 0x30, 0x12, 0xA9, 0xBA, 0x20, 0x59, 0xA9, 0x20, 0xC8, 0x9B, +0x20, 0x08, 0xAC, 0xA3, 0x02, 0x85, 0x01, 0x20, 0x02, 0x9B, 0x28, 0xFA, 0x68, 0x60, 0x48, 0xDA, +0xA6, 0x01, 0xB4, 0x93, 0xB7, 0xAD, 0xA6, 0x00, 0xE0, 0x04, 0xD0, 0x13, 0xBB, 0xF0, 0x0B, 0xC0, +0x02, 0xB0, 0x0C, 0xAA, 0xBF, 0x02, 0x03, 0xE1, 0x80, 0x05, 0xAA, 0xBF, 0xF9, 0x02, 0xE1, 0x18, +0x77, 0xA4, 0x20, 0x80, 0xC0, 0xA6, 0x01, 0xB4, 0x93, 0x20, 0x1A, 0x97, 0x20, 0xE2, 0x98, 0xFA, +0x68, 0x60, 0xB7, 0xAD, 0xD7, 0xAA, 0x08, 0xA9, 0xA0, 0xA2, 0x02, 0xA4, 0x25, 0x20, 0x14, 0x96, +0x28, 0xD0, 0x02, 0xA9, 0x44, 0x4C, 0x59, 0xA9, 0x20, 0x38, 0x9B, 0xA2, 0x00, 0x20, 0x79, 0x98, +0x48, 0xDA, 0xE0, 0x08, 0xD0, 0x14, 0xAF, 0xDD, 0x02, 0xE1, 0xD0, 0x04, 0xA9, 0x9B, 0x80, 0x02, +0xA9, 0x6D, 0x20, 0x80, 0xC0, 0x20, 0x22, 0x98, 0x80, 0x49, 0xFA, 0x68, 0x34, 0x83, 0x30, 0x45, +0x48, 0xDA, 0xB5, 0x83, 0xC9, 0x06, 0xD0, 0x30, 0xA2, 0x03, 0x20, 0x43, 0x9B, 0xD7, 0xAA, 0xD0, +0x18, 0xA2, 0x04, 0x20, 0x43, 0x9B, 0xD7, 0xAA, 0xD0, 0x0F, 0xA2, 0x05, 0x20, 0x43, 0x9B, 0xD7, +0xAA, 0xD0, 0x06, 0xA9, 0x6C, 0xE2, 0x02, 0x80, 0x02, 0xA9, 0x6B, 0x08, 0x20, 0x80, 0xC0, 0x20, +0x08, 0xAC, 0x28, 0x20, 0xE6, 0x98, 0x80, 0x0B, 0xC9, 0x02, 0x90, 0x04, 0xC9, 0x06, 0xB0, 0x03, +0x20, 0xAE, 0x98, 0xFA, 0x68, 0xE6, 0x25, 0x1A, 0xE8, 0xE4, 0x04, 0x90, 0x90, 0x4C, 0x6E, 0xB7, +0xA0, 0x05, 0x84, 0x25, 0x20, 0x38, 0x9B, 0xA2, 0x00, 0xDA, 0x48, 0x20, 0x79, 0x98, 0x20, 0x46, +0x97, 0xA3, 0x02, 0xC9, 0x03, 0xF0, 0x12, 0xC9, 0x04, 0xF0, 0x0E, 0xA9, 0xCB, 0x20, 0x59, 0xA9, +0xA3, 0x02, 0xC9, 0x02, 0xD0, 0x03, 0x20, 0x22, 0x98, 0xA3, 0x02, 0xAA, 0xA3, 0x01, 0xE0, 0x01, +0xF0, 0x04, 0xE0, 0x00, 0xD0, 0x04, 0x9B, 0x20, 0xE2, 0x98, 0xE6, 0x25, 0x68, 0x1A, 0xFA, 0xE8, +0xE4, 0x04, 0x90, 0xC5, 0x60, 0xAF, 0xF5, 0x02, 0xE1, 0xF0, 0x07, 0xA0, 0xA0, 0xBB, 0xA5, 0x68, +0x80, 0x17, 0xA2, 0xD0, 0xA5, 0x68, 0xC9, 0x0C, 0x90, 0x06, 0xF0, 0x0B, 0xE9, 0x0C, 0x80, 0x07, +0xAA, 0xD0, 0x02, 0xA9, 0x0C, 0xA2, 0xC1, 0xA0, 0xCD, 0x86, 0x6D, 0x84, 0x6E, 0x85, 0x6C, 0xA0, +0x05, 0x84, 0x25, 0xA6, 0x00, 0x20, 0x38, 0x9B, 0xA2, 0x00, 0x48, 0xDA, 0x20, 0x79, 0x98, 0x20, +0x43, 0x9B, 0xE0, 0x03, 0xF0, 0x31, 0xE0, 0x04, 0xF0, 0x37, 0xE0, 0x08, 0xF0, 0x1F, 0xA6, 0x01, +0xE0, 0x05, 0xD0, 0x02, 0xA0, 0x08, 0xB9, 0x64, 0x00, 0xC0, 0x00, 0xF0, 0x04, 0xC0, 0x01, 0xD0, +0x01, 0x1A, 0xA2, 0x00, 0x38, 0x20, 0xA3, 0x97, 0x20, 0x08, 0xAC, 0x80, 0x14, 0xA0, 0x01, 0x20, +0x36, 0x96, 0xA0, 0x01, 0x4C, 0xD9, 0x98, 0xA0, 0x00, 0x20, 0x36, 0x96, 0xA0, 0x00, 0x20, 0xE2, +0x98, 0xFA, 0xDA, 0xE0, 0x05, 0xD0, 0x0D, 0xA5, 0x6D, 0x20, 0x59, 0xA9, 0xA5, 0x6E, 0x20, 0x59, +0xA9, 0x20, 0x08, 0xAC, 0xFA, 0x68, 0x1A, 0xE8, 0xE6, 0x25, 0xE4, 0x04, 0x90, 0x9C, 0x60, 0x58, +0x20, 0x84, 0x9A, 0xC9, 0x8B, 0xF0, 0x05, 0xC9, 0x8A, 0xF0, 0x13, 0x60, 0xA5, 0x01, 0xD0, 0x04, +0xA5, 0x04, 0x85, 0x01, 0xC6, 0x01, 0xA6, 0x01, 0xB5, 0x83, 0x30, 0xF0, 0x80, 0x13, 0xA5, 0x01, +0x1A, 0xC5, 0x04, 0x90, 0x04, 0xA9, 0xFF, 0x85, 0x01, 0xE6, 0x01, 0xA6, 0x01, 0xB5, 0x83, 0x30, +0xED, 0xA9, 0x00, 0x60, 0x20, 0x74, 0xCF, 0x10, 0xFB, 0xC9, 0x8B, 0xF0, 0x19, 0xC9, 0x8A, 0xF0, +0x15, 0xC9, 0x88, 0xF0, 0x12, 0xC9, 0x95, 0xF0, 0x0E, 0xC9, 0x9B, 0xF0, 0x09, 0xC9, 0x8D, 0xF0, +0x05, 0x20, 0x5D, 0xA0, 0x80, 0xDE, 0x18, 0x60, 0xA5, 0x22, 0x48, 0x64, 0x24, 0x84, 0x25, 0x84, +0x22, 0x20, 0x6C, 0xA9, 0x20, 0x76, 0xA9, 0x68, 0x85, 0x22, 0x60, 0xA6, 0x00, 0xBF, 0xFE, 0x88, +0xFF, 0x85, 0x1F, 0x29, 0x0F, 0x85, 0x04, 0x8A, 0x0A, 0xAA, 0xBF, 0xE9, 0x88, 0xFF, 0xEB, 0xBF, +0xE8, 0x88, 0xFF, 0xA2, 0x00, 0x20, 0xF6, 0x9A, 0xE0, 0x08, 0x90, 0xF9, 0xEB, 0x20, 0xF6, 0x9A, +0xE0, 0x10, 0x90, 0xF9, 0xA2, 0x00, 0x9B, 0xB5, 0x83, 0xC9, 0x80, 0x94, 0x93, 0xE8, 0xB0, 0x01, +0xC8, 0xE0, 0x10, 0x90, 0xF2, 0x60, 0x4A, 0x48, 0xA0, 0x80, 0xB0, 0x01, 0x9B, 0x94, 0x83, 0x68, +0xE8, 0x60, 0x8B, 0x4B, 0xAB, 0xA6, 0x00, 0xBD, 0xC5, 0x88, 0x85, 0xA4, 0xBD, 0xD6, 0x88, 0x85, +0xAA, 0xBD, 0xDF, 0x88, 0x85, 0xAD, 0xBD, 0xCD, 0x88, 0x85, 0xA7, 0xA9, 0xE1, 0x85, 0xAF, 0x4B, +0x68, 0x85, 0xA6, 0x85, 0xAC, 0x85, 0xA9, 0xA9, 0x89, 0x85, 0xA5, 0x85, 0xAB, 0x85, 0xA8, 0xA9, +0x02, 0x85, 0xAE, 0x8A, 0x0A, 0xAA, 0xAB, 0x60, 0xA6, 0x00, 0xBF, 0x09, 0x89, 0xFF, 0x85, 0xA3, +0x60, 0xA6, 0x01, 0x86, 0x01, 0x20, 0x02, 0x9B, 0xA6, 0x01, 0xB4, 0x93, 0xB7, 0xA7, 0x10, 0x56, +0x48, 0xA5, 0x00, 0xC9, 0x03, 0xF0, 0x37, 0xC9, 0x04, 0xF0, 0x3D, 0x5A, 0xA0, 0xFF, 0xC2, 0x20, +0xF4, 0x00, 0x00, 0xF4, 0x00, 0x80, 0xA5, 0x58, 0x85, 0x1B, 0xA5, 0x5A, 0x85, 0x1D, 0xC9, 0x80, +0x00, 0xB0, 0x11, 0xC8, 0x38, 0xC8, 0xA5, 0x1B, 0xE3, 0x01, 0x85, 0x1B, 0xA5, 0x1D, 0xE3, 0x03, +0x85, 0x1D, 0xB0, 0xF0, 0x84, 0x05, 0x68, 0x68, 0xE2, 0x30, 0x7A, 0x68, 0x80, 0x1A, 0x68, 0x8B, +0x4B, 0xAB, 0xB9, 0x75, 0x89, 0xAB, 0x80, 0x0E, 0x68, 0x0A, 0x30, 0x06, 0xAF, 0xF8, 0x02, 0xE1, +0x80, 0x04, 0xAF, 0x01, 0x03, 0xE1, 0x85, 0x05, 0xB7, 0xAD, 0x60, 0x48, 0x97, 0xAD, 0xA6, 0x01, +0xE0, 0x03, 0xF0, 0x07, 0xE0, 0x04, 0xF0, 0x03, 0x68, 0x18, 0x60, 0xAF, 0xDA, 0x02, 0xE1, 0xCF, +0xDB, 0x02, 0xE1, 0xD0, 0xF3, 0x68, 0x38, 0x60, 0x48, 0xDA, 0x5A, 0x20, 0x84, 0xFE, 0xA9, 0x1B, +0x20, 0x59, 0xA9, 0x7A, 0xFA, 0x68, 0x60, 0x48, 0xDA, 0x5A, 0xA9, 0x7F, 0x85, 0x32, 0xA9, 0x18, +0x80, 0xEE, 0x20, 0x17, 0x9C, 0xD4, 0x28, 0xD4, 0x24, 0xA6, 0x00, 0xBF, 0xFE, 0x88, 0xFF, 0x0A, +0x0A, 0x10, 0x12, 0x9C, 0x7B, 0x04, 0xA5, 0x32, 0x48, 0x20, 0xC8, 0x9B, 0x20, 0xBC, 0x96, 0x68, +0x30, 0x03, 0x20, 0xD7, 0x9B, 0xC2, 0x30, 0x68, 0x85, 0x24, 0x68, 0x85, 0x28, 0xE2, 0x30, 0x20, +0x1A, 0x9C, 0x9C, 0x32, 0xC0, 0x18, 0x6B, 0xE2, 0x40, 0x50, 0xB8, 0xA2, 0x00, 0xA0, 0x78, 0xA9, +0x04, 0x84, 0x09, 0x85, 0x0A, 0xA0, 0x00, 0x50, 0x06, 0xB1, 0x09, 0x95, 0x0B, 0x80, 0x04, 0xB5, +0x0B, 0x91, 0x09, 0xE8, 0xA0, 0x80, 0x50, 0x06, 0xB1, 0x09, 0x95, 0x0B, 0x80, 0x04, 0xB5, 0x0B, +0x91, 0x09, 0xE8, 0xA5, 0x0A, 0x1A, 0xC9, 0x08, 0x90, 0xD9, 0xA0, 0x7B, 0xC4, 0x09, 0xD0, 0xCF, +0x60, 0xD8, 0x7C, 0x55, 0x9C, 0xA2, 0x9D, 0xBE, 0x9D, 0xE2, 0x9C, 0x5F, 0x9C, 0xC9, 0x9C, 0xBB, +0xB0, 0x1F, 0xA0, 0xC4, 0xC4, 0x39, 0xD0, 0x04, 0xA4, 0x38, 0xF0, 0x15, 0x48, 0xDA, 0x29, 0x7F, +0xC9, 0x02, 0xB0, 0x09, 0x08, 0x78, 0x20, 0x59, 0xC4, 0x20, 0x91, 0xC4, 0x28, 0xFA, 0x68, 0x80, +0x47, 0xEB, 0xA3, 0x07, 0xA8, 0xEB, 0x91, 0x28, 0xA0, 0x05, 0x84, 0x38, 0x08, 0x78, 0x22, 0xE2, +0x9C, 0xFF, 0xAD, 0x7C, 0x04, 0xAE, 0x7C, 0x05, 0xA0, 0x05, 0x20, 0x37, 0x9F, 0xAD, 0xFC, 0x04, +0xAE, 0xFC, 0x05, 0xA0, 0x0C, 0x20, 0x37, 0x9F, 0xAD, 0x00, 0xC0, 0x0A, 0x08, 0xAD, 0x7C, 0x07, +0x2A, 0x2A, 0x2A, 0x29, 0x03, 0x49, 0x03, 0x1A, 0x28, 0xA2, 0x00, 0xA0, 0x10, 0x20, 0x48, 0x9F, +0xA9, 0x8D, 0x8D, 0x11, 0x02, 0xA2, 0x11, 0x28, 0x6B, 0xA2, 0x04, 0xBF, 0xB7, 0x02, 0xE1, 0x48, +0xCA, 0xD0, 0xF8, 0x68, 0x9D, 0x7C, 0x04, 0x68, 0x9D, 0x7C, 0x05, 0x8A, 0x30, 0xEA, 0xA2, 0x80, +0x80, 0xF1, 0x08, 0x78, 0x20, 0xD2, 0xC4, 0x90, 0x10, 0xAD, 0x7C, 0x07, 0x49, 0x90, 0xAA, 0x29, +0x80, 0xA8, 0x8A, 0x29, 0x10, 0x0A, 0x0A, 0x0A, 0xAA, 0xA9, 0x20, 0x1C, 0x7C, 0x07, 0x98, 0x29, +0x3F, 0x48, 0x8A, 0x29, 0x3F, 0x03, 0x01, 0xF0, 0x05, 0xA9, 0x20, 0x0C, 0x7C, 0x07, 0x68, 0xAD, +0x7C, 0x07, 0x48, 0x29, 0x2E, 0x8D, 0x7C, 0x07, 0x68, 0x29, 0x90, 0x0A, 0x90, 0x09, 0xF0, 0x0D, +0xA9, 0x41, 0x0C, 0x7C, 0x07, 0x80, 0x0A, 0xF0, 0x08, 0xA9, 0x01, 0x80, 0xF5, 0xA9, 0x40, 0x80, +0xF1, 0x98, 0x2A, 0x8A, 0xB0, 0x09, 0x30, 0x0D, 0xA9, 0x90, 0x0C, 0x7C, 0x07, 0x80, 0x0A, 0x30, +0x08, 0xA9, 0x10, 0x80, 0xF5, 0xA9, 0x80, 0x80, 0xF1, 0x8A, 0x29, 0x7F, 0xAA, 0x0A, 0x10, 0x07, +0x8A, 0x09, 0x80, 0xA2, 0xFF, 0x80, 0x03, 0x8A, 0xA2, 0x00, 0xDA, 0x48, 0x98, 0x29, 0x7F, 0xA8, +0x0A, 0x10, 0x07, 0x98, 0x09, 0x80, 0xA0, 0xFF, 0x80, 0x03, 0x98, 0xA0, 0x00, 0x5A, 0x48, 0xAD, +0xFC, 0x05, 0x8D, 0xFC, 0x06, 0x68, 0x18, 0x6D, 0xFC, 0x04, 0x8D, 0xFC, 0x04, 0x68, 0x6D, 0xFC, +0x05, 0x8D, 0xFC, 0x05, 0x20, 0x8B, 0x9E, 0xAD, 0x7C, 0x05, 0x8D, 0xFC, 0x06, 0x68, 0x18, 0x6D, +0x7C, 0x04, 0x8D, 0x7C, 0x04, 0x68, 0x6D, 0x7C, 0x05, 0x8D, 0x7C, 0x05, 0x20, 0x76, 0x9E, 0x28, +0x18, 0x6B, 0xC2, 0x30, 0xA9, 0x00, 0x00, 0x8F, 0xB8, 0x02, 0xE1, 0x8F, 0xBA, 0x02, 0xE1, 0xA9, +0xFF, 0x03, 0x8F, 0xBC, 0x02, 0xE1, 0x8F, 0xBE, 0x02, 0xE1, 0xE2, 0x30, 0x80, 0x22, 0x29, 0x01, +0xAA, 0xF0, 0x01, 0xE8, 0xAD, 0x78, 0x04, 0x9F, 0xB8, 0x02, 0xE1, 0xAD, 0x78, 0x05, 0x9F, 0xB9, +0x02, 0xE1, 0xAD, 0xF8, 0x04, 0x9F, 0xBC, 0x02, 0xE1, 0xAD, 0xF8, 0x05, 0x9F, 0xBD, 0x02, 0xE1, +0xA2, 0x00, 0xA9, 0xC0, 0x1C, 0xFC, 0x07, 0x1C, 0x7C, 0x06, 0x20, 0x4C, 0x9E, 0x0C, 0xFC, 0x07, +0x20, 0x69, 0x9E, 0xB0, 0x07, 0x2C, 0xFC, 0x07, 0x22, 0x0C, 0x9E, 0xFF, 0xA2, 0x02, 0x20, 0x4C, +0x9E, 0x0C, 0x7C, 0x06, 0x20, 0x69, 0x9E, 0xB0, 0x42, 0x2C, 0x7C, 0x06, 0x70, 0x3D, 0x10, 0x02, +0xE2, 0x40, 0xC2, 0x30, 0xBF, 0xB8, 0x02, 0xE1, 0x70, 0x21, 0x89, 0x00, 0xFF, 0xD0, 0x1C, 0x89, +0x80, 0x00, 0xF0, 0x17, 0x09, 0x00, 0xFF, 0x9F, 0xB8, 0x02, 0xE1, 0xE2, 0x30, 0xA9, 0x40, 0xE0, +0x02, 0xD0, 0x04, 0x0C, 0x7C, 0x06, 0x6B, 0x0C, 0xFC, 0x07, 0x6B, 0xA8, 0xBF, 0xBC, 0x02, 0xE1, +0x9F, 0xB8, 0x02, 0xE1, 0x98, 0x9F, 0xBC, 0x02, 0xE1, 0xE2, 0x30, 0x6B, 0xBF, 0xBD, 0x02, 0xE1, +0x08, 0xBF, 0xB9, 0x02, 0xE1, 0x30, 0x09, 0x28, 0x30, 0x03, 0xA9, 0x00, 0x60, 0xA9, 0xC0, 0x60, +0x28, 0x30, 0x03, 0xA9, 0x40, 0x60, 0xA9, 0x80, 0x60, 0xC2, 0x30, 0xBF, 0xBC, 0x02, 0xE1, 0xDF, +0xB8, 0x02, 0xE1, 0xE2, 0x30, 0x60, 0xA0, 0x00, 0xBB, 0xEB, 0xB9, 0x7C, 0x04, 0xEB, 0xA8, 0x50, +0x05, 0x2C, 0xFC, 0x07, 0x80, 0x14, 0x2C, 0xFC, 0x07, 0x80, 0x1D, 0xA0, 0x80, 0xA2, 0x02, 0xEB, +0xB9, 0x7C, 0x04, 0xEB, 0xA8, 0x50, 0x0E, 0x2C, 0x7C, 0x06, 0x30, 0x07, 0x50, 0x23, 0x98, 0x30, +0x20, 0x10, 0x37, 0x50, 0x35, 0x2C, 0x7C, 0x06, 0x08, 0x98, 0x30, 0x29, 0x28, 0x30, 0x10, 0x50, +0x47, 0xC2, 0x30, 0xEB, 0xDF, 0xBC, 0x02, 0xE1, 0xE2, 0x30, 0xF0, 0x02, 0xB0, 0x03, 0x60, 0x70, +0x37, 0x9B, 0xF0, 0x02, 0xA0, 0x80, 0xBF, 0xBC, 0x02, 0xE1, 0x99, 0x7C, 0x04, 0xBF, 0xBD, 0x02, +0xE1, 0x99, 0x7C, 0x05, 0x60, 0x28, 0x30, 0x20, 0x70, 0x12, 0x9B, 0xF0, 0x02, 0xA0, 0x80, 0xBF, +0xB8, 0x02, 0xE1, 0x99, 0x7C, 0x04, 0xBF, 0xB9, 0x02, 0xE1, 0x80, 0xE5, 0xEB, 0xC2, 0x30, 0xDF, +0xB8, 0x02, 0xE1, 0xE2, 0x30, 0x90, 0xE3, 0x60, 0x98, 0x30, 0x17, 0xAD, 0xFC, 0x06, 0x10, 0x17, +0x38, 0x9B, 0xF0, 0x02, 0xA0, 0x80, 0xF9, 0x7C, 0x05, 0x70, 0x0C, 0x2C, 0xFC, 0x06, 0x10, 0xCA, +0x30, 0xAF, 0xAD, 0xFC, 0x06, 0x10, 0xE9, 0x9B, 0xF0, 0x02, 0xA0, 0x80, 0xB9, 0x7C, 0x05, 0xC2, +0x30, 0xEB, 0xDF, 0xBC, 0x02, 0xE1, 0xE2, 0x30, 0xF0, 0x02, 0xB0, 0x95, 0xC2, 0x30, 0xDF, 0xB8, +0x02, 0xE1, 0xE2, 0x30, 0x90, 0xA4, 0x60, 0xE0, 0x80, 0x90, 0x0D, 0x49, 0xFF, 0x69, 0x00, 0x48, +0x8A, 0x49, 0xFF, 0x69, 0x00, 0xAA, 0x68, 0x38, 0x8D, 0x21, 0x02, 0x8E, 0x20, 0x02, 0xA9, 0xAB, +0x90, 0x02, 0xA9, 0xAD, 0x48, 0xA9, 0xAC, 0x99, 0x01, 0x02, 0x20, 0x62, 0x9F, 0x68, 0x99, 0x00, +0x02, 0x60, 0xA2, 0x11, 0xA9, 0x00, 0x18, 0x2A, 0xC9, 0x0A, 0x90, 0x02, 0xE9, 0x0A, 0x2E, 0x21, +0x02, 0x2E, 0x20, 0x02, 0xCA, 0xD0, 0xF0, 0x09, 0xB0, 0x99, 0x00, 0x02, 0x88, 0xF0, 0x08, 0xC0, +0x07, 0xF0, 0x04, 0xC0, 0x0E, 0xD0, 0xDB, 0x60, 0xAD, 0x15, 0xC0, 0x48, 0x8D, 0x07, 0xC0, 0xF4, +0xF2, 0x9F, 0x98, 0x30, 0x30, 0x08, 0xC9, 0x05, 0xB0, 0x04, 0x0A, 0x28, 0x80, 0x17, 0x28, 0xAD, +0xFB, 0x04, 0x29, 0xD6, 0x08, 0x98, 0x0A, 0x28, 0xD0, 0x0B, 0x18, 0x69, 0x1E, 0x48, 0x20, 0x73, +0xC9, 0x20, 0x97, 0xCD, 0x68, 0x9B, 0xAA, 0xBF, 0xD6, 0x9F, 0xFF, 0x48, 0xBF, 0xD5, 0x9F, 0xFF, +0x48, 0xBB, 0xA3, 0x0A, 0x60, 0x08, 0x0A, 0x28, 0x9B, 0xAA, 0xBF, 0x12, 0xA0, 0xFF, 0x48, 0xBF, +0x11, 0xA0, 0xFF, 0x80, 0xEB, 0x4F, 0xC8, 0xF3, 0xB2, 0xED, 0xB2, 0x26, 0xB3, 0x20, 0xB3, 0x54, +0xB2, 0x6F, 0xB2, 0x0E, 0xB3, 0xAA, 0xB2, 0x4B, 0xB3, 0x5A, 0xB2, 0xE0, 0xB2, 0x9D, 0xB2, 0x08, +0xB3, 0xCC, 0xB2, 0x83, 0x06, 0x68, 0x30, 0x03, 0x8D, 0x06, 0xC0, 0x6B, 0x00, 0xB3, 0xB2, 0x83, +0xCB, 0x3F, 0xCC, 0xAE, 0xB2, 0x4B, 0xB3, 0x1A, 0xCC, 0x70, 0xB3, 0x3B, 0xB3, 0x08, 0xB3, 0xC1, +0xB2, 0x51, 0xAA, 0xA9, 0xB4, 0x9C, 0xB3, 0xF5, 0xB3, 0x01, 0xB0, 0x0F, 0xB2, 0xC1, 0xA2, 0xCD, +0xA2, 0xA7, 0xA6, 0xD5, 0xA2, 0x27, 0xAB, 0x7F, 0xB4, 0x7C, 0xB3, 0x35, 0xB0, 0xCC, 0xA6, 0xBC, +0xA6, 0xD8, 0xA7, 0x7D, 0xA1, 0x9E, 0xA9, 0xFD, 0xA3, 0xCD, 0xB1, 0x89, 0xA1, 0xEA, 0xA0, 0x0C, +0xAC, 0x31, 0xA5, 0xA2, 0xAC, 0x12, 0xAC, 0x9A, 0xC9, 0xA3, 0xC9, 0x3D, 0xA2, 0x5C, 0xA0, 0xCF, +0xAA, 0x63, 0xA0, 0x0C, 0xA6, 0x7F, 0xA9, 0x94, 0xB6, 0x93, 0xBB, 0x9F, 0xA4, 0x22, 0x6C, 0x00, +0xE1, 0xB0, 0x01, 0x60, 0x08, 0x78, 0xA9, 0xB0, 0x20, 0xA8, 0xFC, 0xAD, 0x36, 0xC0, 0x48, 0x29, +0x7F, 0x8D, 0x36, 0xC0, 0xDA, 0x8B, 0x20, 0x82, 0xF8, 0xAD, 0xDF, 0x02, 0x49, 0x0F, 0x8D, 0x6D, +0x01, 0x9C, 0x6E, 0x01, 0xC2, 0x20, 0xA9, 0x88, 0x88, 0x8D, 0x69, 0x01, 0xA9, 0x00, 0x20, 0x8D, +0x6B, 0x01, 0xE2, 0x30, 0xAD, 0xCA, 0x00, 0x8D, 0x6F, 0x01, 0x48, 0x18, 0xC2, 0x30, 0xAC, 0x6D, +0x01, 0xA2, 0x50, 0x02, 0x88, 0xD0, 0x0B, 0xAC, 0x6D, 0x01, 0x2E, 0x69, 0x01, 0x90, 0x03, 0xAD, +0x30, 0xC0, 0xCA, 0xD0, 0x18, 0xA2, 0x50, 0x02, 0xE2, 0x20, 0xAD, 0x6F, 0x01, 0xF0, 0x19, 0x3A, +0x8D, 0x6F, 0x01, 0x8D, 0xCA, 0x00, 0x8D, 0x3C, 0xC0, 0xC2, 0x20, 0x80, 0x06, 0xA9, 0x05, 0x00, +0x3A, 0xD0, 0xFD, 0xCE, 0x6B, 0x01, 0xD0, 0xCC, 0xE2, 0x30, 0x68, 0x8D, 0xCA, 0x00, 0x8D, 0x3C, +0xC0, 0xAB, 0xFA, 0xA0, 0x00, 0x68, 0x8D, 0x36, 0xC0, 0x28, 0x60, 0x20, 0x32, 0xA1, 0x60, 0xA9, +0xFF, 0x8F, 0x34, 0x01, 0xE1, 0x8B, 0xA9, 0xE1, 0x48, 0xAB, 0x9C, 0x36, 0x01, 0x9C, 0xD7, 0x00, +0x9C, 0xCB, 0x00, 0x9C, 0x01, 0x01, 0xC2, 0x20, 0x9C, 0x03, 0x01, 0x9C, 0x43, 0x01, 0x9C, 0xC3, +0x00, 0x9C, 0xC5, 0x00, 0xA9, 0x01, 0x00, 0x8D, 0x74, 0x01, 0xA9, 0x5A, 0xA5, 0x8D, 0x76, 0x01, +0xA9, 0xA9, 0xFF, 0x8D, 0x7A, 0x01, 0xA9, 0x5C, 0x8C, 0x8D, 0x78, 0x01, 0xE2, 0x30, 0x9C, 0x7C, +0x01, 0xAB, 0x8B, 0x8B, 0x20, 0x82, 0xF8, 0xAD, 0x68, 0xC0, 0x29, 0xFE, 0x8D, 0x2D, 0x01, 0xA3, +0x0B, 0x29, 0x80, 0x0D, 0x35, 0xC0, 0x8D, 0x2E, 0x01, 0x68, 0x8D, 0x2B, 0x01, 0x8D, 0x2C, 0x01, +0x8D, 0x3E, 0x01, 0xC2, 0x30, 0x7B, 0x8D, 0x28, 0x01, 0x3B, 0x18, 0x69, 0x0B, 0x00, 0x8D, 0x26, +0x01, 0xA9, 0x01, 0x01, 0x8D, 0x2F, 0x01, 0x8D, 0x31, 0x01, 0xE2, 0x30, 0xA0, 0x05, 0xA9, 0x00, +0x99, 0x20, 0x01, 0x88, 0x10, 0xFA, 0x8D, 0x2A, 0x01, 0x8C, 0x33, 0x01, 0xAB, 0x60, 0xA9, 0x00, +0xA2, 0x02, 0x9F, 0x30, 0x01, 0xE1, 0xCA, 0x10, 0xF9, 0x60, 0xAD, 0x36, 0xC0, 0x48, 0x29, 0x7F, +0x08, 0x78, 0x8D, 0x36, 0xC0, 0xAD, 0x70, 0xC0, 0xA0, 0x00, 0xEA, 0xEA, 0xBD, 0x64, 0xC0, 0x10, +0x04, 0xC8, 0xD0, 0xF8, 0x88, 0x28, 0x68, 0x8D, 0x36, 0xC0, 0x60, 0xE2, 0x30, 0xEB, 0xA9, 0x80, +0x0C, 0x36, 0xC0, 0xEB, 0x8D, 0x07, 0xC0, 0x60, 0x8B, 0x20, 0x82, 0xF8, 0xA2, 0x27, 0xBF, 0xD2, +0xBB, 0xFF, 0x9D, 0x80, 0x00, 0xBF, 0xC2, 0xBB, 0xFF, 0x9D, 0x10, 0x00, 0xCA, 0x10, 0xEF, 0xA2, +0x17, 0x9E, 0xA8, 0x00, 0xCA, 0x10, 0xFA, 0xA9, 0xFF, 0x8D, 0xC2, 0x00, 0xA9, 0x4C, 0x8F, 0xD0, +0x03, 0x00, 0x8F, 0xF5, 0x03, 0x00, 0x8F, 0xF8, 0x03, 0x00, 0xC2, 0x30, 0xA9, 0x65, 0xFF, 0x8F, +0xFE, 0x03, 0x00, 0x8F, 0xD1, 0x03, 0x00, 0x8F, 0xF9, 0x03, 0x00, 0xA9, 0x03, 0xE0, 0x8F, 0xF6, +0x03, 0x00, 0xA9, 0xBB, 0x86, 0x8D, 0xC0, 0x00, 0xA2, 0x5C, 0x00, 0xA0, 0xB5, 0xFF, 0xA9, 0x5C, +0xDE, 0x9D, 0x20, 0x00, 0x98, 0x9D, 0x22, 0x00, 0xCA, 0xCA, 0xCA, 0xCA, 0x10, 0xED, 0xA9, 0x86, +0xB6, 0x8D, 0x51, 0x00, 0xA9, 0x5C, 0x84, 0x8D, 0x7C, 0x00, 0xA9, 0xA6, 0xFF, 0x8D, 0x7E, 0x00, +0xE2, 0x30, 0xA9, 0xFF, 0x8D, 0x53, 0x00, 0x9C, 0xD6, 0x00, 0xAB, 0x4C, 0x15, 0xB7, 0xC2, 0x10, +0xA2, 0xFF, 0x07, 0xA9, 0xB2, 0x9F, 0x00, 0x08, 0xE0, 0xCA, 0x10, 0xF9, 0xE2, 0x30, 0xAD, 0x68, +0xC0, 0x48, 0x8D, 0x06, 0xC0, 0xA9, 0xC1, 0x85, 0x01, 0x64, 0x00, 0xA2, 0x03, 0xBF, 0x67, 0xFB, +0xFF, 0xA8, 0xBF, 0x6B, 0xFB, 0xFF, 0xD1, 0x00, 0xD0, 0x0B, 0xCA, 0x10, 0xF0, 0xA5, 0x01, 0x29, +0x07, 0xAA, 0x9E, 0xF8, 0x07, 0xE6, 0x01, 0xA5, 0x01, 0xC9, 0xC8, 0x90, 0xDE, 0x68, 0x8D, 0x68, +0xC0, 0x22, 0x00, 0x00, 0xFE, 0x90, 0x08, 0xA9, 0x00, 0x8F, 0xFF, 0x15, 0xE1, 0x80, 0xF2, 0xA9, +0x00, 0x8F, 0xFE, 0x0F, 0xE1, 0x8F, 0xFF, 0x0F, 0xE1, 0x22, 0xF2, 0xB4, 0xFF, 0x20, 0x40, 0x65, +0x4C, 0x00, 0x1C, 0x08, 0xE2, 0x30, 0xAF, 0x7D, 0x01, 0xE1, 0x10, 0x09, 0x29, 0xBF, 0x8F, 0x7D, +0x01, 0xE1, 0x20, 0x9F, 0xA9, 0x28, 0x6B, 0x29, 0x0F, 0x09, 0xB0, 0xC9, 0xBA, 0x90, 0x02, 0x69, +0x06, 0x60, 0x22, 0x74, 0x00, 0xE1, 0xA9, 0x06, 0x90, 0x03, 0x20, 0x80, 0xC0, 0x60, 0x22, 0x78, +0x00, 0xE1, 0xA9, 0x05, 0x80, 0xF2, 0xA4, 0x34, 0xB9, 0x00, 0x02, 0xC9, 0xA0, 0xD0, 0x03, 0xC8, +0xD0, 0xF6, 0xC8, 0x84, 0x34, 0xA2, 0x10, 0xDF, 0xEA, 0xC0, 0xFF, 0xF0, 0x69, 0xCA, 0x10, 0xF7, +0x88, 0xB9, 0x00, 0x02, 0xC9, 0xA0, 0xD0, 0x03, 0xC8, 0x80, 0xF6, 0xE2, 0x40, 0xC9, 0xAB, 0xF0, +0x04, 0xC9, 0xAD, 0xD0, 0x01, 0xB8, 0x20, 0x77, 0xA6, 0xE2, 0x30, 0xA9, 0x02, 0x48, 0x5A, 0xA2, +0x00, 0xE8, 0xC8, 0xB9, 0x00, 0x02, 0xC9, 0x8D, 0xF0, 0x06, 0x49, 0xB0, 0xC9, 0x0A, 0x90, 0xF1, +0xC2, 0x30, 0xDA, 0x50, 0x05, 0xF4, 0x00, 0x00, 0x80, 0x03, 0xF4, 0x01, 0x00, 0xA2, 0x0B, 0x29, +0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xA9, 0x09, 0x20, 0x80, 0xC0, 0xA3, 0x03, 0xAA, 0xA3, 0x04, +0x20, 0x2B, 0xA9, 0xFA, 0x68, 0x20, 0x2B, 0xA9, 0x68, 0x68, 0x20, 0xCC, 0xAB, 0xA2, 0x0A, 0x68, +0xCA, 0xD0, 0xFC, 0x4C, 0x63, 0xA9, 0xE0, 0x05, 0x90, 0x2A, 0xE0, 0x0F, 0xB0, 0x06, 0x8A, 0x69, +0x05, 0xAA, 0x80, 0x25, 0xD0, 0x03, 0x4C, 0x31, 0xA8, 0xA9, 0x08, 0x20, 0x80, 0xC0, 0xB8, 0x20, +0xB0, 0xA3, 0x20, 0x08, 0xAC, 0xA9, 0xFB, 0x20, 0x59, 0xA9, 0xE2, 0x40, 0x20, 0xB0, 0xA3, 0x20, +0x7F, 0xAD, 0x80, 0xC6, 0x8A, 0x0A, 0xAA, 0xC2, 0x20, 0xA5, 0x3E, 0xE0, 0x0F, 0x90, 0x06, 0xE0, +0x13, 0xF0, 0x02, 0x29, 0x01, 0x9F, 0x20, 0x01, 0xE1, 0xE2, 0x30, 0xA3, 0x07, 0x29, 0x7F, 0x48, +0xAF, 0x2E, 0x01, 0xE1, 0x29, 0x80, 0x8F, 0x37, 0x01, 0xE1, 0x03, 0x01, 0xFA, 0x83, 0x07, 0x60, +0x08, 0xC2, 0x30, 0xAF, 0x40, 0x01, 0xE1, 0x48, 0xA5, 0x3E, 0x48, 0xF4, 0x00, 0x00, 0xF4, 0x00, +0x02, 0xF4, 0x10, 0x00, 0xA9, 0x01, 0x00, 0x70, 0x01, 0x3A, 0x48, 0xA2, 0x0B, 0x27, 0x22, 0x00, +0x00, 0xE1, 0x28, 0xA2, 0xFF, 0xE8, 0xE0, 0x10, 0xB0, 0x23, 0xBD, 0x00, 0x02, 0xC9, 0x20, 0xF0, +0xF4, 0x50, 0x0E, 0xC9, 0x2D, 0xF0, 0x0A, 0xA9, 0xAB, 0xDA, 0x20, 0x59, 0xA9, 0xFA, 0xBD, 0x00, +0x02, 0x09, 0x80, 0xDA, 0x20, 0x59, 0xA9, 0xFA, 0xE8, 0xE0, 0x10, 0x90, 0xF1, 0x60, 0xAD, 0xFB, +0x04, 0x10, 0x2F, 0xC9, 0xFF, 0xF0, 0x2B, 0x2C, 0x1F, 0xC0, 0x10, 0x23, 0xC2, 0x30, 0xA2, 0x05, +0x09, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xA9, 0x8D, 0x20, 0x71, 0xA9, 0x20, 0x17, 0x9C, 0xC2, +0x30, 0xA2, 0x05, 0x0A, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x20, 0x1A, 0x9C, 0x80, 0x03, 0x20, +0xEB, 0xCC, 0xC2, 0x30, 0xAF, 0x16, 0x01, 0xE1, 0x48, 0x3A, 0x3A, 0x85, 0x3A, 0xE2, 0x30, 0x8B, +0x20, 0x82, 0xF8, 0xA2, 0x0B, 0xBD, 0x08, 0x01, 0x9D, 0x20, 0x01, 0xCA, 0x10, 0xF7, 0x8E, 0x39, +0x01, 0xAD, 0x18, 0x01, 0x8D, 0x2D, 0x01, 0x29, 0x04, 0x4A, 0x4A, 0x8D, 0x2F, 0x01, 0xAD, 0x1A, +0x01, 0x29, 0x80, 0x48, 0xAD, 0x19, 0x01, 0x03, 0x01, 0x8D, 0x2E, 0x01, 0x68, 0xAD, 0x15, 0x01, +0x8D, 0x2C, 0x01, 0x8D, 0x3E, 0x01, 0xAD, 0x2A, 0x01, 0x29, 0x30, 0x4A, 0x20, 0x7B, 0xF8, 0x8D, +0x30, 0x01, 0xA9, 0x00, 0x2A, 0x8D, 0x31, 0x01, 0xAD, 0x14, 0x01, 0x29, 0x01, 0x8D, 0x32, 0x01, +0xAB, 0x20, 0xA3, 0xAC, 0xA9, 0x00, 0x8F, 0x39, 0x01, 0xE1, 0x68, 0x85, 0x3A, 0x68, 0x85, 0x3B, +0x20, 0x57, 0xA9, 0xA2, 0x00, 0xDA, 0x20, 0x08, 0xAC, 0xBF, 0xEA, 0xC0, 0xFF, 0x20, 0x59, 0xA9, +0xA9, 0xBD, 0x20, 0x59, 0xA9, 0xFA, 0xDA, 0xE0, 0x0A, 0xB0, 0x22, 0xE0, 0x05, 0xB0, 0x10, 0x8A, +0x0A, 0xAA, 0xBF, 0x21, 0x01, 0xE1, 0x20, 0x2F, 0xA9, 0xBF, 0x20, 0x01, 0xE1, 0x80, 0x04, 0xBF, +0x25, 0x01, 0xE1, 0x20, 0x2F, 0xA9, 0xFA, 0xE8, 0xE0, 0x0E, 0x90, 0xC9, 0x60, 0xBF, 0x25, 0x01, +0xE1, 0x20, 0x25, 0xA9, 0x80, 0xF0, 0x78, 0xA9, 0x00, 0x00, 0x5B, 0x48, 0xAB, 0xAB, 0xA3, 0x04, +0x85, 0xFB, 0xA3, 0x06, 0x85, 0xFD, 0xA3, 0x08, 0xA2, 0x7F, 0x01, 0x9A, 0x48, 0xE2, 0x30, 0x08, +0xA9, 0x80, 0x8F, 0x37, 0x01, 0xE1, 0x8D, 0x07, 0xC0, 0xA9, 0x08, 0x0C, 0x68, 0xC0, 0x20, 0x4E, +0xFE, 0x20, 0xEB, 0xCC, 0x20, 0x76, 0xA9, 0x28, 0xB0, 0x19, 0xA7, 0xFB, 0x1A, 0x85, 0xFF, 0xA0, +0x01, 0xB7, 0xFB, 0x09, 0x80, 0x5A, 0x20, 0x59, 0xA9, 0x7A, 0xC8, 0xC4, 0xFF, 0x90, 0xF2, 0x58, +0xB0, 0x1F, 0x18, 0x08, 0x20, 0x7B, 0xA9, 0x20, 0x76, 0xA9, 0xA2, 0x00, 0xA0, 0x05, 0x20, 0x68, +0xA9, 0x28, 0x08, 0xB0, 0x04, 0xA9, 0x03, 0x80, 0x02, 0xA9, 0x0C, 0x20, 0x80, 0xC0, 0x28, 0x90, +0x05, 0xFA, 0x7A, 0x20, 0x2A, 0xA9, 0x8D, 0x0F, 0xC0, 0x20, 0x5D, 0xA0, 0xA9, 0x0B, 0x85, 0x22, +0xA0, 0x00, 0xF0, 0x05, 0xA9, 0xDF, 0x99, 0xA8, 0x05, 0xA9, 0x41, 0x99, 0xA9, 0x05, 0x20, 0x89, +0xA5, 0xC8, 0xC0, 0x26, 0x90, 0xEC, 0x88, 0xA9, 0x4C, 0x99, 0xA9, 0x05, 0xA9, 0x40, 0x99, 0xA8, +0x05, 0x20, 0x89, 0xA5, 0x88, 0xD0, 0xF0, 0x80, 0xD9, 0xAD, 0x00, 0xC0, 0x8D, 0x10, 0xC0, 0xC9, +0x8E, 0xD0, 0x0D, 0xAD, 0x62, 0xC0, 0x10, 0x08, 0xAD, 0x61, 0xC0, 0x10, 0x03, 0x20, 0xAB, 0xA5, +0xAD, 0x19, 0xC0, 0x10, 0xFB, 0xAD, 0x19, 0xC0, 0x30, 0xFB, 0x60, 0x5A, 0xA9, 0x0C, 0x85, 0x25, +0x64, 0x24, 0x20, 0x6C, 0xA9, 0xA9, 0xFE, 0x22, 0x98, 0x00, 0xE1, 0xA9, 0x80, 0x1C, 0x36, 0xC0, +0xA2, 0x10, 0xA9, 0xFF, 0x20, 0xA8, 0xFC, 0xCA, 0xD0, 0xF8, 0xA9, 0x80, 0x0C, 0x36, 0xC0, 0x20, +0x76, 0xA9, 0x7A, 0x60, 0x18, 0xC2, 0x30, 0xAF, 0x40, 0x01, 0xE1, 0x90, 0x03, 0x49, 0xFF, 0xFF, +0x48, 0xA5, 0x3E, 0x90, 0x03, 0x49, 0xFF, 0xFF, 0x65, 0x3C, 0x85, 0x3E, 0xAF, 0x46, 0x01, 0xE1, +0x63, 0x01, 0x83, 0x01, 0xE2, 0x30, 0x20, 0x08, 0xA6, 0xFA, 0x68, 0x20, 0x2B, 0xA9, 0xA5, 0x3F, +0xA6, 0x3E, 0x20, 0x2B, 0xA9, 0x4C, 0xCC, 0xAB, 0xA9, 0x0A, 0x4C, 0x80, 0xC0, 0xC9, 0xAD, 0xF0, +0xC4, 0xC9, 0xAB, 0xF0, 0xBF, 0xC9, 0xAA, 0xF0, 0x01, 0x18, 0x08, 0xA2, 0x04, 0x20, 0x79, 0xA6, +0xAF, 0x46, 0x01, 0xE1, 0x48, 0xA5, 0x3C, 0x48, 0xAF, 0x40, 0x01, 0xE1, 0x48, 0xA5, 0x3E, 0x48, +0xA2, 0x0B, 0x0C, 0xB0, 0x03, 0xA2, 0x0B, 0x0D, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xA2, 0x00, +0x68, 0x95, 0x3C, 0xE8, 0xE0, 0x08, 0xD0, 0xF8, 0x28, 0x08, 0xB0, 0x05, 0xA9, 0xD2, 0x20, 0x59, +0xA9, 0x20, 0x08, 0xA6, 0xA2, 0x07, 0xB5, 0x3C, 0xDA, 0x20, 0x2F, 0xA9, 0xE0, 0x04, 0xD0, 0x10, +0xA3, 0x02, 0x6A, 0xB0, 0x0B, 0x20, 0x50, 0xA9, 0xA9, 0xD1, 0x20, 0x59, 0xA9, 0x20, 0x08, 0xA6, +0xFA, 0xCA, 0x10, 0xE2, 0x28, 0x80, 0x8E, 0xA2, 0x03, 0xC2, 0x30, 0x68, 0xF4, 0x00, 0x00, 0xCA, +0xD0, 0xFA, 0x48, 0x60, 0xA2, 0x06, 0x00, 0xBF, 0x00, 0x00, 0xF8, 0xDF, 0xA0, 0xA6, 0xFF, 0xD0, +0x0D, 0xCA, 0xCA, 0x10, 0xF2, 0x22, 0x20, 0x00, 0xF8, 0xAF, 0x08, 0x00, 0xF8, 0x6B, 0x38, 0x6B, +0xD2, 0xCF, 0xCD, 0xD4, 0xCF, 0xCF, 0xCC, 0xD3, 0x20, 0xBF, 0xA7, 0xAD, 0x32, 0x01, 0x6A, 0xAD, +0x0E, 0x01, 0x1A, 0x1A, 0x1A, 0xB0, 0x01, 0x1A, 0x8D, 0x0E, 0x01, 0x80, 0x5F, 0x18, 0xAF, 0x3E, +0x01, 0xE1, 0xF0, 0x13, 0xAF, 0x32, 0x01, 0xE1, 0xF0, 0x0D, 0x4C, 0x5D, 0xA0, 0x38, 0xAF, 0x3E, +0x01, 0xE1, 0xF0, 0x03, 0x4C, 0x5D, 0xA0, 0x8B, 0xAD, 0x68, 0xC0, 0x48, 0x20, 0xBF, 0xA7, 0xAE, +0x35, 0xC0, 0xDA, 0xBA, 0x8E, 0x3C, 0x01, 0x08, 0xC9, 0x00, 0x02, 0xB0, 0x0A, 0xCD, 0x3C, 0x01, +0x70, 0x05, 0x90, 0x03, 0xAD, 0x3C, 0x01, 0x28, 0x48, 0xA3, 0x06, 0xAA, 0x68, 0xE2, 0x30, 0x50, +0x03, 0x8D, 0x09, 0xC0, 0x1B, 0xB0, 0x06, 0x4B, 0xF4, 0x9D, 0xA7, 0x90, 0x0E, 0x4B, 0xF4, 0x9E, +0xA7, 0xA2, 0x5C, 0xDA, 0xF4, 0x18, 0xFB, 0xC2, 0x20, 0x3B, 0x48, 0x3B, 0xE2, 0x30, 0x50, 0x03, +0x8D, 0x09, 0xC0, 0x1B, 0xA2, 0x0B, 0xBD, 0x20, 0x01, 0x9D, 0x08, 0x01, 0xCA, 0x10, 0xF7, 0xAD, +0x2D, 0x01, 0x29, 0xFB, 0x48, 0xAD, 0x2F, 0x01, 0x0A, 0x0A, 0x03, 0x01, 0x8D, 0x18, 0x01, 0x68, +0xAD, 0x36, 0xC0, 0x29, 0x7F, 0x48, 0xAD, 0x2E, 0x01, 0x48, 0x29, 0x80, 0x03, 0x02, 0x8D, 0x1A, +0x01, 0x68, 0x29, 0x7F, 0x8D, 0x19, 0x01, 0x68, 0xAD, 0x32, 0x01, 0x8D, 0x14, 0x01, 0xAD, 0x30, +0x01, 0x0A, 0x0D, 0x31, 0x01, 0x0A, 0x0A, 0x0A, 0x0A, 0x48, 0xAD, 0x12, 0x01, 0x29, 0xCF, 0x03, +0x01, 0xFA, 0xAA, 0xAC, 0x32, 0x01, 0xD0, 0x04, 0xAD, 0x3E, 0x01, 0x48, 0xC2, 0x20, 0xAD, 0x3A, +0x01, 0x48, 0xDA, 0x3B, 0x8D, 0x0E, 0x01, 0xDA, 0xE2, 0x30, 0xAD, 0x3C, 0x01, 0x8F, 0x00, 0x01, +0x01, 0xAF, 0xF8, 0x07, 0x00, 0x8D, 0x1B, 0x01, 0xEE, 0xCB, 0x00, 0x4C, 0x3E, 0xBA, 0xD8, 0x18, +0xFB, 0xE2, 0x30, 0x8D, 0x08, 0xC0, 0xC2, 0x30, 0x20, 0x82, 0xF8, 0xAD, 0x3C, 0x01, 0x1B, 0x68, +0x8D, 0x35, 0xC0, 0xE2, 0x30, 0xF4, 0x00, 0x00, 0x2B, 0x68, 0x20, 0x72, 0xB4, 0xAB, 0x60, 0x78, +0x20, 0x62, 0xFE, 0x20, 0x82, 0xF8, 0xE2, 0x40, 0xAD, 0x2D, 0x01, 0x30, 0x01, 0xB8, 0xC2, 0x30, +0xA5, 0x3A, 0x8D, 0x3A, 0x01, 0xAD, 0x26, 0x01, 0x60, 0xC2, 0x30, 0xAD, 0x01, 0x02, 0x8F, 0x3C, +0x01, 0xE1, 0xE2, 0x30, 0xA8, 0xC8, 0xC8, 0xA2, 0x00, 0xBD, 0x03, 0x02, 0x48, 0xE8, 0x88, 0xD0, +0xF8, 0xC2, 0x30, 0xFA, 0x22, 0x00, 0x00, 0xE1, 0x48, 0x48, 0xE2, 0x30, 0x20, 0x57, 0xA9, 0xA9, +0x0B, 0x20, 0x80, 0xC0, 0xFA, 0x7A, 0x20, 0x2A, 0xA9, 0x20, 0x57, 0xA9, 0xC2, 0x30, 0x68, 0xF0, +0x0B, 0xC9, 0x10, 0x00, 0xB0, 0x06, 0xAF, 0x3C, 0x01, 0xE1, 0x80, 0x04, 0xAF, 0x3D, 0x01, 0xE1, +0xE2, 0x30, 0xA8, 0xF0, 0xB3, 0x88, 0x68, 0x5A, 0x20, 0x2F, 0xA9, 0x20, 0x08, 0xAC, 0x7A, 0x80, +0xF2, 0x20, 0xA4, 0xA8, 0xA4, 0x34, 0xB9, 0x00, 0x02, 0xC9, 0xBD, 0xD0, 0x9B, 0xE6, 0x34, 0x9C, +0x00, 0x02, 0xA4, 0x34, 0x20, 0xA9, 0xB1, 0x84, 0x34, 0xC9, 0xC6, 0xF0, 0x29, 0x20, 0xD3, 0xA8, +0xF0, 0xF0, 0x48, 0xAD, 0x00, 0x02, 0xC9, 0x02, 0xB0, 0x03, 0xFA, 0xCA, 0xDA, 0xC9, 0x02, 0xD0, +0x0C, 0x68, 0xC9, 0x28, 0xB0, 0x03, 0x18, 0x69, 0x64, 0x48, 0xAD, 0x00, 0x02, 0xC9, 0x06, 0xB0, +0x22, 0xEE, 0x00, 0x02, 0x80, 0xCC, 0x20, 0xD3, 0xA8, 0xF0, 0x04, 0x48, 0xEE, 0x00, 0x02, 0xAE, +0x00, 0x02, 0xE0, 0x06, 0xB0, 0x0D, 0x8A, 0xF0, 0x04, 0x68, 0xCA, 0x80, 0xF9, 0x20, 0x5D, 0xA0, +0x4C, 0x4D, 0xA3, 0xC2, 0x30, 0xA2, 0x03, 0x0E, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x20, 0xA4, +0xA8, 0x4C, 0x4D, 0xA3, 0x20, 0x57, 0xA9, 0xA9, 0x04, 0x20, 0x80, 0xC0, 0x08, 0x78, 0xF4, 0xE1, +0x00, 0xF4, 0x08, 0x01, 0xC2, 0x30, 0xA2, 0x03, 0x0F, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0xA2, +0x00, 0xBF, 0x08, 0x01, 0xE1, 0xDA, 0x20, 0x59, 0xA9, 0xFA, 0xE8, 0xE0, 0x14, 0x90, 0xF2, 0x28, +0x4C, 0x57, 0xA9, 0xAF, 0x42, 0x01, 0xE1, 0x08, 0xA5, 0x3E, 0x48, 0x29, 0x0F, 0x85, 0x3E, 0x68, +0x20, 0x7B, 0xF8, 0xAA, 0x20, 0xEB, 0xA8, 0xA5, 0x3E, 0x28, 0x60, 0xA9, 0x0A, 0x85, 0x3C, 0xA5, +0x3C, 0x18, 0xCA, 0x30, 0x06, 0x65, 0x3E, 0x85, 0x3E, 0x80, 0xF4, 0x60, 0xF4, 0x61, 0xF9, 0x80, +0x31, 0xF4, 0x19, 0xFC, 0x80, 0x2C, 0x20, 0x12, 0xA9, 0xA6, 0x3C, 0xA4, 0x3D, 0xF4, 0x98, 0xFD, +0x80, 0x20, 0x20, 0x57, 0xA9, 0xAF, 0x3E, 0x01, 0xE1, 0x20, 0x2F, 0xA9, 0xA9, 0xAF, 0x80, 0x39, +0xF4, 0x66, 0xFD, 0x80, 0x0D, 0xF4, 0xE2, 0xFD, 0x80, 0x08, 0x98, 0x20, 0x2F, 0xA9, 0x8A, 0xF4, +0xD9, 0xFD, 0xEB, 0x8A, 0xC2, 0x30, 0xFA, 0x4B, 0xF4, 0xAA, 0xA1, 0xF4, 0xD3, 0xF8, 0xDA, 0xE2, +0x30, 0xAA, 0xEB, 0xEB, 0x20, 0xD6, 0xFF, 0xEB, 0x8B, 0xF4, 0xB4, 0xF8, 0x8D, 0x06, 0xC0, 0x6B, +0xA2, 0x03, 0xF4, 0x49, 0xF9, 0x80, 0xDB, 0xA9, 0x8D, 0xF4, 0xEC, 0xFD, 0x80, 0xD4, 0xF4, 0xEF, +0xFD, 0x80, 0xCF, 0xF4, 0x6B, 0xFF, 0x80, 0xDB, 0x86, 0x24, 0x84, 0x25, 0xF4, 0x21, 0xFC, 0x80, +0xC1, 0xF4, 0xFF, 0xC2, 0x80, 0xBC, 0xF4, 0x57, 0xFC, 0x80, 0xB7, 0xF4, 0x42, 0xFE, 0x80, 0xB2, +0xA9, 0x98, 0x20, 0x71, 0xA9, 0xA9, 0x00, 0x8F, 0x36, 0x01, 0xE1, 0x60, 0xA9, 0x01, 0x8F, 0x74, +0x01, 0xE1, 0xC2, 0x30, 0xA2, 0x00, 0x08, 0x9B, 0xA9, 0xFF, 0x03, 0x54, 0xE0, 0x00, 0x6B, 0xAF, +0x7D, 0x01, 0xE1, 0x0A, 0x30, 0x15, 0xC2, 0x30, 0xF4, 0xFF, 0x00, 0xF4, 0xC2, 0xA9, 0xA2, 0x05, +0x0F, 0x22, 0x00, 0x00, 0xE1, 0x22, 0x00, 0x18, 0xFF, 0xE2, 0x30, 0xA9, 0xC0, 0x8F, 0x7D, 0x01, +0xE1, 0x60, 0xC6, 0xA9, 0xFF, 0x00, 0x0D, 0xD6, 0xE9, 0xF3, 0xE9, 0xF4, 0xA0, 0xCD, 0xEF, 0xEE, +0xE9, 0xF4, 0xEF, 0xF2, 0xDC, 0xA9, 0xFF, 0x00, 0x48, 0xAA, 0xFF, 0x00, 0xE2, 0x30, 0x78, 0xF4, +0x00, 0x00, 0xAB, 0xAB, 0xA2, 0x02, 0xBD, 0xF8, 0x03, 0x48, 0xCA, 0x10, 0xF9, 0xA9, 0x4C, 0x8D, +0xF8, 0x03, 0xA9, 0xFB, 0x8D, 0xF9, 0x03, 0x9C, 0xFA, 0x03, 0xA2, 0x08, 0xB5, 0xF7, 0x48, 0xCA, +0x10, 0xFA, 0x8B, 0x4B, 0xAB, 0xA2, 0x08, 0xBD, 0x49, 0xAA, 0x95, 0xF7, 0xCA, 0x10, 0xF8, 0xAB, +0x4B, 0x68, 0x85, 0xFF, 0xAD, 0x68, 0xC0, 0x48, 0x20, 0x76, 0xA9, 0xA9, 0xFD, 0x20, 0x80, 0xC0, +0x68, 0x8D, 0x68, 0xC0, 0x38, 0xFB, 0x5C, 0xF7, 0x00, 0x00, 0x68, 0x68, 0xF4, 0x00, 0x00, 0xAB, +0xAB, 0x18, 0xFB, 0x58, 0xA2, 0x00, 0x68, 0x95, 0xF7, 0xE8, 0xE0, 0x09, 0x90, 0xF8, 0x68, 0x9D, +0xEF, 0x03, 0xE0, 0x0B, 0x90, 0xF3, 0xC2, 0x30, 0x6B, 0x58, 0x4C, 0x69, 0xFF, 0x78, 0x5C, 0x2A, +0xAA, 0x00, 0x20, 0x06, 0xA9, 0xA5, 0x3D, 0x85, 0x43, 0xA5, 0x3C, 0x85, 0x42, 0x20, 0x26, 0xB4, +0x20, 0x2F, 0xA9, 0x20, 0xBA, 0xFC, 0xB0, 0x0C, 0x20, 0x75, 0xFE, 0x25, 0x3C, 0xF0, 0x05, 0x20, +0x08, 0xAC, 0x80, 0xE9, 0xA5, 0x43, 0x85, 0x3D, 0xA5, 0x42, 0x85, 0x3C, 0xA9, 0xAD, 0x20, 0x59, +0xA9, 0x20, 0x28, 0xB4, 0x09, 0x80, 0xC9, 0xA0, 0x90, 0x04, 0xC9, 0xFF, 0xD0, 0x02, 0xA9, 0xAE, +0xA8, 0xA5, 0x24, 0xF0, 0x0F, 0xC9, 0x27, 0x08, 0x98, 0x20, 0x59, 0xA9, 0x28, 0x90, 0x09, 0x20, +0x01, 0xA9, 0x80, 0x04, 0x98, 0x20, 0x59, 0xA9, 0xAD, 0x00, 0xC0, 0x29, 0x7F, 0xC9, 0x18, 0xD0, +0x04, 0x2C, 0x10, 0xC0, 0x60, 0x20, 0xBA, 0xFC, 0xB0, 0x15, 0x20, 0x75, 0xFE, 0x25, 0x3C, 0xD0, +0xC0, 0x80, 0x8F, 0xC2, 0x20, 0x18, 0x98, 0x65, 0x3A, 0x85, 0x40, 0xE2, 0x20, 0xA2, 0x40, 0x60, +0x48, 0x29, 0x03, 0xA8, 0x68, 0x4A, 0x4A, 0xAA, 0xBF, 0xE8, 0xAA, 0xFF, 0x88, 0x30, 0x04, 0x4A, +0x4A, 0x80, 0xF9, 0x29, 0x03, 0x85, 0x2F, 0x60, 0x04, 0x14, 0x04, 0x28, 0x05, 0x14, 0x08, 0x28, +0x06, 0x15, 0x04, 0x2A, 0x05, 0x15, 0x08, 0x2A, 0x04, 0x14, 0x04, 0x2A, 0x05, 0x54, 0x08, 0x28, +0x04, 0x14, 0x04, 0x2A, 0x05, 0x14, 0x08, 0x28, 0x04, 0x15, 0x00, 0x2A, 0x05, 0x15, 0x08, 0x08, +0x15, 0x15, 0x04, 0x2A, 0x05, 0x15, 0x08, 0x2A, 0x05, 0x15, 0x04, 0x2A, 0x05, 0x14, 0x08, 0x28, +0x05, 0x15, 0x04, 0x2A, 0x05, 0x14, 0x08, 0x28, 0x20, 0x62, 0xFE, 0xAF, 0x30, 0x01, 0xE1, 0xA2, +0xED, 0x20, 0x84, 0xAD, 0xAF, 0x31, 0x01, 0xE1, 0xA2, 0xF8, 0x20, 0x84, 0xAD, 0xAF, 0x2F, 0x01, +0xE1, 0xA2, 0xCC, 0x20, 0x84, 0xAD, 0xA9, 0x07, 0x20, 0x80, 0xC0, 0x20, 0xCC, 0xAB, 0x38, 0xA5, +0x23, 0xE5, 0x22, 0x38, 0xE9, 0x04, 0x30, 0x74, 0xF0, 0x72, 0x48, 0xA0, 0x00, 0x20, 0x64, 0xB3, +0xC9, 0x22, 0xF0, 0x2F, 0xC9, 0x20, 0xD0, 0x58, 0x20, 0x63, 0xB3, 0x0F, 0x3E, 0x01, 0xE1, 0xD0, +0x4F, 0x20, 0x63, 0xB3, 0xC9, 0xBF, 0xD0, 0x48, 0xA3, 0x01, 0xC9, 0x03, 0x90, 0x53, 0x20, 0xA3, +0xAC, 0x20, 0xF2, 0xAB, 0x68, 0x3A, 0x48, 0x20, 0xD4, 0xAB, 0xA0, 0x01, 0x20, 0xD6, 0xAB, 0x68, +0x3A, 0x80, 0x34, 0x20, 0x63, 0xB3, 0xC9, 0xA8, 0xD0, 0x26, 0x20, 0x63, 0xB3, 0xC9, 0x00, 0xD0, +0x1F, 0x20, 0x63, 0xB3, 0xC9, 0xE1, 0xD0, 0x18, 0xA3, 0x01, 0xC9, 0x03, 0x90, 0x23, 0x20, 0xA3, +0xAC, 0x20, 0xF2, 0xAB, 0x68, 0x3A, 0x48, 0xA0, 0x01, 0x20, 0xD6, 0xAB, 0xA0, 0x03, 0x80, 0xCC, +0x20, 0xA3, 0xAC, 0x20, 0xF2, 0xAB, 0x68, 0x3A, 0xF0, 0x02, 0x10, 0x8E, 0x20, 0x57, 0xA9, 0x80, +0x37, 0x68, 0x80, 0xF8, 0xA0, 0x00, 0x5A, 0x20, 0xFE, 0xAB, 0x7A, 0x84, 0x2F, 0x20, 0x84, 0xAC, +0xA2, 0x05, 0x20, 0x52, 0xA9, 0xA4, 0x2F, 0x20, 0x64, 0xB3, 0x5A, 0x20, 0x2F, 0xA9, 0x7A, 0x88, +0x10, 0xF5, 0x20, 0x53, 0xF9, 0x85, 0x3A, 0x84, 0x3B, 0x85, 0x40, 0x84, 0x41, 0x60, 0x20, 0x12, +0xA9, 0xA6, 0x3A, 0xA4, 0x3B, 0x20, 0x0D, 0xA9, 0xA9, 0xA0, 0x4C, 0x59, 0xA9, 0x20, 0xFE, 0xAB, +0x20, 0x64, 0xB3, 0x4A, 0x85, 0x3F, 0xA8, 0x08, 0x08, 0x90, 0x04, 0x29, 0x0F, 0x09, 0x80, 0x4A, +0xAA, 0xBF, 0x9B, 0xAD, 0xFF, 0x20, 0x79, 0xF8, 0x28, 0x90, 0x02, 0x69, 0x07, 0x85, 0x2E, 0xAA, +0xE0, 0x08, 0xD0, 0x16, 0xA5, 0x3F, 0x29, 0x04, 0xF0, 0x06, 0xAF, 0x30, 0x01, 0xE1, 0x80, 0x04, +0xAF, 0x31, 0x01, 0xE1, 0xD0, 0x04, 0xA9, 0x02, 0x80, 0x08, 0xBF, 0xFA, 0xAD, 0xFF, 0x85, 0x3F, +0x29, 0x03, 0x85, 0x2F, 0x98, 0x28, 0x90, 0x18, 0x29, 0x07, 0xC9, 0x05, 0xD0, 0x03, 0x88, 0x80, +0x20, 0x98, 0xC9, 0x44, 0xF0, 0x06, 0x29, 0x70, 0x09, 0x09, 0x80, 0x17, 0xA9, 0x12, 0x80, 0x13, +0x29, 0x03, 0xC9, 0x03, 0xD0, 0x0C, 0x98, 0xC9, 0x4F, 0xF0, 0x06, 0x29, 0x70, 0x09, 0x07, 0x80, +0x02, 0x88, 0x98, 0x60, 0xA0, 0x00, 0x20, 0x64, 0xB3, 0xE6, 0x40, 0xD0, 0x02, 0xE6, 0x41, 0x20, +0x2F, 0xA9, 0xA2, 0x01, 0x20, 0x52, 0xA9, 0xC4, 0x2F, 0xC8, 0x90, 0xEA, 0xA2, 0x03, 0xC0, 0x04, +0x90, 0xF2, 0x60, 0x20, 0x0D, 0xAC, 0x48, 0x20, 0x84, 0xAC, 0x7A, 0xDA, 0xBB, 0xBF, 0x29, 0xAE, +0xFF, 0x85, 0x2C, 0xBF, 0xA9, 0xAE, 0xFF, 0x85, 0x2D, 0x20, 0x08, 0xAC, 0xFA, 0xA9, 0x00, 0xA0, +0x05, 0x06, 0x2D, 0x26, 0x2C, 0x2A, 0x88, 0xD0, 0xF8, 0x69, 0xBF, 0x20, 0x59, 0xA9, 0xCA, 0xD0, +0xEC, 0x20, 0x08, 0xAC, 0xA5, 0x2E, 0xAA, 0xBF, 0xFA, 0xAD, 0xFF, 0x0A, 0x08, 0xBF, 0xE3, 0xAD, +0xFF, 0x85, 0x2E, 0xA2, 0x08, 0xA4, 0x2F, 0xE0, 0x05, 0xF0, 0x27, 0x06, 0x2E, 0x90, 0x18, 0xBF, +0x10, 0xAE, 0xFF, 0x28, 0x08, 0x10, 0x04, 0xBF, 0x20, 0xAE, 0xFF, 0x20, 0x59, 0xA9, 0xBF, 0x18, +0xAE, 0xFF, 0xF0, 0x03, 0x20, 0x59, 0xA9, 0xCA, 0xD0, 0xDD, 0x28, 0x60, 0x88, 0x30, 0xDC, 0x20, +0x2F, 0xA9, 0xA5, 0x2E, 0xC9, 0xF8, 0x20, 0x64, 0xB3, 0x85, 0x3F, 0x90, 0xEF, 0xFA, 0x88, 0x5A, +0xF0, 0x16, 0x48, 0x20, 0x64, 0xB3, 0x85, 0x3E, 0x65, 0x3A, 0xAA, 0x68, 0x65, 0x3B, 0xA8, 0x8A, +0x18, 0x69, 0x02, 0xAA, 0x90, 0x0B, 0x80, 0x08, 0x38, 0x20, 0x56, 0xF9, 0xAA, 0xE8, 0xD0, 0x01, +0xC8, 0x20, 0x2A, 0xA9, 0x20, 0x08, 0xAC, 0xA9, 0xFB, 0x20, 0x59, 0xA9, 0xA5, 0x3F, 0x10, 0x1D, +0xA9, 0xAD, 0x20, 0x59, 0xA9, 0x18, 0x68, 0x48, 0xF0, 0x0A, 0xA5, 0x3E, 0x49, 0xFF, 0x69, 0x01, +0x85, 0x3E, 0x80, 0x01, 0x38, 0xA5, 0x3F, 0x49, 0xFF, 0x69, 0x00, 0x80, 0x07, 0xA9, 0xAB, 0x20, +0x59, 0xA9, 0xA5, 0x3F, 0x20, 0x2F, 0xA9, 0x68, 0xF0, 0x05, 0xA5, 0x3E, 0x20, 0x2F, 0xA9, 0xA9, +0xFD, 0x4C, 0x59, 0xA9, 0xDA, 0x20, 0x25, 0xA9, 0xA9, 0xBD, 0x20, 0x59, 0xA9, 0x68, 0x48, 0x20, +0x59, 0xA9, 0x68, 0xC9, 0xCC, 0xD0, 0x01, 0x60, 0x4C, 0x50, 0xA9, 0xBB, 0xBB, 0xCC, 0x99, 0x52, +0xDB, 0xCC, 0xE9, 0xA9, 0xBB, 0xCC, 0x99, 0x52, 0xDD, 0xCC, 0xEE, 0xBC, 0xB9, 0xCC, 0x99, 0x52, +0xD9, 0xCC, 0xEA, 0x3C, 0xBB, 0xCC, 0x94, 0x52, 0xDD, 0xCC, 0xE6, 0x32, 0xBB, 0xCC, 0x99, 0x52, +0x1D, 0xCC, 0xE9, 0x88, 0xBB, 0xCC, 0x99, 0x52, 0x1D, 0xCC, 0xFE, 0x08, 0xBB, 0xCC, 0x99, 0x52, +0xDB, 0xCC, 0xE4, 0x08, 0xBB, 0xCC, 0x99, 0x52, 0xD9, 0xCC, 0xE6, 0xB9, 0xE3, 0x40, 0x21, 0xC8, +0xD5, 0x47, 0xA6, 0x80, 0x10, 0x1F, 0x1F, 0x42, 0x42, 0x4A, 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, +0x08, 0x08, 0x10, 0x43, 0x4A, 0x08, 0x04, 0x47, 0x43, 0x42, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, +0x02, 0x02, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x41, +0x41, 0xAC, 0xA9, 0xAC, 0xAC, 0xAC, 0xA4, 0xA8, 0xA3, 0xD9, 0x00, 0xD3, 0xD8, 0xD9, 0x00, 0x00, +0x00, 0xAC, 0xDD, 0xAC, 0xAC, 0xAC, 0xA4, 0xDB, 0xA3, 0x1C, 0x24, 0xAD, 0x8A, 0x8A, 0x15, 0xAD, +0x15, 0x1C, 0x84, 0xAC, 0xA9, 0x23, 0x53, 0xAC, 0x00, 0x5D, 0x5D, 0x1A, 0x8B, 0x8B, 0x9C, 0x1A, +0x9C, 0x1B, 0x13, 0x1A, 0xAD, 0xA1, 0x29, 0x1A, 0x00, 0x9D, 0xC1, 0x75, 0x8A, 0x8A, 0x6D, 0x5B, +0x6D, 0x1D, 0x34, 0x75, 0xA9, 0x23, 0x8A, 0x5B, 0x00, 0x9D, 0x89, 0xA5, 0x9D, 0x8B, 0x9C, 0x5B, +0x9C, 0x1D, 0x11, 0xA5, 0xA9, 0xA1, 0x8B, 0x5B, 0x00, 0x1C, 0x1C, 0xA5, 0x8A, 0x29, 0xAE, 0xA5, +0xA5, 0x19, 0xA5, 0xA5, 0xAE, 0xAE, 0xAE, 0xA5, 0x00, 0x69, 0x69, 0x69, 0x8B, 0xA8, 0xA8, 0x69, +0x69, 0x19, 0x69, 0x69, 0xAE, 0x23, 0xAD, 0x69, 0x00, 0x24, 0x99, 0x24, 0xC0, 0x53, 0x29, 0x24, +0x29, 0x1B, 0x23, 0x89, 0xA5, 0x23, 0x8A, 0x5B, 0x00, 0x24, 0xA1, 0x24, 0xC8, 0x53, 0x7C, 0x24, +0x53, 0x19, 0xA0, 0x89, 0xC9, 0xA1, 0x8B, 0x5D, 0x00, 0xD8, 0x22, 0x06, 0x4A, 0x62, 0x1A, 0x06, +0x1A, 0x5A, 0xC4, 0xC6, 0x28, 0x48, 0xC8, 0xC6, 0x00, 0x26, 0x1A, 0xAA, 0x4A, 0x62, 0x1A, 0xAA, +0x1A, 0x94, 0xCA, 0xAA, 0x08, 0x88, 0x88, 0xAA, 0x00, 0x54, 0x5C, 0xE2, 0x58, 0x44, 0x26, 0xA2, +0x26, 0xC8, 0x26, 0xDE, 0x0A, 0x54, 0x74, 0xA2, 0x00, 0x68, 0xA6, 0x76, 0x5A, 0x44, 0x26, 0xA2, +0x26, 0xE8, 0x48, 0x76, 0x48, 0x94, 0x74, 0xA2, 0x00, 0xC4, 0xDA, 0x74, 0x46, 0xB4, 0x44, 0x74, +0x72, 0x08, 0x44, 0x74, 0x74, 0x84, 0x68, 0x76, 0x00, 0x74, 0x72, 0x74, 0x46, 0xB4, 0xB2, 0x74, +0x72, 0x28, 0x44, 0x74, 0xB2, 0x6E, 0x32, 0x74, 0x00, 0x74, 0xA2, 0x74, 0x94, 0xF4, 0xB2, 0x74, +0x88, 0xCC, 0xA2, 0x94, 0x62, 0x4A, 0x72, 0x9A, 0x00, 0x72, 0xA2, 0x72, 0xC4, 0xF2, 0x22, 0x72, +0xC8, 0xA4, 0xC8, 0x84, 0x0C, 0x8A, 0x72, 0x26, 0x00, 0xAF, 0x42, 0x01, 0xE1, 0xC9, 0x03, 0xB0, +0x20, 0xA5, 0x3D, 0xC9, 0x82, 0xF0, 0x1D, 0xC9, 0x62, 0xF0, 0x19, 0xA4, 0x41, 0xA6, 0x40, 0xD0, +0x01, 0x88, 0xCA, 0x8A, 0x18, 0xE5, 0x3A, 0x85, 0x40, 0x10, 0x01, 0xC8, 0x98, 0xE5, 0x3B, 0xF0, +0x10, 0x4C, 0xCC, 0xAF, 0xC2, 0x30, 0xA5, 0x40, 0x3A, 0x3A, 0x18, 0xE5, 0x3A, 0x85, 0x40, 0xE2, +0x30, 0x20, 0xE3, 0xB1, 0x20, 0x50, 0xA9, 0x20, 0x01, 0xA9, 0x20, 0x01, 0xA9, 0x20, 0xA3, 0xAC, +0x20, 0xF2, 0xAB, 0x80, 0x66, 0xA5, 0x3D, 0x20, 0x13, 0xAC, 0xDA, 0x48, 0xA6, 0x2E, 0xBF, 0xE3, +0xAD, 0xFF, 0x85, 0x2E, 0x68, 0xAA, 0xBF, 0xA9, 0xAE, 0xFF, 0xC5, 0x42, 0xD0, 0x35, 0xBF, 0x29, +0xAE, 0xFF, 0xC5, 0x43, 0xD0, 0x2D, 0xA4, 0x2E, 0xC0, 0x1F, 0xD0, 0x0A, 0xFA, 0x4C, 0x29, 0xAF, +0x4C, 0x93, 0xB0, 0x4C, 0x7C, 0xB0, 0xFA, 0xA5, 0x2C, 0xC5, 0x2E, 0xD0, 0x17, 0xAF, 0x42, 0x01, +0xE1, 0xC5, 0x3F, 0xF0, 0xAC, 0xE0, 0x08, 0xD0, 0x0B, 0xC9, 0x01, 0xF0, 0xF6, 0xC9, 0x02, 0xF0, +0xF2, 0xD0, 0x01, 0xFA, 0xC6, 0x3D, 0xD0, 0xAD, 0xC6, 0x35, 0xF0, 0xA9, 0xA4, 0x34, 0x98, 0xAA, +0x20, 0x52, 0xA9, 0xA9, 0xDE, 0x20, 0x59, 0xA9, 0x20, 0x5D, 0xA0, 0x20, 0x20, 0xA9, 0xA9, 0x00, +0x85, 0x31, 0xA8, 0xAD, 0x00, 0x02, 0xC9, 0xA0, 0xF0, 0xB6, 0xC9, 0xBA, 0xF0, 0x37, 0xC9, 0xA2, +0xF0, 0x61, 0xC9, 0x8D, 0xD0, 0xAD, 0xC2, 0x30, 0x68, 0x8F, 0x30, 0x01, 0xE1, 0xE2, 0x30, 0x4C, +0x4D, 0xA3, 0xC2, 0x30, 0xAF, 0x30, 0x01, 0xE1, 0x48, 0xE2, 0x30, 0xA9, 0xA1, 0x85, 0x33, 0xAD, +0x01, 0x02, 0xC9, 0x8D, 0xF0, 0xC5, 0xA0, 0x00, 0xB9, 0x01, 0x02, 0x99, 0x00, 0x02, 0xC8, 0xC0, +0x20, 0xD0, 0xF5, 0x80, 0xB9, 0xC8, 0x84, 0x34, 0xA4, 0x34, 0x20, 0xA9, 0xB1, 0x84, 0x34, 0x20, +0x1C, 0xB2, 0xD0, 0xF4, 0x80, 0xA5, 0xA9, 0xBA, 0x85, 0x31, 0xA4, 0x34, 0xA5, 0x40, 0x85, 0x3A, +0xA5, 0x41, 0x85, 0x3B, 0x88, 0x20, 0x58, 0xB0, 0xC9, 0x8D, 0xF0, 0x04, 0xC8, 0x84, 0x34, 0x60, +0x4C, 0x4D, 0xA3, 0x20, 0x58, 0xB0, 0x80, 0xDC, 0xC8, 0xB9, 0x00, 0x02, 0xC9, 0x8D, 0xF0, 0x1B, +0xC9, 0xA2, 0xF0, 0x17, 0x5A, 0x2F, 0x33, 0x01, 0xE1, 0x48, 0xA0, 0x00, 0x20, 0xC3, 0xAA, 0x68, +0x20, 0x2B, 0xB4, 0x64, 0x2F, 0x20, 0xF2, 0xAB, 0x7A, 0x80, 0xDD, 0x60, 0x20, 0xD0, 0xB1, 0xC9, +0x93, 0xD0, 0x1E, 0x20, 0x62, 0xFE, 0xF0, 0x19, 0xB9, 0x00, 0x02, 0xC9, 0xA2, 0xF0, 0xC4, 0xC9, +0xBA, 0xF0, 0x92, 0xA9, 0x03, 0x85, 0x3D, 0x20, 0x13, 0xFF, 0x0A, 0xE9, 0xBE, 0xC9, 0xC2, 0xB0, +0x03, 0x4C, 0xCE, 0xAF, 0x0A, 0x0A, 0xA2, 0x04, 0x0A, 0x26, 0x42, 0x26, 0x43, 0xCA, 0x10, 0xF8, +0xC6, 0x3D, 0xF0, 0xF4, 0x10, 0xE1, 0xA2, 0x07, 0x64, 0x3E, 0x20, 0x13, 0xFF, 0x84, 0x34, 0xDF, +0x11, 0xAE, 0xFF, 0xF0, 0x0A, 0xDF, 0x21, 0xAE, 0xFF, 0xD0, 0x1C, 0xA9, 0x40, 0x85, 0x3E, 0xC9, +0xA4, 0xD0, 0x03, 0xC8, 0x80, 0x11, 0x20, 0x13, 0xFF, 0xDF, 0x19, 0xAE, 0xFF, 0xF0, 0x0A, 0xBF, +0x19, 0xAE, 0xFF, 0xF0, 0x03, 0xA4, 0x34, 0x18, 0x88, 0x26, 0x2C, 0xE0, 0x05, 0xD0, 0x36, 0xA5, +0x3E, 0x48, 0x20, 0xA9, 0xB1, 0x8B, 0x20, 0x82, 0xF8, 0x4E, 0x42, 0x01, 0xAB, 0x90, 0x03, 0x20, +0x07, 0xB2, 0x68, 0x85, 0x3E, 0xAF, 0x42, 0x01, 0xE1, 0x29, 0x01, 0xF0, 0x04, 0xA9, 0x01, 0x80, +0x02, 0xA9, 0x00, 0x8F, 0x30, 0x01, 0xE1, 0x8F, 0x31, 0x01, 0xE1, 0xA5, 0x3F, 0xF0, 0x01, 0xE8, +0x86, 0x35, 0xA2, 0x05, 0x88, 0x86, 0x3D, 0xCA, 0x10, 0x90, 0xA5, 0x3E, 0x0F, 0x42, 0x01, 0xE1, +0x8F, 0x42, 0x01, 0xE1, 0x84, 0x34, 0xB9, 0x00, 0x02, 0xC9, 0xBB, 0xF0, 0x07, 0xC9, 0x8D, 0xF0, +0x03, 0x4C, 0x81, 0xB0, 0x4C, 0x75, 0xAF, 0x70, 0x08, 0xB0, 0x25, 0xC9, 0xA0, 0xD0, 0x20, 0xE2, +0x40, 0xB9, 0x00, 0x02, 0xC9, 0xA7, 0xF0, 0x14, 0xC9, 0x8D, 0xD0, 0x03, 0xB8, 0xF0, 0x5D, 0xA2, +0x07, 0x20, 0x07, 0xB2, 0x2F, 0x33, 0x01, 0xE1, 0xC8, 0xD0, 0x0B, 0x60, 0xA9, 0x99, 0xC8, 0x60, +0xA2, 0x03, 0x0A, 0x0A, 0x0A, 0x0A, 0x8B, 0x20, 0x82, 0xF8, 0x0A, 0xC2, 0x30, 0x26, 0x3E, 0x2E, +0x40, 0x01, 0xE2, 0x30, 0xCA, 0x10, 0xF3, 0xAB, 0xA5, 0x31, 0xD0, 0x13, 0xA2, 0x01, 0xB5, 0x3E, +0x95, 0x3C, 0x95, 0x40, 0xBF, 0x40, 0x01, 0xE1, 0x9F, 0x46, 0x01, 0xE1, 0xCA, 0xF0, 0xEF, 0xE8, +0xF0, 0xFD, 0x20, 0x07, 0xB2, 0x70, 0xAA, 0x80, 0x13, 0xB8, 0xC2, 0x30, 0xA9, 0x00, 0x00, 0x85, +0x3E, 0x8F, 0x40, 0x01, 0xE1, 0xE2, 0x30, 0x8F, 0x42, 0x01, 0xE1, 0xAA, 0x20, 0xCA, 0xFC, 0x49, +0xB0, 0xC9, 0x0A, 0x90, 0xAB, 0x08, 0x69, 0x88, 0x28, 0xC9, 0xFA, 0x4C, 0x47, 0xB1, 0xA4, 0x34, +0x20, 0xA9, 0xB1, 0xC9, 0xA8, 0xD0, 0x98, 0xA5, 0x31, 0xD0, 0xF5, 0xA5, 0x3E, 0x8F, 0x3E, 0x01, +0xE1, 0x80, 0xED, 0xA5, 0x40, 0x85, 0x3E, 0xA5, 0x41, 0x85, 0x3F, 0xA4, 0x2F, 0xC0, 0x03, 0xF0, +0x05, 0xB9, 0x3D, 0x00, 0x80, 0x04, 0xAF, 0x40, 0x01, 0xE1, 0x48, 0x20, 0xC3, 0xAA, 0x68, 0x20, +0x2B, 0xB4, 0xC6, 0x2F, 0x10, 0xE5, 0x60, 0x8B, 0x20, 0x82, 0xF8, 0xEE, 0x42, 0x01, 0xAB, 0x60, +0xA2, 0xBA, 0x86, 0x31, 0xA6, 0x40, 0x86, 0x3A, 0xA6, 0x41, 0x86, 0x3B, 0xEB, 0xAF, 0x42, 0x01, +0xE1, 0x4A, 0x90, 0x01, 0x1A, 0xC9, 0x05, 0x90, 0x02, 0xA9, 0x04, 0x3A, 0xAA, 0x85, 0x2F, 0xEB, +0xC9, 0xC6, 0x08, 0xDA, 0xA5, 0x3E, 0x85, 0x3D, 0xA5, 0x3F, 0x85, 0x40, 0xAF, 0x40, 0x01, 0xE1, +0x85, 0x41, 0xAF, 0x41, 0x01, 0xE1, 0x8F, 0x40, 0x01, 0xE1, 0x20, 0xE3, 0xB1, 0x68, 0x85, 0x2F, +0x20, 0xF2, 0xAB, 0x28, 0x60, 0xA5, 0x22, 0x85, 0x25, 0x64, 0x24, 0xA4, 0x24, 0xA5, 0x25, 0x48, +0x20, 0x9C, 0xCD, 0x20, 0x11, 0xB3, 0xA0, 0x00, 0x68, 0x1A, 0xC5, 0x23, 0x90, 0xF1, 0xB0, 0x29, +0xA5, 0x22, 0x48, 0x20, 0x9C, 0xCD, 0xA5, 0x28, 0x85, 0x2A, 0xA5, 0x29, 0x85, 0x2B, 0xA4, 0x21, +0x88, 0x68, 0x1A, 0xC5, 0x23, 0xB0, 0x0D, 0x48, 0x20, 0x9C, 0xCD, 0xB1, 0x28, 0x91, 0x2A, 0x88, +0x10, 0xF9, 0x30, 0xE2, 0xA0, 0x00, 0x20, 0x11, 0xB3, 0xA5, 0x25, 0x4C, 0x9C, 0xCD, 0xA9, 0x28, +0x85, 0x21, 0xA9, 0x18, 0x85, 0x23, 0x3A, 0x85, 0x25, 0xD0, 0xF0, 0xA4, 0x2A, 0x80, 0x62, 0xA4, +0x2A, 0x4C, 0x43, 0xCC, 0x20, 0x37, 0xCC, 0xAD, 0x7B, 0x05, 0x85, 0x24, 0x8D, 0x7B, 0x04, 0x4C, +0x97, 0xCD, 0xB4, 0x00, 0xF0, 0x0F, 0xC0, 0x1B, 0xF0, 0x0E, 0x20, 0x19, 0xCD, 0xB4, 0x00, 0xF0, +0x04, 0xA9, 0xFD, 0x95, 0x01, 0xB5, 0x01, 0x60, 0xA5, 0x37, 0xC9, 0xC3, 0xD0, 0xF3, 0x4C, 0x32, +0xC8, 0xA4, 0x24, 0xB1, 0x28, 0x48, 0x29, 0x3F, 0x09, 0x40, 0x91, 0x28, 0x68, 0x60, 0xA8, 0xA5, +0x28, 0x4C, 0x64, 0xCA, 0x20, 0xAD, 0xCD, 0xDA, 0xA2, 0x03, 0xDF, 0xFA, 0xC3, 0xFF, 0xD0, 0x04, +0xBF, 0xFB, 0xC0, 0xFF, 0xCA, 0x10, 0xF3, 0xFA, 0x60, 0x20, 0xB8, 0xCD, 0x09, 0x80, 0x60, 0xA4, +0x24, 0xA9, 0xA0, 0x2C, 0x1E, 0xC0, 0x10, 0x06, 0x24, 0x32, 0x30, 0x02, 0xA9, 0x20, 0x4C, 0x4E, +0xCC, 0xA8, 0xA5, 0x28, 0x4C, 0x9C, 0xCD, 0x2C, 0x1F, 0xC0, 0x10, 0x03, 0x4C, 0x54, 0xC8, 0xA4, +0x24, 0x91, 0x28, 0x20, 0xC9, 0xCE, 0x20, 0xFC, 0xCE, 0x10, 0xFB, 0x60, 0x20, 0x9E, 0xB2, 0x2C, +0x1F, 0xC0, 0x10, 0x02, 0x06, 0x21, 0xA5, 0x25, 0x8D, 0xFB, 0x05, 0x60, 0xA9, 0xFF, 0x8D, 0xFB, +0x04, 0xAD, 0x58, 0xC0, 0xAD, 0x5A, 0xC0, 0xAD, 0x5D, 0xC0, 0xAD, 0x5F, 0xC0, 0xA9, 0x08, 0x8D, +0x35, 0xC0, 0x60, 0xC8, 0x08, 0x5A, 0xDA, 0x20, 0xC3, 0xAA, 0x20, 0x28, 0xB4, 0xFA, 0x7A, 0x28, +0x60, 0xA4, 0x24, 0xB1, 0x28, 0x2C, 0x1F, 0xC0, 0x30, 0xF6, 0x4C, 0xD2, 0xCE, 0xAF, 0x3E, 0x01, +0xE1, 0x8F, 0x3F, 0x01, 0xE1, 0xA4, 0x42, 0xC2, 0x30, 0xA5, 0x3C, 0x85, 0x42, 0xC6, 0x3E, 0xE2, +0x30, 0x98, 0xA2, 0x42, 0x20, 0x2B, 0xB4, 0xC2, 0x30, 0xE6, 0x42, 0xE2, 0x30, 0xAD, 0x68, 0xC0, +0xCD, 0x83, 0xC0, 0xCD, 0x83, 0xC0, 0x48, 0x8B, 0x29, 0xF2, 0x48, 0xAF, 0x2F, 0x01, 0xE1, 0x0A, +0x0A, 0x03, 0x01, 0x8D, 0x68, 0xC0, 0x68, 0x3B, 0xEB, 0x48, 0xEB, 0x48, 0x4B, 0xF4, 0xEF, 0xB3, +0xA9, 0x5C, 0x48, 0xAF, 0x3E, 0x01, 0xE1, 0x48, 0xAF, 0x3F, 0x01, 0xE1, 0x48, 0xA9, 0x54, 0x48, +0xC2, 0x20, 0x38, 0xA5, 0x3E, 0xE5, 0x3C, 0x48, 0xA2, 0xA9, 0xDA, 0xA5, 0x42, 0x48, 0xA2, 0xA0, +0xDA, 0xA5, 0x3C, 0x48, 0xA2, 0xA2, 0xDA, 0x3B, 0xA2, 0x00, 0xDA, 0xC2, 0x30, 0x48, 0x6B, 0xA3, +0x11, 0x1B, 0xE2, 0x30, 0x80, 0x79, 0x20, 0x26, 0xB4, 0x48, 0xA2, 0x42, 0x20, 0x28, 0xB4, 0x85, +0x40, 0x68, 0xC5, 0x40, 0xF0, 0x1A, 0x48, 0x20, 0x06, 0xA9, 0x68, 0x20, 0x2F, 0xA9, 0x20, 0x08, +0xAC, 0xA9, 0xA8, 0x20, 0x59, 0xA9, 0xA5, 0x40, 0x20, 0x2F, 0xA9, 0xA9, 0xA9, 0x20, 0x59, 0xA9, +0x20, 0xB4, 0xFC, 0x90, 0xD1, 0x60, 0xA2, 0x3C, 0xB8, 0x50, 0x02, 0xE2, 0x40, 0xEB, 0xAD, 0x68, +0xC0, 0xCD, 0x83, 0xC0, 0xCD, 0x83, 0xC0, 0x48, 0x8B, 0x29, 0xF2, 0x48, 0xAF, 0x2F, 0x01, 0xE1, +0x0A, 0x0A, 0x03, 0x01, 0x83, 0x01, 0xAF, 0x39, 0x01, 0xE1, 0xF0, 0x06, 0xAF, 0x2D, 0x01, 0xE1, +0x83, 0x01, 0x68, 0x8D, 0x68, 0xC0, 0xE0, 0x42, 0x90, 0x06, 0xAF, 0x3F, 0x01, 0xE1, 0xB0, 0x04, +0xAF, 0x3E, 0x01, 0xE1, 0x48, 0xAB, 0xEB, 0x50, 0x04, 0x81, 0x00, 0x80, 0x02, 0xA1, 0x00, 0xEB, +0xAB, 0x68, 0x29, 0xBF, 0x2C, 0x1C, 0xC0, 0x10, 0x02, 0x09, 0x40, 0x8D, 0x68, 0xC0, 0xEB, 0x60, +0xAD, 0x00, 0x02, 0xF0, 0x15, 0x8B, 0x68, 0x8F, 0x3E, 0x01, 0xE1, 0x9C, 0x00, 0x02, 0xA9, 0xBA, +0x85, 0x31, 0xA9, 0x02, 0x85, 0x41, 0x3A, 0x85, 0x40, 0x60, 0xAF, 0x42, 0x01, 0xE1, 0xF0, 0x03, +0x20, 0x10, 0xB2, 0xA5, 0x3A, 0x3A, 0x8D, 0x00, 0x02, 0x60, 0xA5, 0x3C, 0x48, 0xA5, 0x3D, 0x48, +0xA0, 0x01, 0x20, 0x26, 0xB4, 0xD9, 0x00, 0x02, 0xD0, 0x29, 0x20, 0xBA, 0xFC, 0xB0, 0x30, 0xC8, +0xCC, 0x00, 0x02, 0x90, 0xED, 0xF0, 0xEB, 0x68, 0x68, 0xA5, 0x3D, 0x48, 0xA5, 0x3C, 0x48, 0xED, +0x00, 0x02, 0x85, 0x3C, 0xB0, 0x02, 0xC6, 0x3D, 0x20, 0x06, 0xA9, 0x68, 0x85, 0x3C, 0x68, 0x85, +0x3D, 0x80, 0xC7, 0x68, 0x85, 0x3D, 0x68, 0x85, 0x3C, 0x20, 0xBA, 0xFC, 0x90, 0xBC, 0x60, 0x68, +0x68, 0x60, 0xA9, 0x37, 0xA0, 0x55, 0x20, 0x64, 0xB6, 0xA9, 0x31, 0xA0, 0x00, 0x20, 0x64, 0xB6, +0x6B, 0x08, 0x78, 0xA2, 0x00, 0xBF, 0x8A, 0x89, 0xFF, 0x9F, 0xC0, 0x02, 0xE1, 0xE8, 0xE0, 0x52, +0x90, 0xF3, 0xA9, 0xFF, 0x9F, 0xC0, 0x02, 0xE1, 0xE8, 0xD0, 0xF9, 0x28, 0x08, 0x78, 0x8B, 0x20, +0x82, 0xF8, 0x20, 0x1D, 0xB6, 0x8E, 0xBC, 0x03, 0x8D, 0xBE, 0x03, 0xE2, 0x30, 0xA2, 0x00, 0x9B, +0xB8, 0xBD, 0xC0, 0x02, 0x20, 0x35, 0xB6, 0xE8, 0xC8, 0xD0, 0xF5, 0xAB, 0x28, 0x6B, 0x8B, 0x08, +0x78, 0x20, 0x82, 0xF8, 0xA2, 0x00, 0x9B, 0xE2, 0x40, 0x20, 0x35, 0xB6, 0x9D, 0xC0, 0x02, 0xE0, +0x29, 0xF0, 0x1C, 0xE0, 0x2A, 0xF0, 0x1C, 0xE0, 0x36, 0xF0, 0x24, 0xE0, 0x37, 0xF0, 0x20, 0xE0, +0x38, 0xB0, 0x06, 0xDF, 0x3D, 0x89, 0xFF, 0x80, 0x14, 0xD0, 0x0C, 0xC9, 0x09, 0x80, 0x0E, 0xC9, +0x08, 0x80, 0x0A, 0xC9, 0x11, 0x80, 0x06, 0xE0, 0x52, 0xB0, 0x04, 0xC9, 0x20, 0xB0, 0x17, 0xE8, +0xC8, 0xD0, 0xC4, 0x20, 0x1D, 0xB6, 0xEC, 0xBC, 0x03, 0xD0, 0x0B, 0xCD, 0xBE, 0x03, 0xD0, 0x06, +0x28, 0x18, 0xE2, 0x30, 0xAB, 0x6B, 0xE2, 0x30, 0x22, 0x01, 0xB5, 0xFF, 0x28, 0x38, 0xAB, 0x6B, +0x08, 0x78, 0x8B, 0x20, 0x82, 0xF8, 0x9C, 0xE0, 0x03, 0xA0, 0x00, 0xEE, 0xE0, 0x03, 0xF0, 0x2C, +0xA2, 0x00, 0xA9, 0xFD, 0x18, 0x69, 0x04, 0x48, 0x09, 0x80, 0xE2, 0x40, 0x20, 0x65, 0xB6, 0xC0, +0x00, 0xD0, 0x05, 0x9D, 0xE1, 0x03, 0x80, 0x08, 0xDD, 0xE1, 0x03, 0xF0, 0x03, 0x68, 0x80, 0xD9, +0x68, 0xE8, 0xE0, 0x04, 0x90, 0xDE, 0xBB, 0xD0, 0x07, 0xC8, 0x80, 0xCF, 0xAB, 0x28, 0x38, 0x6B, +0xAB, 0x28, 0x18, 0x6B, 0x08, 0x78, 0xA9, 0x00, 0x48, 0xA2, 0x00, 0xA9, 0xFD, 0x18, 0x69, 0x04, +0x48, 0xBF, 0xE5, 0x03, 0xE1, 0xA8, 0xA3, 0x01, 0x20, 0x64, 0xB6, 0x68, 0xE8, 0xE0, 0x04, 0x90, +0xEC, 0x22, 0xA0, 0xB5, 0xFF, 0xA2, 0x03, 0xBF, 0xE1, 0x03, 0xE1, 0xDF, 0xE5, 0x03, 0xE1, 0xD0, +0x06, 0xCA, 0x10, 0xF3, 0x68, 0x80, 0xCA, 0x68, 0x3A, 0xD0, 0xCD, 0x80, 0xC0, 0xA2, 0xFA, 0xC2, +0x20, 0x18, 0xA9, 0x00, 0x00, 0x2A, 0x7D, 0xC0, 0x02, 0xCA, 0xE0, 0xFF, 0xD0, 0xF7, 0xC2, 0x30, +0xAA, 0x49, 0xAA, 0xAA, 0x60, 0x48, 0x98, 0x48, 0x29, 0xE0, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x09, +0x38, 0x50, 0x02, 0x09, 0x80, 0xEB, 0x68, 0x29, 0x1F, 0x0A, 0x0A, 0xEB, 0x08, 0x20, 0x69, 0xB6, +0xEB, 0x20, 0x69, 0xB6, 0x28, 0x68, 0x20, 0x6A, 0xB6, 0x48, 0xAD, 0x34, 0xC0, 0x29, 0xDF, 0x8D, +0x34, 0xC0, 0x68, 0x60, 0xB8, 0x5A, 0x08, 0x80, 0xE8, 0xB8, 0x8D, 0x33, 0xC0, 0xAD, 0x34, 0xC0, +0x29, 0x3F, 0x70, 0x04, 0x09, 0xA0, 0x80, 0x02, 0x09, 0xE0, 0x8D, 0x34, 0xC0, 0xAD, 0x34, 0xC0, +0x30, 0xFB, 0xAD, 0x33, 0xC0, 0x60, 0xAF, 0x34, 0x01, 0xE1, 0x48, 0x20, 0x95, 0xB6, 0x68, 0x8F, +0x34, 0x01, 0xE1, 0x18, 0x6B, 0xA9, 0x0B, 0x8D, 0x39, 0xC0, 0xA9, 0xD2, 0x8D, 0x39, 0xC0, 0x20, +0xEF, 0xA0, 0x22, 0x3E, 0xB5, 0xFF, 0x8B, 0x20, 0x82, 0xF8, 0xA2, 0x07, 0xBF, 0x4C, 0x00, 0xE1, +0x48, 0xCA, 0x10, 0xF8, 0x20, 0xFC, 0x84, 0x20, 0xFC, 0x84, 0xA2, 0x00, 0x68, 0x9F, 0x4C, 0x00, +0xE1, 0xE8, 0xE0, 0x08, 0xD0, 0xF6, 0xAB, 0x20, 0xEB, 0xB6, 0xD0, 0x09, 0xAF, 0x38, 0x01, 0xE1, +0x20, 0x2A, 0xB7, 0x38, 0x90, 0x18, 0x22, 0xF4, 0xB6, 0xFF, 0x20, 0xEB, 0xB6, 0xD0, 0x0B, 0xC2, +0x30, 0xA2, 0x01, 0x05, 0x22, 0x00, 0x00, 0xE1, 0xE2, 0x30, 0x60, 0xAD, 0xF3, 0x03, 0x49, 0xA5, +0xCD, 0xF4, 0x03, 0x60, 0x08, 0x78, 0xAD, 0x68, 0xC0, 0x48, 0x29, 0xFE, 0x09, 0x08, 0x8D, 0x68, +0xC0, 0x08, 0x20, 0x37, 0xB7, 0x28, 0xB0, 0x03, 0x20, 0x15, 0xB7, 0x20, 0xE1, 0xF9, 0x68, 0x8D, +0x68, 0xC0, 0x28, 0x18, 0x6B, 0xA2, 0x07, 0xA9, 0x00, 0x1F, 0xE0, 0x02, 0xE1, 0x0A, 0xCA, 0xD0, +0xF8, 0x29, 0xF6, 0x8D, 0x2D, 0xC0, 0x8F, 0x38, 0x01, 0xE1, 0x8D, 0x0A, 0xC0, 0xAF, 0xE3, 0x02, +0xE1, 0xF0, 0x03, 0x8D, 0x0B, 0xC0, 0x60, 0x22, 0x3E, 0xB5, 0xFF, 0x8B, 0x20, 0x82, 0xF8, 0x9C, +0x39, 0x01, 0x18, 0xAD, 0xE0, 0x02, 0x6A, 0x6A, 0x8D, 0x37, 0x01, 0x20, 0x6E, 0xB7, 0xAD, 0x3C, +0xC0, 0x29, 0xF0, 0x0D, 0xDE, 0x02, 0x8D, 0x3C, 0xC0, 0xAD, 0xDE, 0x02, 0x8D, 0xCA, 0x00, 0x0A, +0x0A, 0x0A, 0x0A, 0x8D, 0xB0, 0x1D, 0x20, 0xEA, 0xC3, 0x20, 0xCB, 0x85, 0xAB, 0x60, 0x8B, 0x20, +0x82, 0xF8, 0xAD, 0xDA, 0x02, 0x0A, 0x0A, 0x0A, 0x0A, 0x0D, 0xDB, 0x02, 0x8D, 0x22, 0xC0, 0xAD, +0x34, 0xC0, 0x29, 0xF0, 0x0D, 0xDC, 0x02, 0x8D, 0x34, 0xC0, 0xA9, 0xF0, 0x1C, 0x2B, 0xC0, 0xAD, +0xE9, 0x02, 0x0A, 0x0D, 0xDD, 0x02, 0x0A, 0x0A, 0x0A, 0x0A, 0x09, 0x08, 0x0C, 0x2B, 0xC0, 0xA9, +0x20, 0x1C, 0x29, 0xC0, 0x18, 0xAD, 0xD8, 0x02, 0x6A, 0x6A, 0x8D, 0x21, 0xC0, 0x6A, 0x6A, 0x0C, +0x29, 0xC0, 0xAB, 0x60, 0x90, 0x04, 0x5C, 0x18, 0x00, 0xE1, 0x5C, 0x14, 0x00, 0xE1, 0x18, 0xFB, +0xB0, 0x04, 0xE2, 0x40, 0x80, 0x06, 0xFB, 0xB8, 0x68, 0x09, 0x10, 0x48, 0x18, 0xFB, 0xC2, 0x30, +0x08, 0x8B, 0xF4, 0xE1, 0xE1, 0xAB, 0x8D, 0x08, 0x01, 0xAD, 0x35, 0xC0, 0x8D, 0x19, 0x01, 0x09, +0x00, 0x80, 0x29, 0x1E, 0x9F, 0x8D, 0x35, 0xC0, 0x8E, 0x0A, 0x01, 0x8C, 0x0C, 0x01, 0x7B, 0x8D, +0x10, 0x01, 0xA9, 0x00, 0x00, 0x5B, 0xE2, 0x30, 0x90, 0x06, 0xA3, 0x04, 0x29, 0x10, 0x69, 0x70, +0x70, 0x5D, 0xA9, 0x03, 0x8D, 0x39, 0xC0, 0xAD, 0x39, 0xC0, 0x2C, 0x03, 0x01, 0xF0, 0x30, 0x48, +0x29, 0x07, 0xD0, 0x12, 0xAD, 0x3B, 0xC0, 0x8D, 0x05, 0x01, 0xAD, 0x3B, 0xC0, 0x8D, 0x06, 0x01, +0x22, 0x20, 0x00, 0xE1, 0x80, 0x10, 0xAD, 0x3A, 0xC0, 0x8D, 0x05, 0x01, 0xAD, 0x3A, 0xC0, 0x8D, +0x06, 0x01, 0x22, 0x20, 0x00, 0xE1, 0xA9, 0x00, 0x6A, 0x8D, 0x01, 0x01, 0x68, 0x80, 0x03, 0x9C, +0x01, 0x01, 0x48, 0x2D, 0x04, 0x01, 0xF0, 0x13, 0x22, 0x24, 0x00, 0xE1, 0x6E, 0x01, 0x01, 0x68, +0xAD, 0x01, 0x01, 0xD0, 0x09, 0xC2, 0x30, 0xAB, 0x4C, 0x86, 0xBA, 0x68, 0xD0, 0xF2, 0xB8, 0xC2, +0x30, 0xAB, 0x68, 0x8D, 0x13, 0x01, 0x9C, 0xC3, 0x00, 0x9C, 0xC5, 0x00, 0x50, 0x1E, 0xE2, 0x10, +0x7A, 0x5A, 0x8C, 0x12, 0x01, 0x84, 0x48, 0xA3, 0x02, 0x8D, 0x16, 0x01, 0x85, 0x3A, 0xA0, 0x00, +0xAD, 0x14, 0x01, 0x4A, 0xB0, 0x03, 0xA3, 0x04, 0xA8, 0x8C, 0x15, 0x01, 0x3B, 0x8D, 0x0E, 0x01, +0xE2, 0x30, 0xEB, 0x49, 0x01, 0xD0, 0x0A, 0xAE, 0x16, 0xC0, 0x10, 0x0D, 0xEB, 0x8F, 0x01, 0x01, +0x01, 0xA9, 0x01, 0xEB, 0xAF, 0x00, 0x01, 0x01, 0x1B, 0xAD, 0x68, 0xC0, 0x8D, 0x18, 0x01, 0xAE, +0x18, 0xC0, 0x10, 0x02, 0x29, 0xBF, 0x29, 0x40, 0x09, 0x08, 0x8D, 0x68, 0xC0, 0xAF, 0xF8, 0x07, +0x00, 0x8D, 0x1B, 0x01, 0x50, 0x06, 0x9C, 0xC6, 0x00, 0x4C, 0xB6, 0xBA, 0xEE, 0xCB, 0x00, 0xAD, +0x01, 0x01, 0xF0, 0x0A, 0x8D, 0xC6, 0x00, 0xA9, 0x00, 0x48, 0xAB, 0x4C, 0xAF, 0xBA, 0xA9, 0x00, +0x48, 0xAB, 0xAD, 0x23, 0xC0, 0x10, 0x0F, 0x29, 0x22, 0x4A, 0x4A, 0x90, 0x09, 0xF0, 0x07, 0x22, +0x28, 0x00, 0xE1, 0x4C, 0x33, 0xBA, 0xAD, 0x3C, 0xC0, 0x29, 0xF0, 0x48, 0xC2, 0x30, 0xAD, 0x3E, +0xC0, 0x48, 0xE2, 0x30, 0xA9, 0xE0, 0x8D, 0x3E, 0xC0, 0xAD, 0x3C, 0xC0, 0x29, 0x90, 0x0F, 0xCA, +0x00, 0xE1, 0x8D, 0x3C, 0xC0, 0xAD, 0x3D, 0xC0, 0xAD, 0x3D, 0xC0, 0x8F, 0xCC, 0x00, 0xE1, 0x30, +0x17, 0x22, 0x2C, 0x00, 0xE1, 0xC2, 0x30, 0x68, 0x8D, 0x3E, 0xC0, 0xE2, 0x30, 0x68, 0x0F, 0xCA, +0x00, 0xE1, 0x8D, 0x3C, 0xC0, 0x4C, 0x33, 0xBA, 0xC2, 0x30, 0x68, 0x8D, 0x3E, 0xC0, 0xE2, 0x30, +0x68, 0x0F, 0xCA, 0x00, 0xE1, 0x8D, 0x3C, 0xC0, 0xAD, 0x46, 0xC0, 0x2D, 0x41, 0xC0, 0x8F, 0xC3, +0x00, 0xE1, 0x29, 0x18, 0x48, 0x29, 0x08, 0xF0, 0x1A, 0x22, 0x30, 0x00, 0xE1, 0xAF, 0xD7, 0x00, +0xE1, 0xD0, 0x0C, 0x90, 0x0E, 0xA9, 0x08, 0x1C, 0x41, 0xC0, 0x8D, 0x47, 0xC0, 0x80, 0x04, 0x38, +0x20, 0xA3, 0xBA, 0xAD, 0x27, 0xC0, 0x8F, 0xC5, 0x00, 0xE1, 0x0A, 0x10, 0x0C, 0x90, 0x0A, 0x22, +0x34, 0x00, 0xE1, 0xB8, 0x20, 0xA3, 0xBA, 0x80, 0x02, 0xE2, 0x40, 0x68, 0xD0, 0x04, 0x50, 0x69, +0x70, 0x0A, 0x29, 0x10, 0xF0, 0x63, 0x22, 0x38, 0x00, 0xE1, 0x80, 0x5A, 0xAF, 0xC5, 0x00, 0xE1, +0x29, 0x30, 0x0A, 0x0A, 0x0A, 0x10, 0x55, 0x90, 0x53, 0xAD, 0x26, 0xC0, 0x8F, 0xC4, 0x00, 0xE1, +0x10, 0x07, 0x22, 0x40, 0x00, 0xE1, 0x20, 0xA3, 0xBA, 0xAF, 0xC4, 0x00, 0xE1, 0x29, 0x08, 0xF0, +0x07, 0x22, 0x44, 0x00, 0xE1, 0x20, 0xA3, 0xBA, 0xAF, 0xC4, 0x00, 0xE1, 0x29, 0x20, 0xF0, 0x07, +0x22, 0x48, 0x00, 0xE1, 0x20, 0xA3, 0xBA, 0xAF, 0xC4, 0x00, 0xE1, 0x29, 0x50, 0x0A, 0x0A, 0xF0, +0x09, 0x90, 0x03, 0x8D, 0x10, 0xC0, 0x22, 0x4C, 0x00, 0xE1, 0xAF, 0xC4, 0x00, 0xE1, 0xC9, 0x40, +0xD0, 0x07, 0x22, 0x50, 0x00, 0xE1, 0x20, 0xA3, 0xBA, 0x4C, 0xAF, 0xBA, 0xAF, 0xC5, 0x00, 0xE1, +0xA8, 0x29, 0x0C, 0x4A, 0x4A, 0x4A, 0x90, 0x08, 0xF0, 0x06, 0x22, 0x3C, 0x00, 0xE1, 0x80, 0x23, +0xAD, 0x23, 0xC0, 0x10, 0x0E, 0x29, 0x44, 0x0A, 0x0A, 0xF0, 0x08, 0x90, 0x06, 0x22, 0x54, 0x00, +0xE1, 0x80, 0x10, 0xAD, 0x23, 0xC0, 0x10, 0x10, 0x29, 0x11, 0x4A, 0x90, 0x0B, 0xF0, 0x09, 0x22, +0x58, 0x00, 0xE1, 0x90, 0x31, 0x4C, 0xB5, 0xBA, 0x22, 0x5C, 0x00, 0xE1, 0x80, 0xF5, 0x68, 0x18, +0xFB, 0xAF, 0xC6, 0x00, 0xE1, 0x0A, 0x8F, 0xC6, 0x00, 0xE1, 0xD0, 0x69, 0xA9, 0x80, 0x0C, 0x36, +0xC0, 0xAF, 0x1B, 0x01, 0xE1, 0x8D, 0xF8, 0x07, 0xC2, 0x10, 0xEB, 0xA9, 0x00, 0xAA, 0x2C, 0xFF, +0xCF, 0xBD, 0x00, 0x00, 0xE2, 0x10, 0xA9, 0xE1, 0x48, 0xAB, 0xAD, 0x8B, 0xC0, 0xAD, 0x8B, 0xC0, +0xAD, 0x18, 0x01, 0x8D, 0x68, 0xC0, 0xCE, 0xCB, 0x00, 0xC2, 0x30, 0x9C, 0xC3, 0x00, 0xAD, 0x0E, +0x01, 0x1B, 0xAD, 0x13, 0x01, 0x48, 0xAD, 0x10, 0x01, 0x5B, 0xAC, 0x0C, 0x01, 0xAE, 0x0A, 0x01, +0xAD, 0x19, 0x01, 0x8D, 0x35, 0xC0, 0xAD, 0x08, 0x01, 0xAB, 0x28, 0xB0, 0x01, 0x40, 0xFB, 0x5C, +0x72, 0xC0, 0x00, 0x90, 0x09, 0xAF, 0xC6, 0x00, 0xE1, 0x6A, 0x8F, 0xC6, 0x00, 0xE1, 0x60, 0xAF, +0xC6, 0x00, 0xE1, 0xF0, 0x8A, 0xB8, 0xA9, 0x00, 0x48, 0xAB, 0xAD, 0x68, 0xC0, 0xAE, 0x18, 0xC0, +0x10, 0x02, 0x29, 0xBF, 0x29, 0x40, 0x09, 0x08, 0x8D, 0x68, 0xC0, 0xA9, 0x80, 0x1C, 0x36, 0xC0, +0x50, 0x0B, 0x22, 0x70, 0x00, 0xE1, 0xB0, 0x03, 0x4C, 0xAF, 0xBA, 0xE2, 0x40, 0xC2, 0x20, 0x3B, +0xA2, 0x6B, 0xDA, 0x4B, 0xF4, 0x3D, 0xBA, 0x48, 0x38, 0xFB, 0xA9, 0x04, 0x48, 0x70, 0x04, 0x5C, +0x3D, 0xFD, 0x00, 0xAF, 0x08, 0x01, 0xE1, 0x85, 0x45, 0xAF, 0x0A, 0x01, 0xE1, 0x85, 0x46, 0xAF, +0x0C, 0x01, 0xE1, 0x85, 0x47, 0xAF, 0x0E, 0x01, 0xE1, 0x85, 0x49, 0x38, 0xFB, 0x5C, 0x56, 0xFA, +0x00, 0x0F, 0xA0, 0xC1, 0xF0, 0xF0, 0xEC, 0xE5, 0xA0, 0xC9, 0xC9, 0xE7, 0xF3, 0x00, 0x43, 0x6F, +0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, 0x6F, +0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x31, 0x39, 0x37, +0x37, 0x2D, 0x31, 0x39, 0x38, 0xB7, 0x00, 0x00, 0xC6, 0xE5, 0xF2, 0xEE, 0xA0, 0xC2, 0xE1, 0xE3, +0xE8, 0xED, 0xE1, 0xEE, 0xA0, 0xCA, 0xF2, 0xAE, 0x00, 0x00, 0xB1, 0xB9, 0xB7, 0xB7, 0xA0, 0xCD, +0xE9, 0xE3, 0xF2, 0xEF, 0xF3, 0xEF, 0xE6, 0xF4, 0x0A, 0xA0, 0xC1, 0xEC, 0xEC, 0xA0, 0xD2, 0xE9, +0xE7, 0xE8, 0xF4, 0xF3, 0xA0, 0xD2, 0xE5, 0xF3, 0xE5, 0xF2, 0xF6, 0xE5, 0xE4, 0xAE, 0x00, 0x0D, +0xA0, 0xD2, 0xCF, 0xCD, 0xA0, 0xD6, 0xE5, 0xF2, 0xF3, 0xE9, 0xEF, 0xEE, 0xA0, 0x00, 0x00, 0x13, +0x00, 0x00, 0x15, 0x17, 0x20, 0xB8, 0xA1, 0xA2, 0x00, 0xC2, 0x20, 0x18, 0x8B, 0x4B, 0xAB, 0xBC, +0x8E, 0xBB, 0xAB, 0x8A, 0x69, 0xFF, 0x00, 0xDA, 0x48, 0xE2, 0x30, 0x20, 0x12, 0x96, 0xC2, 0x30, +0x68, 0x20, 0x85, 0xC0, 0xFA, 0xE8, 0xE0, 0x06, 0x90, 0xDF, 0xE2, 0x30, 0xAD, 0x59, 0xFB, 0x4C, +0x2F, 0xA9, 0x5C, 0xCC, 0xB7, 0xFF, 0x5C, 0xBE, 0xB7, 0xFF, 0x5C, 0xBE, 0xB7, 0xFF, 0x5C, 0xE6, +0xA4, 0xFF, 0x5C, 0x1C, 0xB5, 0xFF, 0x5C, 0x3E, 0xB5, 0xFF, 0x5C, 0xE4, 0xB5, 0xFF, 0x5C, 0xA0, +0xB5, 0xFF, 0x5C, 0x83, 0x92, 0xFF, 0x5C, 0xF4, 0xB6, 0xFF, 0x5C, 0xF3, 0xC4, 0xFF, 0x5C, 0xF7, +0xC4, 0xFF, 0x5C, 0x19, 0xFE, 0x00, 0x5C, 0xAC, 0x91, 0xFF, 0x00, 0xC6, 0xE9, 0xF2, 0xED, 0xF7, +0xE1, 0xF2, 0xE5, 0x07, 0xA0, 0xD4, 0xEF, 0xEF, 0xEC, 0xF3, 0x09, 0xA0, 0xC8, 0xE1, 0xF2, 0xE4, +0xF7, 0xE1, 0xF2, 0xE5, 0x8D, 0xA0, 0xC7, 0xA0, 0xC1, 0xEE, 0xE4, 0xF2, 0xE1, 0xE4, 0xE5, 0x06, +0xA0, 0xC5, 0xA0, 0xC2, 0xE5, 0xF2, 0xEE, 0xF3, 0x07, 0xA0, 0xC7, 0xA0, 0xCB, 0xEE, 0xF5, 0xF4, +0xF3, 0xEF, 0xEE, 0x8D, 0xA0, 0xCD, 0xA0, 0xC1, 0xF3, 0xEB, 0xE9, 0xEE, 0xF3, 0x07, 0xA0, 0xC1, +0xA0, 0xC3, 0xE1, 0xE2, 0xF2, 0xE1, 0xEC, 0x06, 0xA0, 0xD2, 0xA0, 0xCB, 0xF5, 0xF2, 0xE9, 0xE8, +0xE1, 0xF2, 0xE1, 0xA0, 0xC6, 0xA0, 0xC2, 0xE1, 0xE3, 0xE8, 0xED, 0xE1, 0xEE, 0xA0, 0xCA, 0xF2, +0xAA, 0x02, 0xA0, 0xC3, 0xA0, 0xC5, 0xF7, 0xF9, 0x09, 0xA0, 0xCA, 0xA0, 0xCD, 0xE1, 0xE3, 0xD0, +0xE8, 0xE5, 0xE5, 0x8D, 0xA0, 0xD0, 0xA0, 0xC2, 0xE1, 0xF5, 0xED, 0x09, 0xA0, 0xD3, 0xA0, 0xC7, +0xEC, 0xE1, 0xF3, 0xF3, 0xAA, 0x06, 0xA0, 0xD2, 0xA0, 0xCD, 0xEF, 0xEF, 0xF2, 0xE5, 0xAA, 0x8D, +0xA0, 0xD2, 0xA0, 0xC4, 0xEF, 0xF5, 0xE3, 0xE5, 0xF4, 0xF4, 0xE5, 0x05, 0xA0, 0xCB, 0xA0, 0xC8, +0xE1, 0xEE, 0xF3, 0xEF, 0xEE, 0x06, 0xA0, 0xCA, 0xA0, 0xD2, 0xE9, 0xE3, 0xEB, 0xE1, 0xF2, 0xE4, +0x8D, 0xA0, 0xC5, 0xA0, 0xCC, 0xE1, 0xE9, 0x0A, 0xA0, 0xC3, 0xA0, 0xCC, 0xE5, 0xF7, 0xE9, 0xF3, +0x07, 0xA0, 0xD4, 0xA0, 0xD2, 0xF5, 0xE4, 0xE9, 0xEE, 0x8D, 0xA0, 0xD2, 0xA0, 0xCD, 0xEF, 0xEE, +0xF4, 0xE1, 0xE7, 0xEE, 0xE5, 0x05, 0xA0, 0xC2, 0xA0, 0xCD, 0xE1, 0xF2, 0xEB, 0xF3, 0x07, 0xA0, +0xCC, 0xA0, 0xD4, 0xE8, 0xEF, 0xED, 0xF0, 0xF3, 0xEF, 0xEE, 0xA0, 0xD0, 0xA0, 0xD2, 0xE5, 0xE9, +0xE3, 0xE8, 0xE5, 0xF2, 0xF4, 0x05, 0xA0, 0xC4, 0xA0, 0xCF, 0xEC, 0xE9, 0xF6, 0xE5, 0xF2, 0x05, +0xA0, 0xC4, 0xE9, 0xE1, 0xE7, 0xF3, 0x8D, 0xA0, 0xC7, 0xA0, 0xD3, 0xE5, 0xE9, 0xF4, 0xFA, 0x08, +0xA0, 0xCA, 0xA0, 0xD7, 0xEF, 0xF2, 0xF4, 0xE8, 0xE9, 0xEE, 0xE7, 0xF4, 0xEF, 0xEE, 0x01, 0xA0, +0xD2, 0xA0, 0xC3, 0xE1, 0xF2, 0xF2, 0x8D, 0xA0, 0xD2, 0xA0, 0xD7, 0xE9, 0xEC, 0xEC, 0xE9, 0xE1, +0xED, 0xF3, 0x13, 0xA0, 0xCB, 0xA0, 0xC7, 0xF2, 0xE1, 0xE2, 0xE5, 0x8D, 0xA0, 0x1D, 0xA0, 0xCA, +0xA0, 0xD2, 0xE5, 0xF9, 0xEE, 0xEF, 0xEC, 0xE4, 0xF3, 0xC4, 0xA0, 0xC8, 0xE9, 0xEC, 0xEC, 0xED, +0xE1, 0xEE, 0xAD, 0xAD, 0xC8, 0xA0, 0xCC, 0xE5, 0xE8, 0xF4, 0xED, 0xE1, 0xEE, 0xAD, 0xAD, 0xCA, +0xA0, 0xCD, 0xE5, 0xE4, 0xE9, 0xE3, 0xE1, 0xAD, 0xAD, 0xCE, 0xA0, 0xD3, 0xF4, 0xE1, 0xF2, 0xEB, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xA0, 0x20, 0x40, 0x21, 0xE0, 0x21, 0x80, 0x22, 0x20, 0x23, +0xC0, 0x23, 0x60, 0x24, 0x00, 0x25, 0xA0, 0x25, 0x40, 0x26, 0xE0, 0x26, 0x80, 0x27, 0x20, 0x28, +0xC0, 0x28, 0x60, 0x29, 0x00, 0x2A, 0xA0, 0x2A, 0x40, 0x2B, 0xE0, 0x2B, 0x80, 0x2C, 0x20, 0x2D, +0xC0, 0x2D, 0x60, 0x2E, 0x00, 0x2F, 0xA0, 0x2F, 0x40, 0x30, 0xE0, 0x30, 0x80, 0x31, 0x20, 0x32, +0xC0, 0x32, 0x60, 0x33, 0x00, 0x34, 0xA0, 0x34, 0x40, 0x35, 0xE0, 0x35, 0x80, 0x36, 0x20, 0x37, +0xC0, 0x37, 0x60, 0x38, 0x00, 0x39, 0xA0, 0x39, 0x40, 0x3A, 0xE0, 0x3A, 0x80, 0x3B, 0x20, 0x3C, +0xC0, 0x3C, 0x60, 0x3D, 0x00, 0x3E, 0xA0, 0x3E, 0x40, 0x3F, 0xE0, 0x3F, 0x80, 0x40, 0x20, 0x41, +0xC0, 0x41, 0x60, 0x42, 0x00, 0x43, 0xA0, 0x43, 0x40, 0x44, 0xE0, 0x44, 0x80, 0x45, 0x20, 0x46, +0xC0, 0x46, 0x60, 0x47, 0x00, 0x48, 0xA0, 0x48, 0x40, 0x49, 0xE0, 0x49, 0x80, 0x4A, 0x20, 0x4B, +0xC0, 0x4B, 0x60, 0x4C, 0x00, 0x4D, 0xA0, 0x4D, 0x40, 0x4E, 0xE0, 0x4E, 0x80, 0x4F, 0x20, 0x50, +0xC0, 0x50, 0x60, 0x51, 0x00, 0x52, 0xA0, 0x52, 0x40, 0x53, 0xE0, 0x53, 0x80, 0x54, 0x20, 0x55, +0xC0, 0x55, 0x60, 0x56, 0x00, 0x57, 0xA0, 0x57, 0x40, 0x58, 0xE0, 0x58, 0x80, 0x59, 0x20, 0x5A, +0xC0, 0x5A, 0x60, 0x5B, 0x00, 0x5C, 0xA0, 0x5C, 0x40, 0x5D, 0xE0, 0x5D, 0x80, 0x5E, 0x20, 0x5F, +0xC0, 0x5F, 0x60, 0x60, 0x00, 0x61, 0xA0, 0x61, 0x40, 0x62, 0xE0, 0x62, 0x80, 0x63, 0x20, 0x64, +0xC0, 0x64, 0x60, 0x65, 0x00, 0x66, 0xA0, 0x66, 0x40, 0x67, 0xE0, 0x67, 0x80, 0x68, 0x20, 0x69, +0xC0, 0x69, 0x60, 0x6A, 0x00, 0x6B, 0xA0, 0x6B, 0x40, 0x6C, 0xE0, 0x6C, 0x80, 0x6D, 0x20, 0x6E, +0xC0, 0x6E, 0x60, 0x6F, 0x00, 0x70, 0xA0, 0x70, 0x40, 0x71, 0xE0, 0x71, 0x80, 0x72, 0x20, 0x73, +0xC0, 0x73, 0x60, 0x74, 0x00, 0x75, 0xA0, 0x75, 0x40, 0x76, 0xE0, 0x76, 0x80, 0x77, 0x20, 0x78, +0xC0, 0x78, 0x60, 0x79, 0x00, 0x7A, 0xA0, 0x7A, 0x40, 0x7B, 0xE0, 0x7B, 0x80, 0x7C, 0x20, 0x7D, +0xC0, 0x7D, 0x60, 0x7E, 0x00, 0x7F, 0xA0, 0x7F, 0x40, 0x80, 0xE0, 0x80, 0x80, 0x81, 0x20, 0x82, +0xC0, 0x82, 0x60, 0x83, 0x00, 0x84, 0xA0, 0x84, 0x40, 0x85, 0xE0, 0x85, 0x80, 0x86, 0x20, 0x87, +0xC0, 0x87, 0x60, 0x88, 0x00, 0x89, 0xA0, 0x89, 0x40, 0x8A, 0xE0, 0x8A, 0x80, 0x8B, 0x20, 0x8C, +0xC0, 0x8C, 0x60, 0x8D, 0x00, 0x8E, 0xA0, 0x8E, 0x40, 0x8F, 0xE0, 0x8F, 0x80, 0x90, 0x20, 0x91, +0xC0, 0x91, 0x60, 0x92, 0x00, 0x93, 0xA0, 0x93, 0x40, 0x94, 0xE0, 0x94, 0x80, 0x95, 0x20, 0x96, +0xC0, 0x96, 0x60, 0x97, 0x00, 0x98, 0xA0, 0x98, 0x40, 0x99, 0xE0, 0x99, 0x80, 0x9A, 0x20, 0x9B, +0xC0, 0x9B, 0x60, 0x9C, 0x2B, 0x80, 0x04, 0x2B, 0xA2, 0x00, 0x00, 0x5A, 0x3B, 0x18, 0x63, 0x01, +0xA8, 0x3B, 0xDA, 0xAA, 0x8B, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xBD, 0x07, 0x00, 0x99, 0x07, 0x00, +0xBD, 0x05, 0x00, 0x99, 0x05, 0x00, 0xBD, 0x03, 0x00, 0x99, 0x03, 0x00, 0xAB, 0xFA, 0x3B, 0x18, +0x63, 0x01, 0x69, 0x02, 0x00, 0x1B, 0x8A, 0xC9, 0x01, 0x00, 0x6B, 0xA0, 0x04, 0x00, 0x80, 0xC8, +0xA0, 0x00, 0x00, 0x80, 0xC3, 0x0B, 0x00, 0x00, 0x00, 0x70, 0xBF, 0xFF, 0x00, 0x9F, 0xBF, 0xFF, +0x00, 0x9F, 0xBF, 0xFF, 0x00, 0xA1, 0xBF, 0xFF, 0x00, 0x72, 0xBF, 0xFF, 0x00, 0xA6, 0xBF, 0xFF, +0x00, 0x3F, 0xBF, 0xFF, 0x00, 0x3F, 0xBF, 0xFF, 0x00, 0xB6, 0xBF, 0xFF, 0x00, 0xAD, 0xBF, 0xFF, +0x00, 0x18, 0xB0, 0x38, 0xA9, 0x00, 0x00, 0x8F, 0xFF, 0x00, 0xE1, 0xA9, 0xFF, 0x00, 0x8F, 0xEF, +0x1D, 0xE0, 0xB0, 0xBC, 0xA9, 0x5C, 0xC0, 0x8F, 0x65, 0x00, 0xE1, 0xA9, 0xEA, 0xBF, 0x8F, 0x69, +0x00, 0xE1, 0xE2, 0x30, 0xA9, 0xFF, 0x8F, 0x67, 0x00, 0xE1, 0x8F, 0x6B, 0x00, 0xE1, 0xC2, 0x30, +0x80, 0x9E, 0xA9, 0x00, 0x02, 0x80, 0x03, 0xA9, 0xFF, 0xFF, 0x83, 0x07, 0x80, 0x92, 0xA9, 0xFF, +0x00, 0x8F, 0xEF, 0x1D, 0xE0, 0x80, 0x89, 0xE2, 0x30, 0x8B, 0xA9, 0xE0, 0x48, 0xAB, 0xAD, 0xEF, +0x1D, 0x1A, 0xC9, 0x04, 0xB0, 0x19, 0x8D, 0xEF, 0x1D, 0x0A, 0x0A, 0xAA, 0xC2, 0x30, 0xA3, 0x08, +0x9D, 0xDF, 0x1D, 0xE8, 0xE8, 0xA3, 0x0A, 0x9D, 0xDF, 0x1D, 0xA9, 0xFF, 0x00, 0x80, 0x05, 0xC2, +0x30, 0xA9, 0x00, 0x00, 0x83, 0x0C, 0xAB, 0x4C, 0x3B, 0xBF, 0x08, 0x78, 0x48, 0xDA, 0x5A, 0xAF, +0xFF, 0x00, 0xE1, 0x3A, 0x30, 0x08, 0x8F, 0xFF, 0x00, 0xE1, 0xF0, 0x09, 0x80, 0x54, 0xA9, 0x00, +0x00, 0x8F, 0xFF, 0x00, 0xE1, 0xE2, 0x30, 0x8B, 0xA9, 0xE0, 0x48, 0xAB, 0xAD, 0xDE, 0x1D, 0xD0, +0x3E, 0xA9, 0x01, 0x8D, 0xDE, 0x1D, 0xAD, 0xEF, 0x1D, 0x30, 0x31, 0x4B, 0x62, 0x0B, 0x00, 0xAD, +0xE1, 0x1D, 0x48, 0xC2, 0x30, 0xAD, 0xDF, 0x1D, 0x3A, 0x48, 0x6B, 0xE2, 0x30, 0xA9, 0xE0, 0x48, +0xAB, 0x78, 0xA2, 0x00, 0xC2, 0x30, 0xBD, 0xE3, 0x1D, 0x9D, 0xDF, 0x1D, 0xE8, 0xE8, 0xE0, 0x0C, +0x00, 0xF0, 0xF3, 0x90, 0xF1, 0xE2, 0x30, 0xCE, 0xEF, 0x1D, 0x10, 0xCA, 0x9C, 0xDE, 0x1D, 0xAB, +0xC2, 0x30, 0x7A, 0xFA, 0x68, 0x28, 0x6B, 0xAF, 0xFF, 0x00, 0xE1, 0x6B, 0x08, 0x78, 0x48, 0xAF, +0xFF, 0x00, 0xE1, 0x1A, 0x8F, 0xFF, 0x00, 0xE1, 0x80, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xA3, +0xA2, 0xE2, 0x40, 0x50, 0xB8, 0x5C, 0x10, 0x00, 0xE1, 0x38, 0x90, 0x18, 0x5C, 0xB4, 0xB7, 0xFF, +0xC2, 0x30, 0x29, 0xFF, 0x00, 0xA4, 0x06, 0x5A, 0xA4, 0x08, 0x5A, 0x0A, 0xA8, 0xAF, 0xC0, 0x00, +0xE1, 0x85, 0x06, 0xAF, 0xC1, 0x00, 0xE1, 0x85, 0x07, 0xB7, 0x06, 0x85, 0x06, 0xE2, 0x70, 0xA7, +0x06, 0xF0, 0x18, 0xC9, 0x20, 0x90, 0x2A, 0xB8, 0xA7, 0x06, 0xF0, 0x1A, 0xC9, 0x20, 0x90, 0x21, +0x70, 0x04, 0x30, 0x0F, 0x09, 0x80, 0x08, 0x20, 0x59, 0xA9, 0x28, 0xE6, 0x06, 0xD0, 0xE9, 0xE6, +0x07, 0x80, 0xE5, 0x20, 0x59, 0xA9, 0xC2, 0x30, 0x68, 0x85, 0x08, 0x68, 0x85, 0x06, 0xE2, 0x30, +0x60, 0xA8, 0xE6, 0x06, 0xD0, 0x02, 0xE6, 0x07, 0xA7, 0x06, 0x5A, 0x70, 0x02, 0x09, 0x80, 0x08, +0x20, 0x59, 0xA9, 0x28, 0x7A, 0x88, 0xD0, 0xF0, 0x80, 0xD1, 0xC1, 0xD8, 0xD9, 0xD3, 0xC4, 0xD0, +0xC2, 0xCB, 0xCD, 0xD1, 0xCC, 0xED, 0xF8, 0xE5, 0xC6, 0xD4, 0x8D, 0xCA, 0xCB, 0xCD, 0xC9, 0x00, +0xE2, 0x40, 0x70, 0x25, 0xEA, 0x38, 0x90, 0x18, 0xB8, 0x50, 0x1E, 0x01, 0x31, 0x45, 0x46, 0x47, +0x48, 0x00, 0x14, 0x00, 0x48, 0x48, 0x20, 0x54, 0xC1, 0x08, 0x78, 0xEB, 0xA9, 0xC1, 0x8D, 0xF8, +0x07, 0xEB, 0x22, 0x06, 0x48, 0xFF, 0x28, 0x80, 0x0D, 0x48, 0x48, 0x20, 0x54, 0xC1, 0xDA, 0xA2, +0xC1, 0x22, 0x00, 0x48, 0xFF, 0xFA, 0xEB, 0x68, 0x8D, 0x36, 0xC0, 0x68, 0x8D, 0x68, 0xC0, 0xEB, +0x08, 0x38, 0xFB, 0x28, 0x60, 0xC8, 0xC8, 0xC8, 0xC8, 0x48, 0x48, 0x20, 0x54, 0xC1, 0x22, 0x03, +0x48, 0xFF, 0x80, 0xE2, 0x08, 0x18, 0xFB, 0x48, 0xAD, 0x36, 0xC0, 0x83, 0x05, 0x09, 0x80, 0x8D, +0x36, 0xC0, 0xAD, 0x68, 0xC0, 0x83, 0x06, 0x29, 0x8F, 0x8D, 0x68, 0xC0, 0xA9, 0x00, 0x8F, 0x96, +0x15, 0xE1, 0x68, 0x28, 0xE2, 0x30, 0x60, 0x4D, 0x53, 0x41, 0xBF, 0xDE, 0x4D, 0xFF, 0xA8, 0xBF, +0xD5, 0x14, 0xE1, 0x10, 0x05, 0x22, 0x26, 0x10, 0xE1, 0x60, 0xB9, 0xFD, 0xBF, 0x60, 0x90, 0x03, +0x4C, 0xC9, 0x4F, 0xDA, 0x20, 0xB3, 0x55, 0xFA, 0xBD, 0xB8, 0x05, 0x09, 0x41, 0x9D, 0xB8, 0x05, +0x5A, 0xA0, 0x04, 0xC2, 0x30, 0xB7, 0x00, 0xD0, 0x0E, 0xE2, 0x30, 0x7A, 0xBD, 0xB8, 0x05, 0x29, +0xBE, 0x9D, 0xB8, 0x05, 0x4C, 0xC4, 0x4F, 0x48, 0x38, 0xE2, 0x30, 0x20, 0x18, 0x54, 0xC2, 0x30, +0x68, 0xDA, 0xBB, 0x9F, 0xE0, 0x1D, 0xE1, 0xA9, 0x00, 0x00, 0x9F, 0xDE, 0x1D, 0xE1, 0xFA, 0xE2, +0x30, 0xDA, 0xA0, 0x08, 0xE0, 0xC2, 0xA2, 0x02, 0xB7, 0x00, 0xB0, 0x06, 0x9F, 0xA4, 0x15, 0xE1, +0x80, 0x04, 0x9F, 0xA7, 0x15, 0xE1, 0x88, 0xCA, 0x10, 0xEE, 0xFA, 0x7A, 0x20, 0xC4, 0x51, 0xBF, +0xD5, 0x14, 0xE1, 0x10, 0x04, 0x22, 0x32, 0x10, 0xE1, 0x4C, 0xC4, 0x4F, 0x00, 0x00, 0x10, 0x10, +0xE2, 0x40, 0x70, 0x25, 0xEA, 0x38, 0x90, 0x18, 0xB8, 0x50, 0x1E, 0x01, 0x31, 0x45, 0x46, 0x47, +0x48, 0x00, 0x14, 0x00, 0x48, 0x48, 0x20, 0x54, 0xC2, 0x08, 0x78, 0xEB, 0xA9, 0xC2, 0x8D, 0xF8, +0x07, 0xEB, 0x22, 0x06, 0x48, 0xFF, 0x28, 0x80, 0x0D, 0x48, 0x48, 0x20, 0x54, 0xC2, 0xDA, 0xA2, +0xC2, 0x22, 0x00, 0x48, 0xFF, 0xFA, 0xEB, 0x68, 0x8D, 0x36, 0xC0, 0x68, 0x8D, 0x68, 0xC0, 0xEB, +0x08, 0x38, 0xFB, 0x28, 0x60, 0xC8, 0xC8, 0xC8, 0xC8, 0x48, 0x48, 0x20, 0x54, 0xC2, 0x22, 0x03, +0x48, 0xFF, 0x80, 0xE2, 0x08, 0x18, 0xFB, 0x48, 0xAD, 0x36, 0xC0, 0x83, 0x05, 0x09, 0x80, 0x8D, +0x36, 0xC0, 0xAD, 0x68, 0xC0, 0x83, 0x06, 0x29, 0x8F, 0x8D, 0x68, 0xC0, 0xA9, 0x00, 0x8F, 0x97, +0x15, 0xE1, 0x68, 0x28, 0xE2, 0x30, 0x60, 0x4D, 0x53, 0x41, 0xDA, 0x20, 0x2E, 0x55, 0xFA, 0xBD, +0xB8, 0x05, 0x89, 0x40, 0xF0, 0x03, 0x20, 0xC4, 0x51, 0x60, 0xB0, 0x0B, 0xA9, 0x03, 0x20, 0xCE, +0x55, 0xAA, 0xB9, 0xFD, 0xBF, 0x80, 0x35, 0x4C, 0xC9, 0x4F, 0x5A, 0xA0, 0x04, 0xB7, 0x00, 0xAA, +0xC8, 0xB7, 0x00, 0x7A, 0xB0, 0x1F, 0x8A, 0x20, 0xCE, 0x55, 0xA0, 0x05, 0x97, 0x00, 0x80, 0x24, +0xBB, 0xBF, 0x57, 0x15, 0xE1, 0x90, 0x13, 0x29, 0x6F, 0x5A, 0xA0, 0x04, 0x17, 0x00, 0x7A, 0x9F, +0x57, 0x15, 0xE1, 0xA2, 0x05, 0x20, 0xC1, 0x55, 0x80, 0x0A, 0xA2, 0x00, 0xA0, 0x04, 0x97, 0x00, +0xC8, 0x8A, 0x97, 0x00, 0x4C, 0xC4, 0x4F, 0x00, 0xFE, 0xFE, 0x15, 0x57, 0xFE, 0x7E, 0xBE, 0x5E, +0x3E, 0x2E, 0x1E, 0x16, 0x0E, 0x0A, 0x04, 0x00, 0x08, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, +0xE2, 0x40, 0x70, 0x37, 0xEA, 0x38, 0x90, 0x18, 0xB8, 0x50, 0x30, 0x01, 0x88, 0x69, 0x6F, 0x75, +0x7B, 0x4C, 0x98, 0xC3, 0xEB, 0xAD, 0xED, 0x03, 0x48, 0xAD, 0xEE, 0x03, 0x48, 0xA9, 0x30, 0x0C, +0x68, 0xC0, 0xB0, 0x03, 0x1C, 0x68, 0xC0, 0x68, 0x8D, 0xEE, 0x03, 0x68, 0x8D, 0xED, 0x03, 0xEB, +0x8D, 0x08, 0xC0, 0x50, 0x03, 0x8D, 0x09, 0xC0, 0x6C, 0xED, 0x03, 0x8D, 0x7B, 0x06, 0x5A, 0xDA, +0x08, 0x2C, 0xF8, 0x07, 0x30, 0x05, 0xA9, 0x08, 0x0C, 0xFB, 0x04, 0x20, 0x8F, 0xC3, 0x28, 0x70, +0x15, 0x90, 0x10, 0xAD, 0xFB, 0x04, 0x10, 0x0B, 0x20, 0xF4, 0xCC, 0xFA, 0x7A, 0xAD, 0x7B, 0x06, +0x6C, 0x38, 0x00, 0x4C, 0x5A, 0xC8, 0x4C, 0x03, 0xC8, 0x20, 0x8F, 0xC3, 0x4C, 0xB4, 0xC9, 0x20, +0x8F, 0xC3, 0x4C, 0xD0, 0xC9, 0x20, 0x8F, 0xC3, 0x4C, 0xEA, 0xC9, 0x20, 0x8F, 0xC3, 0xAA, 0xF0, +0x08, 0xCA, 0xD0, 0x07, 0x20, 0x94, 0xCF, 0x10, 0x04, 0x38, 0x60, 0xA2, 0x03, 0x18, 0x60, 0xA2, +0xC3, 0x8E, 0xF8, 0x07, 0xAE, 0xFF, 0xCF, 0x60, 0x8B, 0x48, 0x5A, 0xDA, 0xAD, 0x68, 0xC0, 0x48, +0x29, 0xCF, 0x8D, 0x68, 0xC0, 0xAD, 0x36, 0xC0, 0x48, 0x09, 0x80, 0x8D, 0x36, 0xC0, 0x08, 0x08, +0x18, 0xFB, 0xC2, 0x30, 0x38, 0xA5, 0x3E, 0x48, 0xE5, 0x3C, 0x48, 0xA3, 0x05, 0x6A, 0xA3, 0x01, +0xA6, 0x3C, 0xA4, 0x42, 0x90, 0x05, 0x54, 0x01, 0x00, 0x80, 0x03, 0x54, 0x00, 0x01, 0x68, 0x38, +0x65, 0x42, 0x85, 0x42, 0x68, 0x1A, 0x85, 0x3C, 0x68, 0xE2, 0x30, 0x68, 0x8D, 0x36, 0xC0, 0x68, +0x8D, 0x68, 0xC0, 0x38, 0xFB, 0xFA, 0x7A, 0x68, 0xAB, 0x60, 0xAF, 0xEF, 0x02, 0xE1, 0x49, 0x07, +0x38, 0xE9, 0x03, 0x0A, 0x1A, 0x8F, 0x45, 0x01, 0xE1, 0x60, 0x88, 0x95, 0x8A, 0x8B, 0x86, 0x82, +0x80, 0x05, 0xC6, 0xC1, 0xC2, 0x38, 0x90, 0x18, 0x80, 0x16, 0xEA, 0x01, 0x20, 0x8D, 0x8D, 0x8D, +0x8D, 0x00, 0x59, 0x29, 0xB2, 0x96, 0xA5, 0xAD, 0xEC, 0x91, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, +0x5A, 0x9B, 0xA2, 0x06, 0x20, 0xB4, 0xC4, 0x7A, 0x60, 0xA9, 0x0E, 0x1C, 0x7C, 0x07, 0xAF, 0xC3, +0x00, 0xE1, 0xA8, 0x29, 0x08, 0xF0, 0x0C, 0x8D, 0x47, 0xC0, 0x98, 0x29, 0xF7, 0x8F, 0xC3, 0x00, +0xE1, 0xA9, 0x08, 0xA8, 0x0C, 0x7C, 0x07, 0x2C, 0x27, 0xC0, 0x50, 0x08, 0x10, 0x06, 0xA9, 0x0E, +0xA8, 0x0C, 0x7C, 0x07, 0x98, 0xF0, 0x38, 0x18, 0x60, 0xC9, 0x10, 0xB0, 0x32, 0xA8, 0x6A, 0x08, +0xA9, 0x0F, 0x1C, 0xFC, 0x07, 0x98, 0x0C, 0xFC, 0x07, 0x29, 0x08, 0x8F, 0xD7, 0x00, 0xE1, 0x28, +0x90, 0x0C, 0x98, 0x29, 0x06, 0xF0, 0x07, 0xA9, 0x40, 0x0C, 0x27, 0xC0, 0x80, 0x05, 0xA9, 0x40, +0x1C, 0x27, 0xC0, 0x98, 0x29, 0x08, 0xF0, 0x1D, 0x0C, 0x41, 0xC0, 0x80, 0x18, 0xA2, 0x03, 0x38, +0x60, 0xA2, 0x00, 0x20, 0xB4, 0xC4, 0x9C, 0x7C, 0x05, 0x9C, 0x7C, 0x04, 0x9C, 0xFC, 0x05, 0x9C, +0xFC, 0x04, 0x9C, 0x7C, 0x07, 0x08, 0x78, 0x20, 0xD2, 0xC4, 0x28, 0x18, 0x60, 0xA2, 0x02, 0x20, +0xB4, 0xC4, 0xA2, 0x04, 0x08, 0x18, 0xFB, 0x28, 0xEB, 0xAD, 0x36, 0xC0, 0x48, 0x09, 0x80, 0x8D, +0x36, 0xC0, 0xEB, 0x22, 0x51, 0x9C, 0xFF, 0x08, 0x38, 0xFB, 0x28, 0xEB, 0x68, 0x8D, 0x36, 0xC0, +0xEB, 0x60, 0xAD, 0x27, 0xC0, 0x10, 0xB8, 0x6A, 0x6A, 0xAD, 0x24, 0xC0, 0xAA, 0xB0, 0xB0, 0xAD, +0x27, 0xC0, 0x29, 0x02, 0xF0, 0xA9, 0xAD, 0x24, 0xC0, 0xA8, 0x18, 0x60, 0xA2, 0x08, 0x20, 0xB4, +0xC4, 0x80, 0xB2, 0x20, 0x80, 0xC0, 0x6B, 0x20, 0x85, 0xC0, 0x6B, 0xD6, 0xC6, 0xC1, 0xC2, 0x01, +0xA2, 0x20, 0xA2, 0x00, 0xA2, 0x03, 0xC9, 0x00, 0xB0, 0x0C, 0x38, 0xB0, 0x01, 0x18, 0x6A, 0x29, +0x80, 0x8F, 0xB0, 0x0F, 0xE1, 0x18, 0x90, 0x06, 0xA9, 0xC0, 0x8F, 0xB0, 0x0F, 0xE1, 0xFB, 0x18, +0xFB, 0xE2, 0x30, 0xA9, 0xC5, 0x8D, 0xF8, 0x07, 0xA9, 0x04, 0x8F, 0xC7, 0x0F, 0xE1, 0x08, 0x8B, +0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xAD, 0x36, 0xC0, 0x48, 0x8F, 0xC8, 0x0F, 0xE1, 0x29, 0xFB, 0x09, +0x80, 0x8D, 0x36, 0xC0, 0xA3, 0x03, 0x4A, 0x22, 0xB5, 0x6A, 0xFF, 0xEB, 0x68, 0xAF, 0xC8, 0x0F, +0xE1, 0x8D, 0x36, 0xC0, 0x08, 0x38, 0xFB, 0x28, 0xAB, 0x68, 0xEB, 0x48, 0xAF, 0xB0, 0x0F, 0xE1, +0x29, 0x40, 0xD0, 0x02, 0x68, 0x60, 0xF4, 0x00, 0x00, 0xAB, 0xAB, 0xA9, 0x08, 0x8D, 0x35, 0xC0, +0x68, 0xB0, 0x03, 0x4C, 0x01, 0x08, 0xA6, 0x00, 0xD0, 0x0A, 0xA5, 0x01, 0xCD, 0xF8, 0x07, 0xD0, +0x03, 0x4C, 0xBA, 0xFA, 0x4C, 0x00, 0xE0, 0x20, 0x93, 0xFE, 0x20, 0x89, 0xFE, 0x20, 0x39, 0xFB, +0x20, 0x58, 0xFC, 0xA9, 0x0A, 0x85, 0x25, 0x64, 0x24, 0x20, 0x22, 0xFC, 0x6B, 0x03, 0x03, 0x83, +0x01, 0x83, 0x01, 0x01, 0x01, 0x03, 0x83, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, +0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, +0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, +0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xC3, 0xFF, 0xFC, 0xF3, 0xCF, 0x3F, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBF, 0x0A, +0xA2, 0x20, 0xA0, 0x00, 0x64, 0x03, 0x64, 0x3C, 0x5A, 0x5A, 0x2B, 0x4B, 0xAB, 0xA9, 0xC6, 0x8D, +0xF8, 0x07, 0xE2, 0x30, 0x08, 0x68, 0x8D, 0xFE, 0x07, 0x78, 0x22, 0x49, 0x65, 0xFF, 0xA2, 0x60, +0xB0, 0x0C, 0x64, 0x03, 0x78, 0x18, 0x08, 0x28, 0xA6, 0x2B, 0xC6, 0x03, 0xD0, 0x28, 0xBD, 0x88, +0xC0, 0x22, 0xB1, 0x65, 0xFF, 0x20, 0x48, 0xC6, 0xA5, 0x01, 0xCD, 0xF8, 0x07, 0xD0, 0x03, 0x4C, +0xBA, 0xFA, 0x4C, 0x00, 0xE0, 0x9C, 0x35, 0xC0, 0xAD, 0xFE, 0x07, 0x29, 0x04, 0xD0, 0x01, 0x58, +0xA5, 0x3D, 0x60, 0x00, 0x00, 0x00, 0x08, 0x88, 0xD0, 0x04, 0xF0, 0xCB, 0x80, 0xC4, 0xBD, 0x8C, +0xC0, 0x10, 0xFB, 0x49, 0xD5, 0xD0, 0xF0, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0xAA, 0xD0, 0xF3, +0xEA, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0xC9, 0x96, 0xF0, 0x09, 0x28, 0x90, 0xA8, 0x49, 0xAD, 0xF0, +0x25, 0xD0, 0xA2, 0xA0, 0x03, 0x85, 0x40, 0xBD, 0x8C, 0xC0, 0x10, 0xFB, 0x2A, 0x85, 0x3C, 0xBD, +0x8C, 0xC0, 0x10, 0xFB, 0x25, 0x3C, 0x88, 0xD0, 0xEC, 0x28, 0xC5, 0x3D, 0xD0, 0x87, 0xA5, 0x40, +0xC5, 0x41, 0xD0, 0x81, 0xB0, 0x82, 0xA0, 0x56, 0x84, 0x3C, 0xBC, 0x8C, 0xC0, 0x10, 0xFB, 0x59, +0xD6, 0x02, 0xA4, 0x3C, 0x88, 0x99, 0x00, 0x03, 0xD0, 0xEE, 0x84, 0x3C, 0xBC, 0x8C, 0xC0, 0x10, +0xFB, 0x59, 0xD6, 0x02, 0xA4, 0x3C, 0x91, 0x26, 0xC8, 0xD0, 0xEF, 0xBC, 0x8C, 0xC0, 0x10, 0xFB, +0x59, 0xD6, 0x02, 0xD0, 0xCD, 0xA0, 0x00, 0xA2, 0x56, 0xCA, 0x30, 0xFB, 0xB1, 0x26, 0x5E, 0x00, +0x03, 0x2A, 0x5E, 0x00, 0x03, 0x2A, 0x91, 0x26, 0xC8, 0xD0, 0xEE, 0xE6, 0x27, 0xE6, 0x3D, 0xA5, +0x3D, 0xCD, 0x00, 0x08, 0xA6, 0x4F, 0x90, 0xDB, 0x20, 0x45, 0xC6, 0x4C, 0x01, 0x08, 0x00, 0x00, +0xE2, 0x40, 0x70, 0x1B, 0xEA, 0x38, 0x90, 0x18, 0xB8, 0x50, 0x14, 0x01, 0x31, 0x37, 0x38, 0x39, +0x3A, 0x00, 0x14, 0x00, 0x48, 0x48, 0x20, 0x46, 0xC7, 0x22, 0x00, 0x10, 0xE1, 0x80, 0x09, 0x48, +0x48, 0x20, 0x46, 0xC7, 0x22, 0x04, 0x10, 0xE1, 0xEB, 0x68, 0x8D, 0x68, 0xC0, 0x68, 0x8D, 0x36, +0xC0, 0xEB, 0x08, 0x38, 0xFB, 0x28, 0x60, 0xC8, 0xC8, 0xC8, 0xC8, 0x48, 0x48, 0x20, 0x46, 0xC7, +0x22, 0x08, 0x10, 0xE1, 0x80, 0xE2, 0x08, 0x18, 0xFB, 0x28, 0xE2, 0x30, 0xEB, 0xAD, 0x36, 0xC0, +0x83, 0x04, 0x09, 0x80, 0x8D, 0x36, 0xC0, 0xAD, 0x68, 0xC0, 0x83, 0x03, 0x29, 0x8F, 0x8D, 0x68, +0xC0, 0xEB, 0x60, 0xA8, 0xC3, 0xA9, 0xA0, 0xC1, 0xF0, 0xF0, 0xEC, 0xE5, 0xAC, 0xA0, 0xB1, 0xB9, +0xB8, 0xB6, 0xAC, 0xA0, 0xC7, 0xF2, 0xE5, 0xE7, 0xA0, 0xD3, 0xE5, 0xE9, 0xF4, 0xFA, 0xAC, 0xA0, +0xD0, 0xE5, 0xF4, 0xE5, 0xF2, 0xA0, 0xD2, 0xE9, 0xE3, 0xE8, 0xE5, 0xF2, 0xF4, 0xAC, 0xA0, 0xC5, +0xE4, 0xA0, 0xCC, 0xE1, 0xE9, 0x00, 0x22, 0x18, 0x10, 0xE1, 0x60, 0x22, 0x1C, 0x10, 0xE1, 0x60, +0xFB, 0xD4, 0x85, 0xAB, 0xAB, 0xDC, 0x84, 0x00, 0x18, 0xFB, 0x6B, 0xA2, 0xFF, 0x6B, 0x18, 0xFB, +0x22, 0x22, 0x10, 0xE1, 0x08, 0x38, 0xFB, 0x28, 0x50, 0x0A, 0xAF, 0x21, 0x10, 0xE1, 0x48, 0xAF, +0x20, 0x10, 0xE1, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x48, 0xFF, 0x5C, 0x03, 0x48, 0xFF, +0x18, 0xFB, 0xC2, 0x30, 0xA2, 0x00, 0x11, 0xA0, 0xE1, 0x00, 0xA9, 0x00, 0x06, 0x8F, 0x00, 0x11, +0xE1, 0x5C, 0x14, 0x10, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x4C, 0x4B, 0x00, 0x10, 0x10, +0x4C, 0xB0, 0xC9, 0x20, 0x89, 0xCE, 0x20, 0x2A, 0xC8, 0x20, 0xCB, 0xCC, 0xA9, 0x00, 0x8F, 0x34, +0x01, 0xE1, 0xA9, 0x01, 0x8D, 0xFB, 0x04, 0x06, 0x21, 0x8D, 0x01, 0xC0, 0x8D, 0x0D, 0xC0, 0x8D, +0x0F, 0xC0, 0x20, 0x37, 0xCC, 0xAC, 0x7B, 0x05, 0x80, 0x32, 0xA9, 0x07, 0x85, 0x36, 0xA9, 0xC3, +0x85, 0x37, 0xA9, 0x05, 0x85, 0x38, 0xA9, 0xC3, 0x85, 0x39, 0x60, 0xE6, 0x4E, 0xD0, 0x02, 0xE6, +0x4F, 0x20, 0x74, 0xCF, 0x10, 0xF5, 0x60, 0xC6, 0xCA, 0xC2, 0x00, 0x00, 0x00, 0x4C, 0x6F, 0xC3, +0xA4, 0x35, 0x18, 0xB0, 0x38, 0x8D, 0x7B, 0x06, 0x5A, 0xDA, 0xB0, 0x6E, 0x20, 0x73, 0xC9, 0xAD, +0x7B, 0x06, 0xC9, 0x8D, 0xD0, 0x18, 0xAE, 0x00, 0xC0, 0x10, 0x13, 0xE0, 0x93, 0xD0, 0x0F, 0x2C, +0x10, 0xC0, 0xAE, 0x00, 0xC0, 0x10, 0xFB, 0xE0, 0x83, 0xF0, 0x03, 0x2C, 0x10, 0xC0, 0xEB, 0xAF, +0x36, 0x01, 0xE1, 0x10, 0x0E, 0xEB, 0x8F, 0x34, 0x01, 0xE1, 0xA9, 0x01, 0x8F, 0x36, 0x01, 0xE1, +0x18, 0x80, 0x1D, 0xEB, 0x29, 0x7F, 0xC9, 0x20, 0xB0, 0x05, 0x20, 0x7C, 0xCA, 0x80, 0x11, 0xAD, +0x7B, 0x06, 0x20, 0xE7, 0xCD, 0xC8, 0x8C, 0x7B, 0x05, 0xC4, 0x21, 0x90, 0x03, 0x20, 0xEA, 0xCA, +0xA9, 0x08, 0x1C, 0xFB, 0x04, 0xAD, 0x7B, 0x05, 0x2C, 0x1F, 0xC0, 0x10, 0x02, 0xA9, 0x00, 0x85, +0x24, 0x8D, 0x7B, 0x04, 0xFA, 0x7A, 0xAD, 0x7B, 0x06, 0x60, 0xA4, 0x24, 0xAD, 0x7B, 0x06, 0x91, +0x28, 0x20, 0x73, 0xC9, 0x20, 0xC9, 0xCE, 0x20, 0xFC, 0xCE, 0x10, 0xFB, 0x8D, 0x7B, 0x06, 0xA8, +0xAD, 0xFB, 0x04, 0x29, 0x08, 0xF0, 0xCE, 0xC0, 0x8D, 0xD0, 0x05, 0xA9, 0x08, 0x1C, 0xFB, 0x04, +0xC0, 0x9B, 0xF0, 0x0E, 0xC0, 0x95, 0xD0, 0xBD, 0x20, 0xB8, 0xCD, 0x09, 0x80, 0x8D, 0x7B, 0x06, +0xD0, 0xB3, 0x20, 0x37, 0xCE, 0x20, 0x3B, 0xC8, 0x20, 0x49, 0xCE, 0x20, 0xAD, 0xCD, 0x29, 0x7F, +0xA0, 0x10, 0xD9, 0x62, 0xC9, 0xF0, 0x05, 0x88, 0x10, 0xF8, 0x30, 0x0F, 0xB9, 0x51, 0xC9, 0x29, +0x7F, 0x20, 0x7F, 0xCA, 0xB9, 0x51, 0xC9, 0x30, 0xD9, 0x10, 0xA9, 0xA8, 0xAD, 0xFB, 0x04, 0xC0, +0x11, 0xD0, 0x0B, 0x20, 0xE6, 0xCC, 0xA9, 0x98, 0x8D, 0x7B, 0x06, 0x4C, 0xB5, 0xC8, 0xC0, 0x05, +0xD0, 0x07, 0x29, 0xDF, 0x8D, 0xFB, 0x04, 0x80, 0x8B, 0xC0, 0x04, 0xD0, 0xFA, 0x09, 0x20, 0xD0, +0xF3, 0x0C, 0x1C, 0x08, 0x0A, 0x1F, 0x1D, 0x0B, 0x9F, 0x88, 0x9C, 0x8A, 0x11, 0x12, 0x88, 0x8A, +0x9F, 0x9C, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x49, 0x4A, 0x4B, 0x4D, 0x34, 0x38, 0x08, +0x0A, 0x0B, 0x15, 0xA4, 0x25, 0x8C, 0xFB, 0x05, 0xA4, 0x24, 0xCC, 0x7B, 0x04, 0xD0, 0x03, 0xAC, +0x7B, 0x05, 0xC4, 0x21, 0x90, 0x02, 0xA0, 0x00, 0x8C, 0x7B, 0x05, 0x2C, 0x1F, 0xC0, 0x10, 0x02, +0xA0, 0x00, 0x84, 0x24, 0x8C, 0x7B, 0x04, 0xAC, 0x7B, 0x05, 0x60, 0x20, 0x78, 0xC9, 0x88, 0x20, +0x88, 0xC9, 0x98, 0x60, 0x3A, 0xA8, 0x80, 0xF7, 0x00, 0x00, 0xAD, 0x7B, 0x06, 0x4C, 0x75, 0xC3, +0xA9, 0x83, 0xD0, 0x02, 0xA9, 0x81, 0x8D, 0xFB, 0x04, 0x8D, 0x01, 0xC0, 0x8D, 0x0D, 0xC0, 0x8D, +0x0F, 0xC0, 0xA9, 0x00, 0x8F, 0x34, 0x01, 0xE1, 0x20, 0x69, 0xCE, 0x20, 0x37, 0xCC, 0x80, 0x47, +0x20, 0x69, 0xCE, 0x20, 0x3B, 0xC8, 0x29, 0x7F, 0x8D, 0x7B, 0x06, 0xA2, 0x00, 0xAD, 0xFB, 0x04, +0x29, 0x02, 0xF0, 0x02, 0xA2, 0xC3, 0xAD, 0x7B, 0x06, 0x60, 0x29, 0x7F, 0xAA, 0x20, 0x69, 0xCE, +0xA9, 0x08, 0x2C, 0xFB, 0x04, 0xD0, 0x30, 0x8A, 0x2C, 0x26, 0xCA, 0xF0, 0x4E, 0xAC, 0x7B, 0x05, +0x24, 0x32, 0x10, 0x02, 0x09, 0x80, 0x20, 0xF9, 0xCD, 0xC8, 0x8C, 0x7B, 0x05, 0xC4, 0x21, 0x90, +0x06, 0x9C, 0x7B, 0x05, 0x20, 0x71, 0xCB, 0xA5, 0x28, 0x8D, 0x7B, 0x07, 0xA5, 0x29, 0x8D, 0xFB, +0x07, 0x20, 0x53, 0xCE, 0xA2, 0x00, 0x60, 0x20, 0x53, 0xCE, 0x8A, 0x38, 0xE9, 0x20, 0x2C, 0xFB, +0x06, 0x30, 0x2C, 0x8D, 0xFB, 0x05, 0x85, 0x25, 0x20, 0x64, 0xCA, 0xAD, 0xFB, 0x06, 0x8D, 0x7B, +0x05, 0xA9, 0xF7, 0x2D, 0xFB, 0x04, 0x8D, 0xFB, 0x04, 0xD0, 0xCC, 0x20, 0x53, 0xCE, 0x8A, 0xC9, +0x1E, 0xF0, 0x05, 0x20, 0x7F, 0xCA, 0x80, 0xBF, 0xA9, 0x08, 0x0C, 0xFB, 0x04, 0xA9, 0xFF, 0x8D, +0xFB, 0x06, 0x80, 0xBD, 0x48, 0x4A, 0x29, 0x03, 0x09, 0x04, 0x85, 0x29, 0x68, 0x29, 0x18, 0x90, +0x02, 0x69, 0x7F, 0x85, 0x28, 0x0A, 0x0A, 0x05, 0x28, 0x85, 0x28, 0x60, 0xE2, 0x40, 0x50, 0xB8, +0x8D, 0x7B, 0x07, 0x48, 0x5A, 0xAC, 0x7B, 0x07, 0xC0, 0x05, 0x90, 0x13, 0xB9, 0x4D, 0xCB, 0xF0, +0x0E, 0x50, 0x12, 0x30, 0x10, 0x8D, 0x7B, 0x07, 0xAD, 0xFB, 0x04, 0x29, 0x28, 0xF0, 0x03, 0x38, +0xB0, 0x09, 0xAD, 0x7B, 0x07, 0x09, 0x80, 0x20, 0xAE, 0xCA, 0x18, 0x7A, 0x68, 0x60, 0x48, 0xB9, +0x32, 0xCB, 0x48, 0x60, 0xAD, 0xFB, 0x04, 0x10, 0x05, 0x29, 0xEF, 0x8D, 0xFB, 0x04, 0x60, 0xAD, +0xFB, 0x04, 0x10, 0xFA, 0x09, 0x10, 0xD0, 0xF3, 0xAD, 0x68, 0xC0, 0x48, 0x09, 0x08, 0x8D, 0x68, +0xC0, 0x20, 0xDD, 0xFB, 0x68, 0x8D, 0x68, 0xC0, 0x60, 0xCE, 0x7B, 0x05, 0x10, 0x0B, 0xA5, 0x21, +0x8D, 0x7B, 0x05, 0xCE, 0x7B, 0x05, 0x20, 0x0B, 0xCB, 0x60, 0x9C, 0x7B, 0x05, 0xAD, 0xFB, 0x04, +0x10, 0x7F, 0x60, 0xA5, 0x22, 0x85, 0x25, 0x9C, 0x7B, 0x05, 0x4C, 0x97, 0xCD, 0xEE, 0x7B, 0x05, +0xAD, 0x7B, 0x05, 0xC5, 0x21, 0x90, 0x03, 0x20, 0xEA, 0xCA, 0x60, 0xA5, 0x22, 0xC5, 0x25, 0xB0, +0x1E, 0xC6, 0x25, 0x4C, 0x97, 0xCD, 0xAD, 0xFB, 0x04, 0x10, 0x02, 0x29, 0xFB, 0xA0, 0xFF, 0xD0, +0x09, 0xAD, 0xFB, 0x04, 0x10, 0x02, 0x09, 0x04, 0xA0, 0x7F, 0x8D, 0xFB, 0x04, 0x84, 0x32, 0x60, +0xA9, 0x81, 0x8F, 0x36, 0x01, 0xE1, 0x60, 0xB3, 0xBE, 0xC7, 0xD8, 0x00, 0x70, 0x1A, 0x36, 0xE9, +0x15, 0x20, 0x00, 0x8B, 0x9D, 0x00, 0x00, 0xE5, 0x6C, 0x83, 0xD9, 0xF2, 0x3B, 0xDF, 0xFC, 0x3F, +0x2F, 0x0A, 0x4A, 0x4A, 0xCA, 0xCA, 0x00, 0xCB, 0x4C, 0x4C, 0xCA, 0x4B, 0x4B, 0x00, 0x4C, 0x4C, +0x00, 0x00, 0x4C, 0x4B, 0x4B, 0x4C, 0x4A, 0x4C, 0x4C, 0x4A, 0x4C, 0xCB, 0x4B, 0xA0, 0x00, 0xF0, +0x15, 0xE6, 0x25, 0xA5, 0x25, 0x8D, 0xFB, 0x05, 0xC5, 0x23, 0xB0, 0x03, 0x4C, 0x9C, 0xCD, 0xCE, +0xFB, 0x05, 0xC6, 0x25, 0xA0, 0x01, 0xAD, 0x36, 0xC0, 0x48, 0x09, 0x80, 0x8D, 0x36, 0xC0, 0x20, +0x97, 0xCB, 0x68, 0x8D, 0x36, 0xC0, 0x60, 0xDA, 0x8C, 0x7B, 0x07, 0xA5, 0x21, 0x48, 0x2C, 0x1F, +0xC0, 0x10, 0x1B, 0x8D, 0x01, 0xC0, 0x4A, 0xAA, 0xA5, 0x20, 0x4A, 0xB8, 0x90, 0x02, 0xE2, 0x40, +0x2A, 0x45, 0x21, 0x4A, 0x70, 0x03, 0xB0, 0x01, 0xCA, 0x86, 0x21, 0xAD, 0x1F, 0xC0, 0x08, 0xA6, +0x22, 0x98, 0xD0, 0x03, 0xA6, 0x23, 0xCA, 0x8A, 0x20, 0x9C, 0xCD, 0xA5, 0x28, 0x85, 0x2A, 0xA5, +0x29, 0x85, 0x2B, 0xAD, 0x7B, 0x07, 0xF0, 0x32, 0xE8, 0xE4, 0x23, 0xB0, 0x32, 0x8A, 0x20, 0x9C, +0xCD, 0xA4, 0x21, 0x28, 0x08, 0x10, 0x1E, 0xAD, 0x55, 0xC0, 0x98, 0xF0, 0x07, 0xB1, 0x28, 0x91, +0x2A, 0x88, 0xD0, 0xF9, 0x70, 0x04, 0xB1, 0x28, 0x91, 0x2A, 0xAD, 0x54, 0xC0, 0xA4, 0x21, 0xB0, +0x04, 0xB1, 0x28, 0x91, 0x2A, 0x88, 0x10, 0xF9, 0x30, 0xC1, 0xCA, 0xE4, 0x22, 0x10, 0xCE, 0x28, +0x68, 0x85, 0x21, 0x20, 0x3C, 0xCC, 0x20, 0x97, 0xCD, 0xFA, 0x60, 0x20, 0x40, 0xCC, 0xA5, 0x25, +0x48, 0x10, 0x06, 0x20, 0x9C, 0xCD, 0x20, 0x3C, 0xCC, 0xE6, 0x25, 0xA5, 0x25, 0xC5, 0x23, 0x90, +0xF2, 0x68, 0x85, 0x25, 0x4C, 0x97, 0xCD, 0x20, 0xF3, 0xCA, 0x80, 0xDF, 0xA0, 0x00, 0xF0, 0x03, +0xAC, 0x7B, 0x05, 0xA5, 0x32, 0x29, 0x80, 0x09, 0x20, 0x2C, 0x1F, 0xC0, 0x30, 0x13, 0x91, 0x28, +0xC8, 0xC4, 0x21, 0x90, 0xF9, 0x60, 0xDA, 0xA2, 0xD8, 0xA0, 0x14, 0xA5, 0x32, 0x29, 0xA0, 0x80, +0x17, 0xDA, 0x48, 0x98, 0x48, 0x38, 0xE5, 0x21, 0xAA, 0x98, 0x4A, 0xA8, 0x68, 0x45, 0x20, 0x6A, +0xB0, 0x03, 0x10, 0x01, 0xC8, 0x68, 0xB0, 0x0B, 0x2C, 0x55, 0xC0, 0x91, 0x28, 0x2C, 0x54, 0xC0, +0xE8, 0xF0, 0x06, 0x91, 0x28, 0xC8, 0xE8, 0xD0, 0xEF, 0xFA, 0x38, 0x60, 0xAD, 0xFB, 0x04, 0x30, +0x48, 0x20, 0xCE, 0xCC, 0x2C, 0x1F, 0xC0, 0x10, 0x0D, 0x20, 0x2E, 0xCD, 0x90, 0x08, 0x2C, 0x1F, +0xC0, 0x30, 0x03, 0x20, 0x5F, 0xCD, 0xAD, 0x7B, 0x05, 0x18, 0x65, 0x20, 0x2C, 0x1F, 0xC0, 0x30, +0x06, 0xC9, 0x28, 0x90, 0x02, 0xA9, 0x27, 0x8D, 0x7B, 0x05, 0x85, 0x24, 0xA5, 0x25, 0x20, 0x64, +0xCA, 0x2C, 0x1F, 0xC0, 0x10, 0x05, 0x20, 0x0A, 0xCD, 0x80, 0x03, 0x20, 0x06, 0xCD, 0xA9, 0x00, +0x2C, 0x1A, 0xC0, 0x30, 0x02, 0xA9, 0x14, 0x85, 0x22, 0x60, 0xA9, 0x01, 0x0C, 0xFB, 0x04, 0x60, +0xA9, 0x01, 0x1C, 0xFB, 0x04, 0x60, 0xAD, 0xFB, 0x04, 0x30, 0x1A, 0x20, 0xCB, 0xCC, 0x20, 0x19, +0xCD, 0x20, 0xFD, 0xCC, 0xA9, 0xFD, 0x85, 0x39, 0xA9, 0x1B, 0x85, 0x38, 0x60, 0xA9, 0xFD, 0x85, +0x37, 0xA9, 0xF0, 0x85, 0x36, 0x60, 0xA9, 0x28, 0xD0, 0x02, 0xA9, 0x50, 0x85, 0x21, 0xA9, 0x18, +0x85, 0x23, 0x64, 0x22, 0x64, 0x20, 0xA9, 0x00, 0x60, 0x2C, 0x1F, 0xC0, 0x10, 0x03, 0x20, 0x91, +0xCC, 0x8D, 0x0E, 0xC0, 0xA9, 0xFF, 0x8D, 0xFB, 0x04, 0x8F, 0x34, 0x01, 0xE1, 0x60, 0xDA, 0xA2, +0x17, 0x8D, 0x01, 0xC0, 0x8A, 0x20, 0x64, 0xCA, 0xA0, 0x27, 0x84, 0x2A, 0x98, 0x4A, 0xB0, 0x03, +0x2C, 0x55, 0xC0, 0xA8, 0xB1, 0x28, 0x2C, 0x54, 0xC0, 0xA4, 0x2A, 0x91, 0x28, 0x88, 0x10, 0xEA, +0xCA, 0x30, 0x04, 0xE4, 0x22, 0xB0, 0xDD, 0x8D, 0x00, 0xC0, 0x8D, 0x0C, 0xC0, 0x80, 0x33, 0xDA, +0xA2, 0x17, 0x8A, 0x20, 0x64, 0xCA, 0xA0, 0x00, 0x8D, 0x01, 0xC0, 0xB1, 0x28, 0x84, 0x2A, 0x48, +0x98, 0x4A, 0xB0, 0x03, 0x8D, 0x55, 0xC0, 0xA8, 0x68, 0x91, 0x28, 0x8D, 0x54, 0xC0, 0xA4, 0x2A, +0xC8, 0xC0, 0x28, 0x90, 0xE6, 0x20, 0x56, 0xCC, 0xCA, 0x30, 0x04, 0xE4, 0x22, 0xB0, 0xD3, 0x8D, +0x0D, 0xC0, 0x20, 0x97, 0xCD, 0xFA, 0x60, 0xA5, 0x25, 0x8D, 0xFB, 0x05, 0x20, 0x64, 0xCA, 0xA5, +0x20, 0x2C, 0x1F, 0xC0, 0x10, 0x01, 0x4A, 0x18, 0x65, 0x28, 0x85, 0x28, 0x60, 0xC9, 0xE1, 0x90, +0x06, 0xC9, 0xFB, 0xB0, 0x02, 0x29, 0xDF, 0x60, 0x5A, 0x20, 0x78, 0xC9, 0xA5, 0x5A, 0xB1, 0x28, +0x2C, 0x1F, 0xC0, 0x10, 0x15, 0x8D, 0x01, 0xC0, 0x98, 0x45, 0x20, 0x6A, 0xB0, 0x04, 0xAD, 0x55, +0xC0, 0xC8, 0x98, 0x4A, 0xA8, 0xB1, 0x28, 0x2C, 0x54, 0xC0, 0x2C, 0x1E, 0xC0, 0x10, 0x06, 0xC9, +0x20, 0xB0, 0x02, 0x09, 0x40, 0x7A, 0x60, 0x48, 0x20, 0xED, 0xCD, 0x68, 0x60, 0x24, 0x32, 0x30, +0x02, 0x29, 0x7F, 0x48, 0x20, 0x78, 0xC9, 0x80, 0x01, 0x48, 0x29, 0xFF, 0x30, 0x15, 0xAD, 0xFB, +0x04, 0x6A, 0x68, 0x48, 0x90, 0x0D, 0x2C, 0x1E, 0xC0, 0x10, 0x08, 0x49, 0x40, 0x89, 0x60, 0xF0, +0x02, 0x49, 0x40, 0x2C, 0x1F, 0xC0, 0x10, 0x1B, 0x8D, 0x01, 0xC0, 0x5A, 0x48, 0x98, 0x45, 0x20, +0x4A, 0xB0, 0x04, 0xAD, 0x55, 0xC0, 0xC8, 0x98, 0x4A, 0xA8, 0x68, 0x91, 0x28, 0xAD, 0x54, 0xC0, +0x7A, 0x68, 0x60, 0x91, 0x28, 0x68, 0x60, 0x5A, 0x48, 0x20, 0xB8, 0xCD, 0x8D, 0x7B, 0x06, 0x29, +0x80, 0x49, 0xAB, 0x20, 0xF3, 0xCD, 0x68, 0x7A, 0x60, 0x5A, 0x48, 0xAC, 0x7B, 0x05, 0xAD, 0x7B, +0x06, 0x80, 0xF0, 0xAD, 0xFB, 0x04, 0x29, 0x10, 0xD0, 0xEE, 0x5A, 0x48, 0xAC, 0x7B, 0x05, 0x20, +0xBD, 0xCD, 0x49, 0x80, 0x20, 0xF9, 0xCD, 0x80, 0xDD, 0x20, 0x0A, 0xCD, 0xA9, 0xFF, 0x85, 0x32, +0xAD, 0xFB, 0x04, 0x29, 0x04, 0xF0, 0x02, 0x46, 0x32, 0xAD, 0x7B, 0x07, 0x85, 0x28, 0xAD, 0xFB, +0x07, 0x85, 0x29, 0xAD, 0xFB, 0x05, 0x85, 0x25, 0x60, 0x2C, 0x12, 0xC0, 0x10, 0x3A, 0xA9, 0x06, +0xC5, 0x06, 0xF0, 0x34, 0xA2, 0x03, 0x2C, 0x11, 0xC0, 0x30, 0x02, 0xA2, 0x0B, 0x85, 0x06, 0x2C, +0x80, 0xC0, 0xA5, 0x06, 0xC9, 0x06, 0xF0, 0x01, 0xE8, 0x2C, 0x81, 0xC0, 0x2C, 0x81, 0xC0, 0xA0, +0x00, 0xA9, 0xF8, 0x85, 0x37, 0x84, 0x36, 0xB1, 0x36, 0x91, 0x36, 0xC8, 0xD0, 0xF9, 0xE6, 0x37, +0xD0, 0xF5, 0xBD, 0x80, 0xC0, 0xBD, 0x80, 0xC0, 0x60, 0x48, 0xAF, 0x34, 0x01, 0xE1, 0xA8, 0xD0, +0x0B, 0x68, 0x5A, 0x20, 0xB8, 0xCD, 0x48, 0x49, 0x80, 0x4C, 0x43, 0xCE, 0x68, 0x20, 0xB8, 0xCD, +0x48, 0x8F, 0x35, 0x01, 0xE1, 0x98, 0xC8, 0xF0, 0x0E, 0x7A, 0x5A, 0x30, 0x0A, 0xAD, 0x1E, 0xC0, +0x09, 0x7F, 0x4A, 0x2F, 0x34, 0x01, 0xE1, 0x20, 0xF3, 0xCD, 0x68, 0x60, 0xEB, 0xAD, 0x36, 0xC0, +0x09, 0x80, 0x48, 0x48, 0x8D, 0x36, 0xC0, 0xEB, 0x48, 0xE6, 0x4E, 0xD0, 0x2A, 0xE6, 0x4F, 0xAF, +0x45, 0x01, 0xE1, 0x3A, 0x8F, 0x45, 0x01, 0xE1, 0x10, 0x1D, 0x20, 0xEA, 0xC3, 0xAF, 0x34, 0x01, +0xE1, 0xF0, 0x14, 0x5A, 0x20, 0xB8, 0xCD, 0x48, 0xAF, 0x35, 0x01, 0xE1, 0xA8, 0x68, 0x8F, 0x35, +0x01, 0xE1, 0x98, 0x20, 0xF3, 0xCD, 0x7A, 0x68, 0x20, 0x94, 0xCF, 0x08, 0x08, 0xEB, 0x68, 0x83, +0x03, 0xEB, 0x28, 0x10, 0x06, 0x20, 0xF3, 0xCD, 0x20, 0x74, 0xCF, 0xEB, 0x68, 0x29, 0x7F, 0x0F, +0x37, 0x01, 0xE1, 0x8D, 0x36, 0xC0, 0xEB, 0x28, 0x60, 0x20, 0x2A, 0xC8, 0xA9, 0x00, 0x8F, 0x34, +0x01, 0xE1, 0xA9, 0xF7, 0x1C, 0xFB, 0x04, 0x8D, 0x0F, 0xC0, 0x60, 0xAD, 0x00, 0xC0, 0x10, 0x04, +0x8D, 0x10, 0xC0, 0x60, 0x20, 0x94, 0xCF, 0x10, 0xFA, 0x90, 0xF0, 0x48, 0xDA, 0x5A, 0x18, 0xFB, +0x08, 0x38, 0x20, 0xE2, 0xCF, 0xF0, 0x48, 0x28, 0xFB, 0x7A, 0xFA, 0x68, 0xAF, 0x5A, 0x01, 0xE1, +0x09, 0x80, 0x38, 0x60, 0x48, 0xDA, 0x5A, 0x18, 0xFB, 0x08, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0xA2, +0x06, 0x06, 0x22, 0x00, 0x00, 0xE1, 0x68, 0xD0, 0x07, 0x28, 0xFB, 0x7A, 0xFA, 0x68, 0x80, 0x28, +0xE2, 0x30, 0xA9, 0x00, 0x8F, 0x45, 0x01, 0xE1, 0x18, 0x20, 0xE2, 0xCF, 0xF0, 0x11, 0x28, 0xFB, +0xAF, 0x58, 0x01, 0xE1, 0xC9, 0x0A, 0xF0, 0x15, 0x38, 0x7A, 0xFA, 0x68, 0xE2, 0x80, 0x60, 0x28, +0xFB, 0x38, 0x7A, 0xFA, 0x68, 0xC2, 0x80, 0x60, 0x2C, 0x00, 0xC0, 0x18, 0x60, 0x20, 0x7B, 0xCF, +0x80, 0xEF, 0xC2, 0x30, 0xF4, 0x00, 0x00, 0xF4, 0x28, 0x04, 0xF4, 0xE1, 0x00, 0xF4, 0x58, 0x01, +0xA2, 0x06, 0x0A, 0xB0, 0x03, 0xA2, 0x06, 0x0B, 0x22, 0x00, 0x00, 0xE1, 0x68, 0x60, 0x00, 0x00, +0x6F, 0xD8, 0x65, 0xD7, 0xF8, 0xDC, 0x94, 0xD9, 0xB1, 0xDB, 0x30, 0xF3, 0xD8, 0xDF, 0xE1, 0xDB, +0x8F, 0xF3, 0x98, 0xF3, 0xE4, 0xF1, 0xDD, 0xF1, 0xD4, 0xF1, 0x24, 0xF2, 0x31, 0xF2, 0x40, 0xF2, +0xD7, 0xF3, 0xE1, 0xF3, 0xE8, 0xF6, 0xFD, 0xF6, 0x68, 0xF7, 0x6E, 0xF7, 0xE6, 0xF7, 0x57, 0xFC, +0x20, 0xF7, 0x26, 0xF7, 0xF4, 0x03, 0x6C, 0xF2, 0x6E, 0xF2, 0x72, 0xF2, 0x76, 0xF2, 0x7F, 0xF2, +0x4E, 0xF2, 0x6A, 0xD9, 0x55, 0xF2, 0x85, 0xF2, 0xA5, 0xF2, 0xCA, 0xF2, 0x17, 0xF3, 0xF4, 0x03, +0xF4, 0x03, 0x61, 0xF2, 0x45, 0xDA, 0x3D, 0xD9, 0x11, 0xD9, 0xC8, 0xD9, 0x48, 0xD8, 0xF4, 0x03, +0x20, 0xD9, 0x6A, 0xD9, 0xDB, 0xD9, 0x6D, 0xD8, 0xEB, 0xD9, 0x83, 0xE7, 0xF4, 0x03, 0xF4, 0x03, +0x12, 0xE3, 0x7A, 0xE7, 0xD4, 0xDA, 0x95, 0xD8, 0xA4, 0xD6, 0x69, 0xD6, 0x9F, 0xDB, 0x48, 0xD6, +0x90, 0xEB, 0x23, 0xEC, 0xAF, 0xEB, 0x0A, 0x00, 0xDE, 0xE2, 0x12, 0xD4, 0xCD, 0xDF, 0xFF, 0xE2, +0x8D, 0xEE, 0xAE, 0xEF, 0x41, 0xE9, 0x09, 0xEF, 0xEA, 0xEF, 0xF1, 0xEF, 0x3A, 0xF0, 0x9E, 0xF0, +0x64, 0xE7, 0xD6, 0xE6, 0xC5, 0xE3, 0x07, 0xE7, 0xE5, 0xE6, 0x46, 0xE6, 0x5A, 0xE6, 0x86, 0xE6, +0x91, 0xE6, 0x79, 0xC0, 0xE7, 0x79, 0xA9, 0xE7, 0x7B, 0x81, 0xE9, 0x7B, 0x68, 0xEA, 0x7D, 0x96, +0xEE, 0x50, 0x54, 0xDF, 0x46, 0x4E, 0xDF, 0x7F, 0xCF, 0xEE, 0x7F, 0x97, 0xDE, 0x64, 0x64, 0xDF, +0x45, 0x4E, 0xC4, 0x46, 0x4F, 0xD2, 0x4E, 0x45, 0x58, 0xD4, 0x44, 0x41, 0x54, 0xC1, 0x49, 0x4E, +0x50, 0x55, 0xD4, 0x44, 0x45, 0xCC, 0x44, 0x49, 0xCD, 0x52, 0x45, 0x41, 0xC4, 0x47, 0xD2, 0x54, +0x45, 0x58, 0xD4, 0x50, 0x52, 0xA3, 0x49, 0x4E, 0xA3, 0x43, 0x41, 0x4C, 0xCC, 0x50, 0x4C, 0x4F, +0xD4, 0x48, 0x4C, 0x49, 0xCE, 0x56, 0x4C, 0x49, 0xCE, 0x48, 0x47, 0x52, 0xB2, 0x48, 0x47, 0xD2, +0x48, 0x43, 0x4F, 0x4C, 0x4F, 0x52, 0xBD, 0x48, 0x50, 0x4C, 0x4F, 0xD4, 0x44, 0x52, 0x41, 0xD7, +0x58, 0x44, 0x52, 0x41, 0xD7, 0x48, 0x54, 0x41, 0xC2, 0x48, 0x4F, 0x4D, 0xC5, 0x52, 0x4F, 0x54, +0xBD, 0x53, 0x43, 0x41, 0x4C, 0x45, 0xBD, 0x53, 0x48, 0x4C, 0x4F, 0x41, 0xC4, 0x54, 0x52, 0x41, +0x43, 0xC5, 0x4E, 0x4F, 0x54, 0x52, 0x41, 0x43, 0xC5, 0x4E, 0x4F, 0x52, 0x4D, 0x41, 0xCC, 0x49, +0x4E, 0x56, 0x45, 0x52, 0x53, 0xC5, 0x46, 0x4C, 0x41, 0x53, 0xC8, 0x43, 0x4F, 0x4C, 0x4F, 0x52, +0xBD, 0x50, 0x4F, 0xD0, 0x56, 0x54, 0x41, 0xC2, 0x48, 0x49, 0x4D, 0x45, 0x4D, 0xBA, 0x4C, 0x4F, +0x4D, 0x45, 0x4D, 0xBA, 0x4F, 0x4E, 0x45, 0x52, 0xD2, 0x52, 0x45, 0x53, 0x55, 0x4D, 0xC5, 0x52, +0x45, 0x43, 0x41, 0x4C, 0xCC, 0x53, 0x54, 0x4F, 0x52, 0xC5, 0x53, 0x50, 0x45, 0x45, 0x44, 0xBD, +0x4C, 0x45, 0xD4, 0x47, 0x4F, 0x54, 0xCF, 0x52, 0x55, 0xCE, 0x49, 0xC6, 0x52, 0x45, 0x53, 0x54, +0x4F, 0x52, 0xC5, 0xA6, 0x47, 0x4F, 0x53, 0x55, 0xC2, 0x52, 0x45, 0x54, 0x55, 0x52, 0xCE, 0x52, +0x45, 0xCD, 0x53, 0x54, 0x4F, 0xD0, 0x4F, 0xCE, 0x57, 0x41, 0x49, 0xD4, 0x4C, 0x4F, 0x41, 0xC4, +0x53, 0x41, 0x56, 0xC5, 0x44, 0x45, 0xC6, 0x50, 0x4F, 0x4B, 0xC5, 0x50, 0x52, 0x49, 0x4E, 0xD4, +0x43, 0x4F, 0x4E, 0xD4, 0x4C, 0x49, 0x53, 0xD4, 0x43, 0x4C, 0x45, 0x41, 0xD2, 0x47, 0x45, 0xD4, +0x4E, 0x45, 0xD7, 0x54, 0x41, 0x42, 0xA8, 0x54, 0xCF, 0x46, 0xCE, 0x53, 0x50, 0x43, 0xA8, 0x54, +0x48, 0x45, 0xCE, 0x41, 0xD4, 0x4E, 0x4F, 0xD4, 0x53, 0x54, 0x45, 0xD0, 0xAB, 0xAD, 0xAA, 0xAF, +0xDE, 0x41, 0x4E, 0xC4, 0x4F, 0xD2, 0xBE, 0xBD, 0xBC, 0x53, 0x47, 0xCE, 0x49, 0x4E, 0xD4, 0x41, +0x42, 0xD3, 0x55, 0x53, 0xD2, 0x46, 0x52, 0xC5, 0x53, 0x43, 0x52, 0x4E, 0xA8, 0x50, 0x44, 0xCC, +0x50, 0x4F, 0xD3, 0x53, 0x51, 0xD2, 0x52, 0x4E, 0xC4, 0x4C, 0x4F, 0xC7, 0x45, 0x58, 0xD0, 0x43, +0x4F, 0xD3, 0x53, 0x49, 0xCE, 0x54, 0x41, 0xCE, 0x41, 0x54, 0xCE, 0x50, 0x45, 0x45, 0xCB, 0x4C, +0x45, 0xCE, 0x53, 0x54, 0x52, 0xA4, 0x56, 0x41, 0xCC, 0x41, 0x53, 0xC3, 0x43, 0x48, 0x52, 0xA4, +0x4C, 0x45, 0x46, 0x54, 0xA4, 0x52, 0x49, 0x47, 0x48, 0x54, 0xA4, 0x4D, 0x49, 0x44, 0xA4, 0x00, +0x4E, 0x45, 0x58, 0x54, 0x20, 0x57, 0x49, 0x54, 0x48, 0x4F, 0x55, 0x54, 0x20, 0x46, 0x4F, 0xD2, +0x53, 0x59, 0x4E, 0x54, 0x41, 0xD8, 0x52, 0x45, 0x54, 0x55, 0x52, 0x4E, 0x20, 0x57, 0x49, 0x54, +0x48, 0x4F, 0x55, 0x54, 0x20, 0x47, 0x4F, 0x53, 0x55, 0xC2, 0x4F, 0x55, 0x54, 0x20, 0x4F, 0x46, +0x20, 0x44, 0x41, 0x54, 0xC1, 0x49, 0x4C, 0x4C, 0x45, 0x47, 0x41, 0x4C, 0x20, 0x51, 0x55, 0x41, +0x4E, 0x54, 0x49, 0x54, 0xD9, 0x4F, 0x56, 0x45, 0x52, 0x46, 0x4C, 0x4F, 0xD7, 0x4F, 0x55, 0x54, +0x20, 0x4F, 0x46, 0x20, 0x4D, 0x45, 0x4D, 0x4F, 0x52, 0xD9, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x27, +0x44, 0x20, 0x53, 0x54, 0x41, 0x54, 0x45, 0x4D, 0x45, 0x4E, 0xD4, 0x42, 0x41, 0x44, 0x20, 0x53, +0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0xD4, 0x52, 0x45, 0x44, 0x49, 0x4D, 0x27, 0x44, 0x20, +0x41, 0x52, 0x52, 0x41, 0xD9, 0x44, 0x49, 0x56, 0x49, 0x53, 0x49, 0x4F, 0x4E, 0x20, 0x42, 0x59, +0x20, 0x5A, 0x45, 0x52, 0xCF, 0x49, 0x4C, 0x4C, 0x45, 0x47, 0x41, 0x4C, 0x20, 0x44, 0x49, 0x52, +0x45, 0x43, 0xD4, 0x54, 0x59, 0x50, 0x45, 0x20, 0x4D, 0x49, 0x53, 0x4D, 0x41, 0x54, 0x43, 0xC8, +0x53, 0x54, 0x52, 0x49, 0x4E, 0x47, 0x20, 0x54, 0x4F, 0x4F, 0x20, 0x4C, 0x4F, 0x4E, 0xC7, 0x46, +0x4F, 0x52, 0x4D, 0x55, 0x4C, 0x41, 0x20, 0x54, 0x4F, 0x4F, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x4C, +0x45, 0xD8, 0x43, 0x41, 0x4E, 0x27, 0x54, 0x20, 0x43, 0x4F, 0x4E, 0x54, 0x49, 0x4E, 0x55, 0xC5, +0x55, 0x4E, 0x44, 0x45, 0x46, 0x27, 0x44, 0x20, 0x46, 0x55, 0x4E, 0x43, 0x54, 0x49, 0x4F, 0xCE, +0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x07, 0x00, 0x20, 0x49, 0x4E, 0x20, 0x00, 0x0D, 0x42, 0x52, +0x45, 0x41, 0x4B, 0x07, 0x00, 0xBA, 0xE8, 0xE8, 0xE8, 0xE8, 0xBD, 0x01, 0x01, 0xC9, 0x81, 0xD0, +0x21, 0xA5, 0x86, 0xD0, 0x0A, 0xBD, 0x02, 0x01, 0x85, 0x85, 0xBD, 0x03, 0x01, 0x85, 0x86, 0xDD, +0x03, 0x01, 0xD0, 0x07, 0xA5, 0x85, 0xDD, 0x02, 0x01, 0xF0, 0x07, 0x8A, 0x18, 0x69, 0x12, 0xAA, +0xD0, 0xD8, 0x60, 0x20, 0xE3, 0xD3, 0x85, 0x6D, 0x84, 0x6E, 0x38, 0xA5, 0x96, 0xE5, 0x9B, 0x85, +0x5E, 0xA8, 0xA5, 0x97, 0xE5, 0x9C, 0xAA, 0xE8, 0x98, 0xF0, 0x23, 0xA5, 0x96, 0x38, 0xE5, 0x5E, +0x85, 0x96, 0xB0, 0x03, 0xC6, 0x97, 0x38, 0xA5, 0x94, 0xE5, 0x5E, 0x85, 0x94, 0xB0, 0x08, 0xC6, +0x95, 0x90, 0x04, 0xB1, 0x96, 0x91, 0x94, 0x88, 0xD0, 0xF9, 0xB1, 0x96, 0x91, 0x94, 0xC6, 0x97, +0xC6, 0x95, 0xCA, 0xD0, 0xF2, 0x60, 0x0A, 0x69, 0x36, 0xB0, 0x35, 0x85, 0x5E, 0xBA, 0xE4, 0x5E, +0x90, 0x2E, 0x60, 0xC4, 0x70, 0x90, 0x28, 0xD0, 0x04, 0xC5, 0x6F, 0x90, 0x22, 0x48, 0xA2, 0x09, +0x98, 0x48, 0xB5, 0x93, 0xCA, 0x10, 0xFA, 0x20, 0x84, 0xE4, 0xA2, 0xF7, 0x68, 0x95, 0x9D, 0xE8, +0x30, 0xFA, 0x68, 0xA8, 0x68, 0xC4, 0x70, 0x90, 0x06, 0xD0, 0x05, 0xC5, 0x6F, 0xB0, 0x01, 0x60, +0xA2, 0x4D, 0x24, 0xD8, 0x10, 0x03, 0x4C, 0xE9, 0xF2, 0x20, 0xFB, 0xDA, 0x20, 0x5A, 0xDB, 0xBD, +0x60, 0xD2, 0x48, 0x20, 0x5C, 0xDB, 0xE8, 0x68, 0x10, 0xF5, 0x20, 0x83, 0xD6, 0xA9, 0x50, 0xA0, +0xD3, 0x20, 0x3A, 0xDB, 0xA4, 0x76, 0xC8, 0xF0, 0x03, 0x20, 0x19, 0xED, 0x20, 0xFB, 0xDA, 0xA2, +0xDD, 0x20, 0x2E, 0xD5, 0x86, 0xB8, 0x84, 0xB9, 0x46, 0xD8, 0x20, 0xB1, 0x00, 0xAA, 0xF0, 0xEC, +0xA2, 0xFF, 0x86, 0x76, 0x90, 0x06, 0x20, 0x59, 0xD5, 0x4C, 0x05, 0xD8, 0xA6, 0xAF, 0x86, 0x69, +0xA6, 0xB0, 0x86, 0x6A, 0x20, 0x0C, 0xDA, 0x20, 0x59, 0xD5, 0x84, 0x0F, 0x20, 0x1A, 0xD6, 0x90, +0x44, 0xA0, 0x01, 0xB1, 0x9B, 0x85, 0x5F, 0xA5, 0x69, 0x85, 0x5E, 0xA5, 0x9C, 0x85, 0x61, 0xA5, +0x9B, 0x88, 0xF1, 0x9B, 0x18, 0x65, 0x69, 0x85, 0x69, 0x85, 0x60, 0xA5, 0x6A, 0x69, 0xFF, 0x85, +0x6A, 0xE5, 0x9C, 0xAA, 0x38, 0xA5, 0x9B, 0xE5, 0x69, 0xA8, 0xB0, 0x03, 0xE8, 0xC6, 0x61, 0x18, +0x65, 0x5E, 0x90, 0x03, 0xC6, 0x5F, 0x18, 0xB1, 0x5E, 0x91, 0x60, 0xC8, 0xD0, 0xF9, 0xE6, 0x5F, +0xE6, 0x61, 0xCA, 0xD0, 0xF2, 0xAD, 0x00, 0x02, 0xF0, 0x38, 0xA5, 0x73, 0xA4, 0x74, 0x85, 0x6F, +0x84, 0x70, 0xA5, 0x69, 0x85, 0x96, 0x65, 0x0F, 0x85, 0x94, 0xA4, 0x6A, 0x84, 0x97, 0x90, 0x01, +0xC8, 0x84, 0x95, 0x20, 0x93, 0xD3, 0xA5, 0x50, 0xA4, 0x51, 0x8D, 0xFE, 0x01, 0x8C, 0xFF, 0x01, +0xA5, 0x6D, 0xA4, 0x6E, 0x85, 0x69, 0x84, 0x6A, 0xA4, 0x0F, 0xB9, 0xFB, 0x01, 0x88, 0x91, 0x9B, +0xD0, 0xF8, 0x20, 0x65, 0xD6, 0xA5, 0x67, 0xA4, 0x68, 0x85, 0x5E, 0x84, 0x5F, 0x18, 0xA0, 0x01, +0xB1, 0x5E, 0xD0, 0x0B, 0xA5, 0x69, 0x85, 0xAF, 0xA5, 0x6A, 0x85, 0xB0, 0x4C, 0x3C, 0xD4, 0xA0, +0x04, 0xC8, 0xB1, 0x5E, 0xD0, 0xFB, 0xC8, 0x98, 0x65, 0x5E, 0xAA, 0xA0, 0x00, 0x91, 0x5E, 0xA5, +0x5F, 0x69, 0x00, 0xC8, 0x91, 0x5E, 0x86, 0x5E, 0x85, 0x5F, 0x90, 0xD2, 0xA2, 0x80, 0x86, 0x33, +0x20, 0x6A, 0xFD, 0xE0, 0xEF, 0x90, 0x02, 0xA2, 0xEF, 0xA9, 0x00, 0x9D, 0x00, 0x02, 0x8A, 0xF0, +0x0B, 0xBD, 0xFF, 0x01, 0x29, 0x7F, 0x9D, 0xFF, 0x01, 0xCA, 0xD0, 0xF5, 0xA9, 0x00, 0xA2, 0xFF, +0xA0, 0x01, 0x60, 0x20, 0x0C, 0xFD, 0x29, 0x7F, 0x60, 0xA6, 0xB8, 0xCA, 0xA0, 0x04, 0x84, 0x13, +0x24, 0xD6, 0x10, 0x08, 0x68, 0x68, 0x20, 0x65, 0xD6, 0x4C, 0xD2, 0xD7, 0xE8, 0x20, 0xB5, 0xD8, +0x24, 0x13, 0x70, 0x04, 0xC9, 0x20, 0xF0, 0xF4, 0x85, 0x0E, 0xC9, 0x22, 0xF0, 0x74, 0x70, 0x4D, +0xC9, 0x3F, 0xD0, 0x04, 0xA9, 0xBA, 0xD0, 0x45, 0xC9, 0x30, 0x90, 0x04, 0xC9, 0x3C, 0x90, 0x3D, +0x84, 0xAD, 0xA9, 0xD0, 0x85, 0x9D, 0xA9, 0xCF, 0x85, 0x9E, 0xA0, 0x00, 0x84, 0x0F, 0x88, 0x86, +0xB8, 0xCA, 0xC8, 0xD0, 0x02, 0xE6, 0x9E, 0xE8, 0x20, 0xB5, 0xD8, 0xC9, 0x20, 0xF0, 0xF8, 0x38, +0xF1, 0x9D, 0xF0, 0xEE, 0xC9, 0x80, 0xD0, 0x41, 0x05, 0x0F, 0xC9, 0xC5, 0xD0, 0x0D, 0x20, 0xB0, +0xD8, 0xC9, 0x4E, 0xF0, 0x34, 0xC9, 0x4F, 0xF0, 0x30, 0xA9, 0xC5, 0xA4, 0xAD, 0xE8, 0xC8, 0x99, +0xFB, 0x01, 0xB9, 0xFB, 0x01, 0xF0, 0x39, 0x38, 0xE9, 0x3A, 0xF0, 0x04, 0xC9, 0x49, 0xD0, 0x02, +0x85, 0x13, 0x38, 0xE9, 0x78, 0xD0, 0x86, 0x85, 0x0E, 0x20, 0xB5, 0xD8, 0xF0, 0xDF, 0xC5, 0x0E, +0xF0, 0xDB, 0xC8, 0x99, 0xFB, 0x01, 0xE8, 0xD0, 0xF0, 0xA6, 0xB8, 0xE6, 0x0F, 0xB1, 0x9D, 0xC8, +0xD0, 0x02, 0xE6, 0x9E, 0x0A, 0x90, 0xF6, 0xB1, 0x9D, 0xD0, 0x9D, 0x20, 0xC3, 0xD8, 0x10, 0xBB, +0x99, 0xFD, 0x01, 0xC6, 0xB9, 0xA9, 0xFF, 0x85, 0xB8, 0x60, 0xA5, 0x67, 0xA6, 0x68, 0xA0, 0x01, +0x85, 0x9B, 0x86, 0x9C, 0xB1, 0x9B, 0xF0, 0x1F, 0xC8, 0xC8, 0xA5, 0x51, 0xD1, 0x9B, 0x90, 0x18, +0xF0, 0x03, 0x88, 0xD0, 0x09, 0xA5, 0x50, 0x88, 0xD1, 0x9B, 0x90, 0x0C, 0xF0, 0x0A, 0x88, 0xB1, +0x9B, 0xAA, 0x88, 0xB1, 0x9B, 0xB0, 0xD7, 0x18, 0x60, 0xD0, 0xFD, 0xA9, 0x00, 0x85, 0xD6, 0xA8, +0x91, 0x67, 0xC8, 0x91, 0x67, 0xA5, 0x67, 0x69, 0x02, 0x85, 0x69, 0x85, 0xAF, 0xA5, 0x68, 0x69, +0x00, 0x85, 0x6A, 0x85, 0xB0, 0x20, 0x97, 0xD6, 0xA9, 0x00, 0xD0, 0x2A, 0xA5, 0x73, 0xA4, 0x74, +0x85, 0x6F, 0x84, 0x70, 0xA5, 0x69, 0xA4, 0x6A, 0x85, 0x6B, 0x84, 0x6C, 0x85, 0x6D, 0x84, 0x6E, +0x20, 0x49, 0xD8, 0xA2, 0x55, 0x86, 0x52, 0x68, 0xA8, 0x68, 0xA2, 0xF8, 0x9A, 0x48, 0x98, 0x48, +0xA9, 0x00, 0x85, 0x7A, 0x85, 0x14, 0x60, 0x18, 0xA5, 0x67, 0x69, 0xFF, 0x85, 0xB8, 0xA5, 0x68, +0x69, 0xFF, 0x85, 0xB9, 0x60, 0x90, 0x0A, 0xF0, 0x08, 0xC9, 0xC9, 0xF0, 0x04, 0xC9, 0x2C, 0xD0, +0xE5, 0x20, 0x0C, 0xDA, 0x20, 0x1A, 0xD6, 0x20, 0xB7, 0x00, 0xF0, 0x10, 0xC9, 0xC9, 0xF0, 0x04, +0xC9, 0x2C, 0xD0, 0x84, 0x20, 0xB1, 0x00, 0x20, 0x0C, 0xDA, 0xD0, 0xCA, 0x68, 0x68, 0xA5, 0x50, +0x05, 0x51, 0xD0, 0x06, 0xA9, 0xFF, 0x85, 0x50, 0x85, 0x51, 0xA0, 0x01, 0xB1, 0x9B, 0xF0, 0x44, +0x20, 0x58, 0xD8, 0x20, 0xFB, 0xDA, 0xC8, 0xB1, 0x9B, 0xAA, 0xC8, 0xB1, 0x9B, 0xC5, 0x51, 0xD0, +0x04, 0xE4, 0x50, 0xF0, 0x02, 0xB0, 0x2D, 0x84, 0x85, 0x20, 0xD3, 0xD8, 0xA9, 0x20, 0xA4, 0x85, +0x29, 0x7F, 0x20, 0x5C, 0xDB, 0x20, 0xDD, 0xD8, 0xEA, 0x90, 0x07, 0x20, 0xFB, 0xDA, 0xA9, 0x05, +0x85, 0x24, 0xC8, 0xB1, 0x9B, 0xD0, 0x1D, 0xA8, 0xB1, 0x9B, 0xAA, 0xC8, 0xB1, 0x9B, 0x86, 0x9B, +0x85, 0x9C, 0xD0, 0xB6, 0xA9, 0x0D, 0x20, 0x5C, 0xDB, 0x4C, 0xD2, 0xD7, 0xC8, 0xD0, 0x02, 0xE6, +0x9E, 0xB1, 0x9D, 0x60, 0x10, 0xCC, 0x38, 0xE9, 0x7F, 0xAA, 0x84, 0x85, 0xA0, 0xD0, 0x84, 0x9D, +0xA0, 0xCF, 0x84, 0x9E, 0xA0, 0xFF, 0xCA, 0xF0, 0x07, 0x20, 0x2C, 0xD7, 0x10, 0xFB, 0x30, 0xF6, +0xA9, 0x20, 0x20, 0x5C, 0xDB, 0x20, 0x2C, 0xD7, 0x30, 0x05, 0x20, 0x5C, 0xDB, 0xD0, 0xF6, 0x20, +0x5C, 0xDB, 0xA9, 0x20, 0xD0, 0x98, 0xA9, 0x80, 0x85, 0x14, 0x20, 0x46, 0xDA, 0x20, 0x65, 0xD3, +0xD0, 0x05, 0x8A, 0x69, 0x0F, 0xAA, 0x9A, 0x68, 0x68, 0xA9, 0x09, 0x20, 0xD6, 0xD3, 0x20, 0xA3, +0xD9, 0x18, 0x98, 0x65, 0xB8, 0x48, 0xA5, 0xB9, 0x69, 0x00, 0x48, 0xA5, 0x76, 0x48, 0xA5, 0x75, +0x48, 0xA9, 0xC1, 0x20, 0xC0, 0xDE, 0x20, 0x6A, 0xDD, 0x20, 0x67, 0xDD, 0xA5, 0xA2, 0x09, 0x7F, +0x25, 0x9E, 0x85, 0x9E, 0xA9, 0xAF, 0xA0, 0xD7, 0x85, 0x5E, 0x84, 0x5F, 0x4C, 0x20, 0xDE, 0xA9, +0x13, 0xA0, 0xE9, 0x20, 0xF9, 0xEA, 0x20, 0xB7, 0x00, 0xC9, 0xC7, 0xD0, 0x06, 0x20, 0xB1, 0x00, +0x20, 0x67, 0xDD, 0x20, 0x82, 0xEB, 0x20, 0x15, 0xDE, 0xA5, 0x86, 0x48, 0xA5, 0x85, 0x48, 0xA9, +0x81, 0x48, 0xBA, 0x86, 0xF8, 0x20, 0x58, 0xD8, 0xA5, 0xB8, 0xA4, 0xB9, 0xA6, 0x76, 0xE8, 0xF0, +0x04, 0x85, 0x79, 0x84, 0x7A, 0xA0, 0x00, 0xB1, 0xB8, 0xD0, 0x57, 0xA0, 0x02, 0xB1, 0xB8, 0x18, +0xF0, 0x34, 0xC8, 0xB1, 0xB8, 0x85, 0x75, 0xC8, 0xB1, 0xB8, 0x85, 0x76, 0x98, 0x65, 0xB8, 0x85, +0xB8, 0x90, 0x02, 0xE6, 0xB9, 0x24, 0xF2, 0x10, 0x14, 0xA6, 0x76, 0xE8, 0xF0, 0x0F, 0xA9, 0x23, +0x20, 0x5C, 0xDB, 0xA6, 0x75, 0xA5, 0x76, 0x20, 0x24, 0xED, 0x20, 0x57, 0xDB, 0x20, 0xB1, 0x00, +0x20, 0x28, 0xD8, 0x4C, 0xD2, 0xD7, 0xF0, 0x62, 0xF0, 0x2D, 0xE9, 0x80, 0x90, 0x11, 0xC9, 0x40, +0xB0, 0x14, 0x0A, 0xA8, 0xB9, 0x01, 0xD0, 0x48, 0xB9, 0x00, 0xD0, 0x48, 0x4C, 0xB1, 0x00, 0x4C, +0x46, 0xDA, 0xC9, 0x3A, 0xF0, 0xBF, 0x4C, 0xC9, 0xDE, 0x38, 0xA5, 0x67, 0xE9, 0x01, 0xA4, 0x68, +0xB0, 0x01, 0x88, 0x85, 0x7D, 0x84, 0x7E, 0x60, 0xAD, 0x00, 0xC0, 0xC9, 0x83, 0xF0, 0x01, 0x60, +0x20, 0x53, 0xD5, 0xA2, 0xFF, 0x24, 0xD8, 0x10, 0x03, 0x4C, 0xE9, 0xF2, 0xC9, 0x03, 0xB0, 0x01, +0x18, 0xD0, 0x3C, 0xA5, 0xB8, 0xA4, 0xB9, 0xA6, 0x76, 0xE8, 0xF0, 0x0C, 0x85, 0x79, 0x84, 0x7A, +0xA5, 0x75, 0xA4, 0x76, 0x85, 0x77, 0x84, 0x78, 0x68, 0x68, 0xA9, 0x5D, 0xA0, 0xD3, 0x90, 0x03, +0x4C, 0x31, 0xD4, 0x4C, 0x3C, 0xD4, 0xD0, 0x17, 0xA2, 0xD2, 0xA4, 0x7A, 0xD0, 0x03, 0x4C, 0x12, +0xD4, 0xA5, 0x79, 0x85, 0xB8, 0x84, 0xB9, 0xA5, 0x77, 0xA4, 0x78, 0x85, 0x75, 0x84, 0x76, 0x60, +0xBD, 0x01, 0x02, 0x10, 0x11, 0xA5, 0x0E, 0xF0, 0x16, 0xC9, 0x22, 0xF0, 0x12, 0xA5, 0x13, 0xC9, +0x49, 0xF0, 0x0C, 0xBD, 0x00, 0x02, 0x08, 0xC9, 0x61, 0x90, 0x02, 0x29, 0x5F, 0x28, 0x60, 0xBD, +0x00, 0x02, 0x60, 0x48, 0xA9, 0x20, 0x20, 0x5C, 0xDB, 0x68, 0x4C, 0x24, 0xED, 0xA5, 0x24, 0xC9, +0x21, 0x2C, 0x1F, 0xC0, 0x10, 0x05, 0xAD, 0x7B, 0x05, 0xC9, 0x49, 0x60, 0xAD, 0x50, 0xC0, 0x20, +0xF7, 0xD8, 0xA9, 0x14, 0x4C, 0x4B, 0xFB, 0xA0, 0x27, 0x84, 0x2D, 0x20, 0xCB, 0xF3, 0xA9, 0x27, +0x90, 0x01, 0x2A, 0xA8, 0xA9, 0x00, 0x85, 0x30, 0x20, 0x8B, 0xF7, 0x88, 0x10, 0xF6, 0x60, 0x00, +0x00, 0x00, 0x08, 0xC6, 0x76, 0x28, 0xD0, 0x03, 0x4C, 0x65, 0xD6, 0x20, 0x6C, 0xD6, 0x4C, 0x35, +0xD9, 0xA9, 0x03, 0x20, 0xD6, 0xD3, 0xA5, 0xB9, 0x48, 0xA5, 0xB8, 0x48, 0xA5, 0x76, 0x48, 0xA5, +0x75, 0x48, 0xA9, 0xB0, 0x48, 0x20, 0xB7, 0x00, 0x20, 0x3E, 0xD9, 0x4C, 0xD2, 0xD7, 0x20, 0x0C, +0xDA, 0x20, 0xA6, 0xD9, 0xA5, 0x76, 0xC5, 0x51, 0xB0, 0x0B, 0x98, 0x38, 0x65, 0xB8, 0xA6, 0xB9, +0x90, 0x07, 0xE8, 0xB0, 0x04, 0xA5, 0x67, 0xA6, 0x68, 0x20, 0x1E, 0xD6, 0x90, 0x1E, 0xA5, 0x9B, +0xE9, 0x01, 0x85, 0xB8, 0xA5, 0x9C, 0xE9, 0x00, 0x85, 0xB9, 0x60, 0xD0, 0xFD, 0xA9, 0xFF, 0x85, +0x85, 0x20, 0x65, 0xD3, 0x9A, 0xC9, 0xB0, 0xF0, 0x0B, 0xA2, 0x16, 0x2C, 0xA2, 0x5A, 0x4C, 0x12, +0xD4, 0x4C, 0xC9, 0xDE, 0x68, 0x68, 0xC0, 0x42, 0xF0, 0x3B, 0x85, 0x75, 0x68, 0x85, 0x76, 0x68, +0x85, 0xB8, 0x68, 0x85, 0xB9, 0x20, 0xA3, 0xD9, 0x98, 0x18, 0x65, 0xB8, 0x85, 0xB8, 0x90, 0x02, +0xE6, 0xB9, 0x60, 0xA2, 0x3A, 0x2C, 0xA2, 0x00, 0x86, 0x0D, 0xA0, 0x00, 0x84, 0x0E, 0xA5, 0x0E, +0xA6, 0x0D, 0x85, 0x0D, 0x86, 0x0E, 0xB1, 0xB8, 0xF0, 0xE8, 0xC5, 0x0E, 0xF0, 0xE4, 0xC8, 0xC9, +0x22, 0xD0, 0xF3, 0xF0, 0xE9, 0x68, 0x68, 0x68, 0x60, 0x20, 0x7B, 0xDD, 0x20, 0xB7, 0x00, 0xC9, +0xAB, 0xF0, 0x05, 0xA9, 0xC4, 0x20, 0xC0, 0xDE, 0xA5, 0x9D, 0xD0, 0x05, 0x20, 0xA6, 0xD9, 0xF0, +0xB7, 0x20, 0xB7, 0x00, 0xB0, 0x03, 0x4C, 0x3E, 0xD9, 0x4C, 0x28, 0xD8, 0x20, 0xF8, 0xE6, 0x48, +0xC9, 0xB0, 0xF0, 0x04, 0xC9, 0xAB, 0xD0, 0x89, 0xC6, 0xA1, 0xD0, 0x04, 0x68, 0x4C, 0x2A, 0xD8, +0x20, 0xB1, 0x00, 0x20, 0x0C, 0xDA, 0xC9, 0x2C, 0xF0, 0xEE, 0x68, 0x60, 0xA2, 0x00, 0x86, 0x50, +0x86, 0x51, 0xB0, 0xF7, 0xE9, 0x2F, 0x85, 0x0D, 0xA5, 0x51, 0x85, 0x5E, 0xC9, 0x19, 0xB0, 0xD4, +0xA5, 0x50, 0x0A, 0x26, 0x5E, 0x0A, 0x26, 0x5E, 0x65, 0x50, 0x85, 0x50, 0xA5, 0x5E, 0x65, 0x51, +0x85, 0x51, 0x06, 0x50, 0x26, 0x51, 0xA5, 0x50, 0x65, 0x0D, 0x85, 0x50, 0x90, 0x02, 0xE6, 0x51, +0x20, 0xB1, 0x00, 0x4C, 0x12, 0xDA, 0x20, 0xE3, 0xDF, 0x85, 0x85, 0x84, 0x86, 0xA9, 0xD0, 0x20, +0xC0, 0xDE, 0xA5, 0x12, 0x48, 0xA5, 0x11, 0x48, 0x20, 0x7B, 0xDD, 0x68, 0x2A, 0x20, 0x6D, 0xDD, +0xD0, 0x18, 0x68, 0x10, 0x12, 0x20, 0x72, 0xEB, 0x20, 0x0C, 0xE1, 0xA0, 0x00, 0xA5, 0xA0, 0x91, +0x85, 0xC8, 0xA5, 0xA1, 0x91, 0x85, 0x60, 0x4C, 0x27, 0xEB, 0x68, 0xA0, 0x02, 0xB1, 0xA0, 0xC5, +0x70, 0x90, 0x17, 0xD0, 0x07, 0x88, 0xB1, 0xA0, 0xC5, 0x6F, 0x90, 0x0E, 0xA4, 0xA1, 0xC4, 0x6A, +0x90, 0x08, 0xD0, 0x0D, 0xA5, 0xA0, 0xC5, 0x69, 0xB0, 0x07, 0xA5, 0xA0, 0xA4, 0xA1, 0x4C, 0xB7, +0xDA, 0xA0, 0x00, 0xB1, 0xA0, 0x20, 0xD5, 0xE3, 0xA5, 0x8C, 0xA4, 0x8D, 0x85, 0xAB, 0x84, 0xAC, +0x20, 0xD4, 0xE5, 0xA9, 0x9D, 0xA0, 0x00, 0x85, 0x8C, 0x84, 0x8D, 0x20, 0x35, 0xE6, 0xA0, 0x00, +0xB1, 0x8C, 0x91, 0x85, 0xC8, 0xB1, 0x8C, 0x91, 0x85, 0xC8, 0xB1, 0x8C, 0x91, 0x85, 0x60, 0x20, +0x3D, 0xDB, 0x20, 0xB7, 0x00, 0xF0, 0x24, 0xF0, 0x29, 0xC9, 0xC0, 0xF0, 0x3C, 0xC9, 0xC3, 0x18, +0xF0, 0x37, 0xC9, 0x2C, 0x18, 0xF0, 0x1C, 0xC9, 0x3B, 0xF0, 0x44, 0x20, 0x7B, 0xDD, 0x24, 0x11, +0x30, 0xDD, 0x20, 0x34, 0xED, 0x20, 0xE7, 0xE3, 0x4C, 0xCF, 0xDA, 0xA9, 0x0D, 0x20, 0x5C, 0xDB, +0x49, 0xFF, 0x60, 0x20, 0xDD, 0xD8, 0x30, 0x09, 0xC9, 0x18, 0x90, 0x05, 0x20, 0xFB, 0xDA, 0xD0, +0x1E, 0x69, 0x10, 0x29, 0xF0, 0xAA, 0x38, 0xB0, 0x0C, 0x08, 0x20, 0xF5, 0xE6, 0xC9, 0x29, 0xD0, +0x62, 0x28, 0x90, 0x07, 0xCA, 0x20, 0xCB, 0xF7, 0x90, 0x05, 0xAA, 0xE8, 0xCA, 0xD0, 0x06, 0x20, +0xB1, 0x00, 0x4C, 0xD7, 0xDA, 0x20, 0x57, 0xDB, 0xD0, 0xF2, 0x20, 0xE7, 0xE3, 0x20, 0x00, 0xE6, +0xAA, 0xA0, 0x00, 0xE8, 0xCA, 0xF0, 0xBB, 0xB1, 0x5E, 0x20, 0x5C, 0xDB, 0xC8, 0xC9, 0x0D, 0xD0, +0xF3, 0x20, 0x00, 0xDB, 0x4C, 0x44, 0xDB, 0xA9, 0x20, 0x2C, 0xA9, 0x3F, 0x09, 0x80, 0xC9, 0xA0, +0x90, 0x02, 0x05, 0xF3, 0x20, 0xED, 0xFD, 0x29, 0x7F, 0x48, 0xA5, 0xF1, 0x20, 0xA8, 0xFC, 0x68, +0x60, 0xA5, 0x15, 0xF0, 0x12, 0x30, 0x04, 0xA0, 0xFF, 0xD0, 0x04, 0xA5, 0x7B, 0xA4, 0x7C, 0x85, +0x75, 0x84, 0x76, 0x4C, 0xC9, 0xDE, 0x68, 0x24, 0xD8, 0x10, 0x05, 0xA2, 0xFE, 0x4C, 0xE9, 0xF2, +0xA9, 0xEF, 0xA0, 0xDC, 0x20, 0x3A, 0xDB, 0xA5, 0x79, 0xA4, 0x7A, 0x85, 0xB8, 0x84, 0xB9, 0x60, +0x20, 0x06, 0xE3, 0xA2, 0x01, 0xA0, 0x02, 0xA9, 0x00, 0x8D, 0x01, 0x02, 0xA9, 0x40, 0x20, 0xEB, +0xDB, 0x60, 0xC9, 0x22, 0xD0, 0x0E, 0x20, 0x81, 0xDE, 0xA9, 0x3B, 0x20, 0xC0, 0xDE, 0x20, 0x3D, +0xDB, 0x4C, 0xC7, 0xDB, 0x20, 0x5A, 0xDB, 0x20, 0x06, 0xE3, 0xA9, 0x2C, 0x8D, 0xFF, 0x01, 0x20, +0x2C, 0xD5, 0xAD, 0x00, 0x02, 0xC9, 0x03, 0xD0, 0x10, 0x4C, 0x63, 0xD8, 0x20, 0x5A, 0xDB, 0x4C, +0x2C, 0xD5, 0xA6, 0x7D, 0xA4, 0x7E, 0xA9, 0x98, 0x2C, 0xA9, 0x00, 0x85, 0x15, 0x86, 0x7F, 0x84, +0x80, 0x20, 0xE3, 0xDF, 0x85, 0x85, 0x84, 0x86, 0xA5, 0xB8, 0xA4, 0xB9, 0x85, 0x87, 0x84, 0x88, +0xA6, 0x7F, 0xA4, 0x80, 0x86, 0xB8, 0x84, 0xB9, 0x20, 0xB7, 0x00, 0xD0, 0x1E, 0x24, 0x15, 0x50, +0x0E, 0x20, 0x0C, 0xFD, 0x29, 0x7F, 0x8D, 0x00, 0x02, 0xA2, 0xFF, 0xA0, 0x01, 0xD0, 0x08, 0x30, +0x7F, 0x20, 0x5A, 0xDB, 0x20, 0xDC, 0xDB, 0x86, 0xB8, 0x84, 0xB9, 0x20, 0xB1, 0x00, 0x24, 0x11, +0x10, 0x31, 0x24, 0x15, 0x50, 0x09, 0xE8, 0x86, 0xB8, 0xA9, 0x00, 0x85, 0x0D, 0xF0, 0x0C, 0x85, +0x0D, 0xC9, 0x22, 0xF0, 0x07, 0xA9, 0x3A, 0x85, 0x0D, 0xA9, 0x2C, 0x18, 0x85, 0x0E, 0xA5, 0xB8, +0xA4, 0xB9, 0x69, 0x00, 0x90, 0x01, 0xC8, 0x20, 0xED, 0xE3, 0x20, 0x3D, 0xE7, 0x20, 0x7B, 0xDA, +0x4C, 0x72, 0xDC, 0x48, 0xAD, 0x00, 0x02, 0xF0, 0x30, 0x68, 0x20, 0x4A, 0xEC, 0xA5, 0x12, 0x20, +0x63, 0xDA, 0x20, 0xB7, 0x00, 0xF0, 0x07, 0xC9, 0x2C, 0xF0, 0x03, 0x4C, 0x71, 0xDB, 0xA5, 0xB8, +0xA4, 0xB9, 0x85, 0x7F, 0x84, 0x80, 0xA5, 0x87, 0xA4, 0x88, 0x85, 0xB8, 0x84, 0xB9, 0x20, 0xB7, +0x00, 0xF0, 0x33, 0x20, 0xBE, 0xDE, 0x4C, 0xF1, 0xDB, 0xA5, 0x15, 0xD0, 0xCC, 0x4C, 0x86, 0xDB, +0x20, 0xA3, 0xD9, 0xC8, 0xAA, 0xD0, 0x12, 0xA2, 0x2A, 0xC8, 0xB1, 0xB8, 0xF0, 0x5F, 0xC8, 0xB1, +0xB8, 0x85, 0x7B, 0xC8, 0xB1, 0xB8, 0xC8, 0x85, 0x7C, 0xB1, 0xB8, 0xAA, 0x20, 0x98, 0xD9, 0xE0, +0x83, 0xD0, 0xDD, 0x4C, 0x2B, 0xDC, 0xA5, 0x7F, 0xA4, 0x80, 0xA6, 0x15, 0x10, 0x03, 0x4C, 0x53, +0xD8, 0xA0, 0x00, 0xB1, 0x7F, 0xF0, 0x07, 0xA9, 0xDF, 0xA0, 0xDC, 0x4C, 0x3A, 0xDB, 0x60, 0x3F, +0x45, 0x58, 0x54, 0x52, 0x41, 0x20, 0x49, 0x47, 0x4E, 0x4F, 0x52, 0x45, 0x44, 0x0D, 0x00, 0x3F, +0x52, 0x45, 0x45, 0x4E, 0x54, 0x45, 0x52, 0x0D, 0x00, 0xD0, 0x04, 0xA0, 0x00, 0xF0, 0x03, 0x20, +0xE3, 0xDF, 0x85, 0x85, 0x84, 0x86, 0x20, 0x65, 0xD3, 0xF0, 0x04, 0xA2, 0x00, 0xF0, 0x69, 0x9A, +0xE8, 0xE8, 0xE8, 0xE8, 0x8A, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0x86, 0x60, 0xA0, 0x01, 0x20, +0xF9, 0xEA, 0xBA, 0xBD, 0x09, 0x01, 0x85, 0xA2, 0xA5, 0x85, 0xA4, 0x86, 0x20, 0xBE, 0xE7, 0x20, +0x27, 0xEB, 0xA0, 0x01, 0x20, 0xB4, 0xEB, 0xBA, 0x38, 0xFD, 0x09, 0x01, 0xF0, 0x17, 0xBD, 0x0F, +0x01, 0x85, 0x75, 0xBD, 0x10, 0x01, 0x85, 0x76, 0xBD, 0x12, 0x01, 0x85, 0xB8, 0xBD, 0x11, 0x01, +0x85, 0xB9, 0x4C, 0xD2, 0xD7, 0x8A, 0x69, 0x11, 0xAA, 0x9A, 0x20, 0xB7, 0x00, 0xC9, 0x2C, 0xD0, +0xF1, 0x20, 0xB1, 0x00, 0x20, 0xFF, 0xDC, 0x20, 0x7B, 0xDD, 0x18, 0x24, 0x38, 0x24, 0x11, 0x30, +0x03, 0xB0, 0x03, 0x60, 0xB0, 0xFD, 0xA2, 0xA3, 0x4C, 0x12, 0xD4, 0xA6, 0xB8, 0xD0, 0x02, 0xC6, +0xB9, 0xC6, 0xB8, 0xA2, 0x00, 0x24, 0x48, 0x8A, 0x48, 0xA9, 0x01, 0x20, 0xD6, 0xD3, 0x20, 0x60, +0xDE, 0xA9, 0x00, 0x85, 0x89, 0x20, 0xB7, 0x00, 0x38, 0xE9, 0xCF, 0x90, 0x17, 0xC9, 0x03, 0xB0, +0x13, 0xC9, 0x01, 0x2A, 0x49, 0x01, 0x45, 0x89, 0xC5, 0x89, 0x90, 0x61, 0x85, 0x89, 0x20, 0xB1, +0x00, 0x4C, 0x98, 0xDD, 0xA6, 0x89, 0xD0, 0x2C, 0xB0, 0x7B, 0x69, 0x07, 0x90, 0x77, 0x65, 0x11, +0xD0, 0x03, 0x4C, 0x97, 0xE5, 0x69, 0xFF, 0x85, 0x5E, 0x0A, 0x65, 0x5E, 0xA8, 0x68, 0xD9, 0xB2, +0xD0, 0xB0, 0x67, 0x20, 0x6A, 0xDD, 0x48, 0x20, 0xFD, 0xDD, 0x68, 0xA4, 0x87, 0x10, 0x17, 0xAA, +0xF0, 0x56, 0xD0, 0x5F, 0x46, 0x11, 0x8A, 0x2A, 0xA6, 0xB8, 0xD0, 0x02, 0xC6, 0xB9, 0xC6, 0xB8, +0xA0, 0x1B, 0x85, 0x89, 0xD0, 0xD7, 0xD9, 0xB2, 0xD0, 0xB0, 0x48, 0x90, 0xD9, 0xB9, 0xB4, 0xD0, +0x48, 0xB9, 0xB3, 0xD0, 0x48, 0x20, 0x10, 0xDE, 0xA5, 0x89, 0x4C, 0x86, 0xDD, 0x4C, 0xC9, 0xDE, +0xA5, 0xA2, 0xBE, 0xB2, 0xD0, 0xA8, 0x68, 0x85, 0x5E, 0xE6, 0x5E, 0x68, 0x85, 0x5F, 0x98, 0x48, +0x20, 0x72, 0xEB, 0xA5, 0xA1, 0x48, 0xA5, 0xA0, 0x48, 0xA5, 0x9F, 0x48, 0xA5, 0x9E, 0x48, 0xA5, +0x9D, 0x48, 0x6C, 0x5E, 0x00, 0xA0, 0xFF, 0x68, 0xF0, 0x23, 0xC9, 0x64, 0xF0, 0x03, 0x20, 0x6A, +0xDD, 0x84, 0x87, 0x68, 0x4A, 0x85, 0x16, 0x68, 0x85, 0xA5, 0x68, 0x85, 0xA6, 0x68, 0x85, 0xA7, +0x68, 0x85, 0xA8, 0x68, 0x85, 0xA9, 0x68, 0x85, 0xAA, 0x45, 0xA2, 0x85, 0xAB, 0xA5, 0x9D, 0x60, +0xA9, 0x00, 0x85, 0x11, 0x20, 0xB1, 0x00, 0xB0, 0x03, 0x4C, 0x4A, 0xEC, 0x20, 0x7D, 0xE0, 0xB0, +0x64, 0xC9, 0x2E, 0xF0, 0xF4, 0xC9, 0xC9, 0xF0, 0x55, 0xC9, 0xC8, 0xF0, 0xE7, 0xC9, 0x22, 0xD0, +0x0F, 0xA5, 0xB8, 0xA4, 0xB9, 0x69, 0x00, 0x90, 0x01, 0xC8, 0x20, 0xE7, 0xE3, 0x4C, 0x3D, 0xE7, +0xC9, 0xC6, 0xD0, 0x10, 0xA0, 0x18, 0xD0, 0x38, 0xA5, 0x9D, 0xD0, 0x03, 0xA0, 0x01, 0x2C, 0xA0, +0x00, 0x4C, 0x01, 0xE3, 0xC9, 0xC2, 0xD0, 0x03, 0x4C, 0x54, 0xE3, 0xC9, 0xD2, 0x90, 0x03, 0x4C, +0x0C, 0xDF, 0x20, 0xBB, 0xDE, 0x20, 0x7B, 0xDD, 0xA9, 0x29, 0x2C, 0xA9, 0x28, 0x2C, 0xA9, 0x2C, +0xA0, 0x00, 0xD1, 0xB8, 0xD0, 0x03, 0x4C, 0xB1, 0x00, 0xA2, 0x10, 0x4C, 0x12, 0xD4, 0xA0, 0x15, +0x68, 0x68, 0x4C, 0xD7, 0xDD, 0x20, 0xE3, 0xDF, 0x85, 0xA0, 0x84, 0xA1, 0xA6, 0x11, 0xF0, 0x05, +0xA2, 0x00, 0x86, 0xAC, 0x60, 0xA6, 0x12, 0x10, 0x0D, 0xA0, 0x00, 0xB1, 0xA0, 0xAA, 0xC8, 0xB1, +0xA0, 0xA8, 0x8A, 0x4C, 0xF2, 0xE2, 0x4C, 0xF9, 0xEA, 0x20, 0xB1, 0x00, 0x20, 0xEC, 0xF1, 0x8A, +0xA4, 0xF0, 0x20, 0xA6, 0xF7, 0xA8, 0x20, 0x01, 0xE3, 0x4C, 0xB8, 0xDE, 0xC9, 0xD7, 0xF0, 0xE9, +0x0A, 0x48, 0xAA, 0x20, 0xB1, 0x00, 0xE0, 0xCF, 0x90, 0x20, 0x20, 0xBB, 0xDE, 0x20, 0x7B, 0xDD, +0x20, 0xBE, 0xDE, 0x20, 0x6C, 0xDD, 0x68, 0xAA, 0xA5, 0xA1, 0x48, 0xA5, 0xA0, 0x48, 0x8A, 0x48, +0x20, 0xF8, 0xE6, 0x68, 0xA8, 0x8A, 0x48, 0x4C, 0x3F, 0xDF, 0x20, 0xB2, 0xDE, 0x68, 0xA8, 0xB9, +0xDC, 0xCF, 0x85, 0x91, 0xB9, 0xDD, 0xCF, 0x85, 0x92, 0x20, 0x90, 0x00, 0x4C, 0x6A, 0xDD, 0xA5, +0xA5, 0x05, 0x9D, 0xD0, 0x0B, 0xA5, 0xA5, 0xF0, 0x04, 0xA5, 0x9D, 0xD0, 0x03, 0xA0, 0x00, 0x2C, +0xA0, 0x01, 0x4C, 0x01, 0xE3, 0x20, 0x6D, 0xDD, 0xB0, 0x13, 0xA5, 0xAA, 0x09, 0x7F, 0x25, 0xA6, +0x85, 0xA6, 0xA9, 0xA5, 0xA0, 0x00, 0x20, 0xB2, 0xEB, 0xAA, 0x4C, 0xB0, 0xDF, 0xA9, 0x00, 0x85, +0x11, 0xC6, 0x89, 0x20, 0x00, 0xE6, 0x85, 0x9D, 0x86, 0x9E, 0x84, 0x9F, 0xA5, 0xA8, 0xA4, 0xA9, +0x20, 0x04, 0xE6, 0x86, 0xA8, 0x84, 0xA9, 0xAA, 0x38, 0xE5, 0x9D, 0xF0, 0x08, 0xA9, 0x01, 0x90, +0x04, 0xA6, 0x9D, 0xA9, 0xFF, 0x85, 0xA2, 0xA0, 0xFF, 0xE8, 0xC8, 0xCA, 0xD0, 0x07, 0xA6, 0xA2, +0x30, 0x0F, 0x18, 0x90, 0x0C, 0xB1, 0xA8, 0xD1, 0x9E, 0xF0, 0xEF, 0xA2, 0xFF, 0xB0, 0x02, 0xA2, +0x01, 0xE8, 0x8A, 0x2A, 0x25, 0x16, 0xF0, 0x02, 0xA9, 0x01, 0x4C, 0x93, 0xEB, 0x20, 0xFB, 0xE6, +0x20, 0x1E, 0xFB, 0x4C, 0x01, 0xE3, 0x20, 0xBE, 0xDE, 0xAA, 0x20, 0xE8, 0xDF, 0x20, 0xB7, 0x00, +0xD0, 0xF4, 0x60, 0xA2, 0x00, 0x20, 0xB7, 0x00, 0x86, 0x10, 0x85, 0x81, 0x20, 0xB7, 0x00, 0x20, +0x7D, 0xE0, 0xB0, 0x03, 0x4C, 0xC9, 0xDE, 0xA2, 0x00, 0x86, 0x11, 0x86, 0x12, 0x4C, 0x07, 0xE0, +0x4C, 0x28, 0xF1, 0x4C, 0x3C, 0xD4, 0x00, 0x20, 0xB1, 0x00, 0x90, 0x05, 0x20, 0x7D, 0xE0, 0x90, +0x0B, 0xAA, 0x20, 0xB1, 0x00, 0x90, 0xFB, 0x20, 0x7D, 0xE0, 0xB0, 0xF6, 0xC9, 0x24, 0xD0, 0x06, +0xA9, 0xFF, 0x85, 0x11, 0xD0, 0x10, 0xC9, 0x25, 0xD0, 0x13, 0xA5, 0x14, 0x30, 0xC6, 0xA9, 0x80, +0x85, 0x12, 0x05, 0x81, 0x85, 0x81, 0x8A, 0x09, 0x80, 0xAA, 0x20, 0xB1, 0x00, 0x86, 0x82, 0x38, +0x05, 0x14, 0xE9, 0x28, 0xD0, 0x03, 0x4C, 0x1E, 0xE1, 0x24, 0x14, 0x30, 0x02, 0x70, 0xF7, 0xA9, +0x00, 0x85, 0x14, 0xA5, 0x69, 0xA6, 0x6A, 0xA0, 0x00, 0x86, 0x9C, 0x85, 0x9B, 0xE4, 0x6C, 0xD0, +0x04, 0xC5, 0x6B, 0xF0, 0x22, 0xA5, 0x81, 0xD1, 0x9B, 0xD0, 0x08, 0xA5, 0x82, 0xC8, 0xD1, 0x9B, +0xF0, 0x6C, 0x88, 0x18, 0xA5, 0x9B, 0x69, 0x07, 0x90, 0xE1, 0xE8, 0xD0, 0xDC, 0xC9, 0x41, 0x90, +0x05, 0xE9, 0x5B, 0x38, 0xE9, 0xA5, 0x60, 0x68, 0x48, 0xC9, 0xD7, 0xD0, 0x0F, 0xBA, 0xBD, 0x02, +0x01, 0xC9, 0xDE, 0xD0, 0x07, 0xA9, 0x9A, 0xA0, 0xE0, 0x60, 0x00, 0x00, 0xA5, 0x6B, 0xA4, 0x6C, +0x85, 0x9B, 0x84, 0x9C, 0xA5, 0x6D, 0xA4, 0x6E, 0x85, 0x96, 0x84, 0x97, 0x18, 0x69, 0x07, 0x90, +0x01, 0xC8, 0x85, 0x94, 0x84, 0x95, 0x20, 0x93, 0xD3, 0xA5, 0x94, 0xA4, 0x95, 0xC8, 0x85, 0x6B, +0x84, 0x6C, 0xA0, 0x00, 0xA5, 0x81, 0x91, 0x9B, 0xC8, 0xA5, 0x82, 0x91, 0x9B, 0xA9, 0x00, 0xC8, +0x91, 0x9B, 0xC8, 0x91, 0x9B, 0xC8, 0x91, 0x9B, 0xC8, 0x91, 0x9B, 0xC8, 0x91, 0x9B, 0xA5, 0x9B, +0x18, 0x69, 0x02, 0xA4, 0x9C, 0x90, 0x01, 0xC8, 0x85, 0x83, 0x84, 0x84, 0x60, 0xA5, 0x0F, 0x0A, +0x69, 0x05, 0x65, 0x9B, 0xA4, 0x9C, 0x90, 0x01, 0xC8, 0x85, 0x94, 0x84, 0x95, 0x60, 0x90, 0x80, +0x00, 0x00, 0x20, 0xB1, 0x00, 0x20, 0x67, 0xDD, 0xA5, 0xA2, 0x30, 0x0D, 0xA5, 0x9D, 0xC9, 0x90, +0x90, 0x09, 0xA9, 0xFE, 0xA0, 0xE0, 0x20, 0xB2, 0xEB, 0xD0, 0x7E, 0x4C, 0xF2, 0xEB, 0xA5, 0x14, +0xD0, 0x47, 0xA5, 0x10, 0x05, 0x12, 0x48, 0xA5, 0x11, 0x48, 0xA0, 0x00, 0x98, 0x48, 0xA5, 0x82, +0x48, 0xA5, 0x81, 0x48, 0x20, 0x02, 0xE1, 0x68, 0x85, 0x81, 0x68, 0x85, 0x82, 0x68, 0xA8, 0xBA, +0xBD, 0x02, 0x01, 0x48, 0xBD, 0x01, 0x01, 0x48, 0xA5, 0xA0, 0x9D, 0x02, 0x01, 0xA5, 0xA1, 0x9D, +0x01, 0x01, 0xC8, 0x20, 0xB7, 0x00, 0xC9, 0x2C, 0xF0, 0xD2, 0x84, 0x0F, 0x20, 0xB8, 0xDE, 0x68, +0x85, 0x11, 0x68, 0x85, 0x12, 0x29, 0x7F, 0x85, 0x10, 0xA6, 0x6B, 0xA5, 0x6C, 0x86, 0x9B, 0x85, +0x9C, 0xC5, 0x6E, 0xD0, 0x04, 0xE4, 0x6D, 0xF0, 0x3F, 0xA0, 0x00, 0xB1, 0x9B, 0xC8, 0xC5, 0x81, +0xD0, 0x06, 0xA5, 0x82, 0xD1, 0x9B, 0xF0, 0x16, 0xC8, 0xB1, 0x9B, 0x18, 0x65, 0x9B, 0xAA, 0xC8, +0xB1, 0x9B, 0x65, 0x9C, 0x90, 0xD7, 0xA2, 0x6B, 0x2C, 0xA2, 0x35, 0x4C, 0x12, 0xD4, 0xA2, 0x78, +0xA5, 0x10, 0xD0, 0xF7, 0xA5, 0x14, 0xF0, 0x02, 0x38, 0x60, 0x20, 0xED, 0xE0, 0xA5, 0x0F, 0xA0, +0x04, 0xD1, 0x9B, 0xD0, 0xE1, 0x4C, 0x4B, 0xE2, 0xA5, 0x14, 0xF0, 0x05, 0xA2, 0x2A, 0x4C, 0x12, +0xD4, 0x20, 0xED, 0xE0, 0x20, 0xE3, 0xD3, 0xA9, 0x00, 0xA8, 0x85, 0xAE, 0xA2, 0x05, 0xA5, 0x81, +0x91, 0x9B, 0x10, 0x01, 0xCA, 0xC8, 0xA5, 0x82, 0x91, 0x9B, 0x10, 0x02, 0xCA, 0xCA, 0x86, 0xAD, +0xA5, 0x0F, 0xC8, 0xC8, 0xC8, 0x91, 0x9B, 0xA2, 0x0B, 0xA9, 0x00, 0x24, 0x10, 0x50, 0x08, 0x68, +0x18, 0x69, 0x01, 0xAA, 0x68, 0x69, 0x00, 0xC8, 0x91, 0x9B, 0xC8, 0x8A, 0x91, 0x9B, 0x20, 0xAD, +0xE2, 0x86, 0xAD, 0x85, 0xAE, 0xA4, 0x5E, 0xC6, 0x0F, 0xD0, 0xDC, 0x65, 0x95, 0xB0, 0x5D, 0x85, +0x95, 0xA8, 0x8A, 0x65, 0x94, 0x90, 0x03, 0xC8, 0xF0, 0x52, 0x20, 0xE3, 0xD3, 0x85, 0x6D, 0x84, +0x6E, 0xA9, 0x00, 0xE6, 0xAE, 0xA4, 0xAD, 0xF0, 0x05, 0x88, 0x91, 0x94, 0xD0, 0xFB, 0xC6, 0x95, +0xC6, 0xAE, 0xD0, 0xF5, 0xE6, 0x95, 0x38, 0xA5, 0x6D, 0xE5, 0x9B, 0xA0, 0x02, 0x91, 0x9B, 0xA5, +0x6E, 0xC8, 0xE5, 0x9C, 0x91, 0x9B, 0xA5, 0x10, 0xD0, 0x62, 0xC8, 0xB1, 0x9B, 0x85, 0x0F, 0xA9, +0x00, 0x85, 0xAD, 0x85, 0xAE, 0xC8, 0x68, 0xAA, 0x85, 0xA0, 0x68, 0x85, 0xA1, 0xD1, 0x9B, 0x90, +0x0E, 0xD0, 0x06, 0xC8, 0x8A, 0xD1, 0x9B, 0x90, 0x07, 0x4C, 0x96, 0xE1, 0x4C, 0x10, 0xD4, 0xC8, +0xA5, 0xAE, 0x05, 0xAD, 0x18, 0xF0, 0x0A, 0x20, 0xAD, 0xE2, 0x8A, 0x65, 0xA0, 0xAA, 0x98, 0xA4, +0x5E, 0x65, 0xA1, 0x86, 0xAD, 0xC6, 0x0F, 0xD0, 0xCA, 0x85, 0xAE, 0xA2, 0x05, 0xA5, 0x81, 0x10, +0x01, 0xCA, 0xA5, 0x82, 0x10, 0x02, 0xCA, 0xCA, 0x86, 0x64, 0xA9, 0x00, 0x20, 0xB6, 0xE2, 0x8A, +0x65, 0x94, 0x85, 0x83, 0x98, 0x65, 0x95, 0x85, 0x84, 0xA8, 0xA5, 0x83, 0x60, 0x84, 0x5E, 0xB1, +0x9B, 0x85, 0x64, 0x88, 0xB1, 0x9B, 0x85, 0x65, 0xA9, 0x10, 0x85, 0x99, 0xA2, 0x00, 0xA0, 0x00, +0x8A, 0x0A, 0xAA, 0x98, 0x2A, 0xA8, 0xB0, 0xA4, 0x06, 0xAD, 0x26, 0xAE, 0x90, 0x0B, 0x18, 0x8A, +0x65, 0x64, 0xAA, 0x98, 0x65, 0x65, 0xA8, 0xB0, 0x93, 0xC6, 0x99, 0xD0, 0xE3, 0x60, 0xA5, 0x11, +0xF0, 0x03, 0x20, 0x00, 0xE6, 0x20, 0x84, 0xE4, 0x38, 0xA5, 0x6F, 0xE5, 0x6D, 0xA8, 0xA5, 0x70, +0xE5, 0x6E, 0xA2, 0x00, 0x86, 0x11, 0x85, 0x9E, 0x84, 0x9F, 0xA2, 0x90, 0x4C, 0x9B, 0xEB, 0xA4, +0x24, 0xA9, 0x00, 0x38, 0xF0, 0xEC, 0xA6, 0x76, 0xE8, 0xD0, 0xA1, 0xA2, 0x95, 0x2C, 0xA2, 0xE0, +0x4C, 0x12, 0xD4, 0x20, 0x41, 0xE3, 0x20, 0x06, 0xE3, 0x20, 0xBB, 0xDE, 0xA9, 0x80, 0x85, 0x14, +0x20, 0xE3, 0xDF, 0x20, 0x6A, 0xDD, 0x20, 0xB8, 0xDE, 0xA9, 0xD0, 0x20, 0xC0, 0xDE, 0x48, 0xA5, +0x84, 0x48, 0xA5, 0x83, 0x48, 0xA5, 0xB9, 0x48, 0xA5, 0xB8, 0x48, 0x20, 0x95, 0xD9, 0x4C, 0xAF, +0xE3, 0xA9, 0xC2, 0x20, 0xC0, 0xDE, 0x09, 0x80, 0x85, 0x14, 0x20, 0xEA, 0xDF, 0x85, 0x8A, 0x84, +0x8B, 0x4C, 0x6A, 0xDD, 0x20, 0x41, 0xE3, 0xA5, 0x8B, 0x48, 0xA5, 0x8A, 0x48, 0x20, 0xB2, 0xDE, +0x20, 0x6A, 0xDD, 0x68, 0x85, 0x8A, 0x68, 0x85, 0x8B, 0xA0, 0x02, 0xB1, 0x8A, 0x85, 0x83, 0xAA, +0xC8, 0xB1, 0x8A, 0xF0, 0x99, 0x85, 0x84, 0xC8, 0xB1, 0x83, 0x48, 0x88, 0x10, 0xFA, 0xA4, 0x84, +0x20, 0x2B, 0xEB, 0xA5, 0xB9, 0x48, 0xA5, 0xB8, 0x48, 0xB1, 0x8A, 0x85, 0xB8, 0xC8, 0xB1, 0x8A, +0x85, 0xB9, 0xA5, 0x84, 0x48, 0xA5, 0x83, 0x48, 0x20, 0x67, 0xDD, 0x68, 0x85, 0x8A, 0x68, 0x85, +0x8B, 0x20, 0xB7, 0x00, 0xF0, 0x03, 0x4C, 0xC9, 0xDE, 0x68, 0x85, 0xB8, 0x68, 0x85, 0xB9, 0xA0, +0x00, 0x68, 0x91, 0x8A, 0x68, 0xC8, 0x91, 0x8A, 0x68, 0xC8, 0x91, 0x8A, 0x68, 0xC8, 0x91, 0x8A, +0x68, 0xC8, 0x91, 0x8A, 0x60, 0x20, 0x6A, 0xDD, 0xA0, 0x00, 0x20, 0x36, 0xED, 0x68, 0x68, 0xA9, +0xFF, 0xA0, 0x00, 0xF0, 0x12, 0xA6, 0xA0, 0xA4, 0xA1, 0x86, 0x8C, 0x84, 0x8D, 0x20, 0x52, 0xE4, +0x86, 0x9E, 0x84, 0x9F, 0x85, 0x9D, 0x60, 0xA2, 0x22, 0x86, 0x0D, 0x86, 0x0E, 0x85, 0xAB, 0x84, +0xAC, 0x85, 0x9E, 0x84, 0x9F, 0xA0, 0xFF, 0xC8, 0xB1, 0xAB, 0xF0, 0x0C, 0xC5, 0x0D, 0xF0, 0x04, +0xC5, 0x0E, 0xD0, 0xF3, 0xC9, 0x22, 0xF0, 0x01, 0x18, 0x84, 0x9D, 0x98, 0x65, 0xAB, 0x85, 0xAD, +0xA6, 0xAC, 0x90, 0x01, 0xE8, 0x86, 0xAE, 0xA5, 0xAC, 0xF0, 0x04, 0xC9, 0x02, 0xD0, 0x0B, 0x98, +0x20, 0xD5, 0xE3, 0xA6, 0xAB, 0xA4, 0xAC, 0x20, 0xE2, 0xE5, 0xA6, 0x52, 0xE0, 0x5E, 0xD0, 0x05, +0xA2, 0xBF, 0x4C, 0x12, 0xD4, 0xA5, 0x9D, 0x95, 0x00, 0xA5, 0x9E, 0x95, 0x01, 0xA5, 0x9F, 0x95, +0x02, 0xA0, 0x00, 0x86, 0xA0, 0x84, 0xA1, 0x88, 0x84, 0x11, 0x86, 0x53, 0xE8, 0xE8, 0xE8, 0x86, +0x52, 0x60, 0x46, 0x13, 0x48, 0x49, 0xFF, 0x38, 0x65, 0x6F, 0xA4, 0x70, 0xB0, 0x01, 0x88, 0xC4, +0x6E, 0x90, 0x11, 0xD0, 0x04, 0xC5, 0x6D, 0x90, 0x0B, 0x85, 0x6F, 0x84, 0x70, 0x85, 0x71, 0x84, +0x72, 0xAA, 0x68, 0x60, 0xA2, 0x4D, 0xA5, 0x13, 0x30, 0xB8, 0x20, 0x84, 0xE4, 0xA9, 0x80, 0x85, +0x13, 0x68, 0xD0, 0xD0, 0xA6, 0x73, 0xA5, 0x74, 0x86, 0x6F, 0x85, 0x70, 0xA0, 0x00, 0x84, 0x8B, +0xA5, 0x6D, 0xA6, 0x6E, 0x85, 0x9B, 0x86, 0x9C, 0xA9, 0x55, 0xA2, 0x00, 0x85, 0x5E, 0x86, 0x5F, +0xC5, 0x52, 0xF0, 0x05, 0x20, 0x23, 0xE5, 0xF0, 0xF7, 0xA9, 0x07, 0x85, 0x8F, 0xA5, 0x69, 0xA6, +0x6A, 0x85, 0x5E, 0x86, 0x5F, 0xE4, 0x6C, 0xD0, 0x04, 0xC5, 0x6B, 0xF0, 0x05, 0x20, 0x19, 0xE5, +0xF0, 0xF3, 0x85, 0x94, 0x86, 0x95, 0xA9, 0x03, 0x85, 0x8F, 0xA5, 0x94, 0xA6, 0x95, 0xE4, 0x6E, +0xD0, 0x07, 0xC5, 0x6D, 0xD0, 0x03, 0x4C, 0x62, 0xE5, 0x85, 0x5E, 0x86, 0x5F, 0xA0, 0x00, 0xB1, +0x5E, 0xAA, 0xC8, 0xB1, 0x5E, 0x08, 0xC8, 0xB1, 0x5E, 0x65, 0x94, 0x85, 0x94, 0xC8, 0xB1, 0x5E, +0x65, 0x95, 0x85, 0x95, 0x28, 0x10, 0xD3, 0x8A, 0x30, 0xD0, 0xC8, 0xB1, 0x5E, 0xA0, 0x00, 0x0A, +0x69, 0x05, 0x65, 0x5E, 0x85, 0x5E, 0x90, 0x02, 0xE6, 0x5F, 0xA6, 0x5F, 0xE4, 0x95, 0xD0, 0x04, +0xC5, 0x94, 0xF0, 0xBA, 0x20, 0x23, 0xE5, 0xF0, 0xF3, 0xB1, 0x5E, 0x30, 0x35, 0xC8, 0xB1, 0x5E, +0x10, 0x30, 0xC8, 0xB1, 0x5E, 0xF0, 0x2B, 0xC8, 0xB1, 0x5E, 0xAA, 0xC8, 0xB1, 0x5E, 0xC5, 0x70, +0x90, 0x06, 0xD0, 0x1E, 0xE4, 0x6F, 0xB0, 0x1A, 0xC5, 0x9C, 0x90, 0x16, 0xD0, 0x04, 0xE4, 0x9B, +0x90, 0x10, 0x86, 0x9B, 0x85, 0x9C, 0xA5, 0x5E, 0xA6, 0x5F, 0x85, 0x8A, 0x86, 0x8B, 0xA5, 0x8F, +0x85, 0x91, 0xA5, 0x8F, 0x18, 0x65, 0x5E, 0x85, 0x5E, 0x90, 0x02, 0xE6, 0x5F, 0xA6, 0x5F, 0xA0, +0x00, 0x60, 0xA6, 0x8B, 0xF0, 0xF7, 0xA5, 0x91, 0x29, 0x04, 0x4A, 0xA8, 0x85, 0x91, 0xB1, 0x8A, +0x65, 0x9B, 0x85, 0x96, 0xA5, 0x9C, 0x69, 0x00, 0x85, 0x97, 0xA5, 0x6F, 0xA6, 0x70, 0x85, 0x94, +0x86, 0x95, 0x20, 0x9A, 0xD3, 0xA4, 0x91, 0xC8, 0xA5, 0x94, 0x91, 0x8A, 0xAA, 0xE6, 0x95, 0xA5, +0x95, 0xC8, 0x91, 0x8A, 0x4C, 0x88, 0xE4, 0xA5, 0xA1, 0x48, 0xA5, 0xA0, 0x48, 0x20, 0x60, 0xDE, +0x20, 0x6C, 0xDD, 0x68, 0x85, 0xAB, 0x68, 0x85, 0xAC, 0xA0, 0x00, 0xB1, 0xAB, 0x18, 0x71, 0xA0, +0x90, 0x05, 0xA2, 0xB0, 0x4C, 0x12, 0xD4, 0x20, 0xD5, 0xE3, 0x20, 0xD4, 0xE5, 0xA5, 0x8C, 0xA4, +0x8D, 0x20, 0x04, 0xE6, 0x20, 0xE6, 0xE5, 0xA5, 0xAB, 0xA4, 0xAC, 0x20, 0x04, 0xE6, 0x20, 0x2A, +0xE4, 0x4C, 0x95, 0xDD, 0xA0, 0x00, 0xB1, 0xAB, 0x48, 0xC8, 0xB1, 0xAB, 0xAA, 0xC8, 0xB1, 0xAB, +0xA8, 0x68, 0x86, 0x5E, 0x84, 0x5F, 0xA8, 0xF0, 0x0A, 0x48, 0x88, 0xB1, 0x5E, 0x91, 0x71, 0x98, +0xD0, 0xF8, 0x68, 0x18, 0x65, 0x71, 0x85, 0x71, 0x90, 0x02, 0xE6, 0x72, 0x60, 0x20, 0x6C, 0xDD, +0xA5, 0xA0, 0xA4, 0xA1, 0x85, 0x5E, 0x84, 0x5F, 0x20, 0x35, 0xE6, 0x08, 0xA0, 0x00, 0xB1, 0x5E, +0x48, 0xC8, 0xB1, 0x5E, 0xAA, 0xC8, 0xB1, 0x5E, 0xA8, 0x68, 0x28, 0xD0, 0x13, 0xC4, 0x70, 0xD0, +0x0F, 0xE4, 0x6F, 0xD0, 0x0B, 0x48, 0x18, 0x65, 0x6F, 0x85, 0x6F, 0x90, 0x02, 0xE6, 0x70, 0x68, +0x86, 0x5E, 0x84, 0x5F, 0x60, 0xC4, 0x54, 0xD0, 0x0C, 0xC5, 0x53, 0xD0, 0x08, 0x85, 0x52, 0xE9, +0x03, 0x85, 0x53, 0xA0, 0x00, 0x60, 0x20, 0xFB, 0xE6, 0x8A, 0x48, 0xA9, 0x01, 0x20, 0xDD, 0xE3, +0x68, 0xA0, 0x00, 0x91, 0x9E, 0x68, 0x68, 0x4C, 0x2A, 0xE4, 0x20, 0xB9, 0xE6, 0xD1, 0x8C, 0x98, +0x90, 0x04, 0xB1, 0x8C, 0xAA, 0x98, 0x48, 0x8A, 0x48, 0x20, 0xDD, 0xE3, 0xA5, 0x8C, 0xA4, 0x8D, +0x20, 0x04, 0xE6, 0x68, 0xA8, 0x68, 0x18, 0x65, 0x5E, 0x85, 0x5E, 0x90, 0x02, 0xE6, 0x5F, 0x98, +0x20, 0xE6, 0xE5, 0x4C, 0x2A, 0xE4, 0x20, 0xB9, 0xE6, 0x18, 0xF1, 0x8C, 0x49, 0xFF, 0x4C, 0x60, +0xE6, 0xA9, 0xFF, 0x85, 0xA1, 0x20, 0xB7, 0x00, 0xC9, 0x29, 0xF0, 0x06, 0x20, 0xBE, 0xDE, 0x20, +0xF8, 0xE6, 0x20, 0xB9, 0xE6, 0xCA, 0x8A, 0x48, 0x18, 0xA2, 0x00, 0xF1, 0x8C, 0xB0, 0xB8, 0x49, +0xFF, 0xC5, 0xA1, 0x90, 0xB3, 0xA5, 0xA1, 0xB0, 0xAF, 0x20, 0xB8, 0xDE, 0x68, 0xA8, 0x68, 0x85, +0x91, 0x68, 0x68, 0x68, 0xAA, 0x68, 0x85, 0x8C, 0x68, 0x85, 0x8D, 0xA5, 0x91, 0x48, 0x98, 0x48, +0xA0, 0x00, 0x8A, 0xF0, 0x1D, 0x60, 0x20, 0xDC, 0xE6, 0x4C, 0x01, 0xE3, 0x20, 0xFD, 0xE5, 0xA2, +0x00, 0x86, 0x11, 0xA8, 0x60, 0x20, 0xDC, 0xE6, 0xF0, 0x08, 0xA0, 0x00, 0xB1, 0x5E, 0xA8, 0x4C, +0x01, 0xE3, 0x4C, 0x99, 0xE1, 0x20, 0xB1, 0x00, 0x20, 0x67, 0xDD, 0x20, 0x08, 0xE1, 0xA6, 0xA0, +0xD0, 0xF0, 0xA6, 0xA1, 0x4C, 0xB7, 0x00, 0x20, 0xDC, 0xE6, 0xD0, 0x03, 0x4C, 0x4E, 0xE8, 0xA6, +0xB8, 0xA4, 0xB9, 0x86, 0xAD, 0x84, 0xAE, 0xA6, 0x5E, 0x86, 0xB8, 0x18, 0x65, 0x5E, 0x85, 0x60, +0xA6, 0x5F, 0x86, 0xB9, 0x90, 0x01, 0xE8, 0x86, 0x61, 0xA0, 0x00, 0xB1, 0x60, 0x48, 0xA9, 0x00, +0x91, 0x60, 0x20, 0xB7, 0x00, 0x20, 0x4A, 0xEC, 0x68, 0xA0, 0x00, 0x91, 0x60, 0xA6, 0xAD, 0xA4, +0xAE, 0x86, 0xB8, 0x84, 0xB9, 0x60, 0x20, 0x67, 0xDD, 0x20, 0x52, 0xE7, 0x20, 0xBE, 0xDE, 0x4C, +0xF8, 0xE6, 0xA5, 0x9D, 0xC9, 0x91, 0xB0, 0x9A, 0x20, 0xF2, 0xEB, 0xA5, 0xA0, 0xA4, 0xA1, 0x84, +0x50, 0x85, 0x51, 0x60, 0xA5, 0x50, 0x48, 0xA5, 0x51, 0x48, 0x20, 0x52, 0xE7, 0xA0, 0x00, 0xB1, +0x50, 0xA8, 0x68, 0x85, 0x51, 0x68, 0x85, 0x50, 0x4C, 0x01, 0xE3, 0x20, 0x46, 0xE7, 0x8A, 0xA0, +0x00, 0x91, 0x50, 0x60, 0x20, 0x46, 0xE7, 0x86, 0x85, 0xA2, 0x00, 0x20, 0xB7, 0x00, 0xF0, 0x03, +0x20, 0x4C, 0xE7, 0x86, 0x86, 0xA0, 0x00, 0xB1, 0x50, 0x45, 0x86, 0x25, 0x85, 0xF0, 0xF8, 0x60, +0xA9, 0x64, 0xA0, 0xEE, 0x4C, 0xBE, 0xE7, 0x20, 0xE3, 0xE9, 0xA5, 0xA2, 0x49, 0xFF, 0x85, 0xA2, +0x45, 0xAA, 0x85, 0xAB, 0xA5, 0x9D, 0x4C, 0xC1, 0xE7, 0x20, 0xF0, 0xE8, 0x90, 0x3C, 0x20, 0xE3, +0xE9, 0xD0, 0x03, 0x4C, 0x53, 0xEB, 0xA6, 0xAC, 0x86, 0x92, 0xA2, 0xA5, 0xA5, 0xA5, 0xA8, 0xF0, +0xCE, 0x38, 0xE5, 0x9D, 0xF0, 0x24, 0x90, 0x12, 0x84, 0x9D, 0xA4, 0xAA, 0x84, 0xA2, 0x49, 0xFF, +0x69, 0x00, 0xA0, 0x00, 0x84, 0x92, 0xA2, 0x9D, 0xD0, 0x04, 0xA0, 0x00, 0x84, 0xAC, 0xC9, 0xF9, +0x30, 0xC7, 0xA8, 0xA5, 0xAC, 0x56, 0x01, 0x20, 0x07, 0xE9, 0x24, 0xAB, 0x10, 0x57, 0xA0, 0x9D, +0xE0, 0xA5, 0xF0, 0x02, 0xA0, 0xA5, 0x38, 0x49, 0xFF, 0x65, 0x92, 0x85, 0xAC, 0xB9, 0x04, 0x00, +0xF5, 0x04, 0x85, 0xA1, 0xB9, 0x03, 0x00, 0xF5, 0x03, 0x85, 0xA0, 0xB9, 0x02, 0x00, 0xF5, 0x02, +0x85, 0x9F, 0xB9, 0x01, 0x00, 0xF5, 0x01, 0x85, 0x9E, 0xB0, 0x03, 0x20, 0x9E, 0xE8, 0xA0, 0x00, +0x98, 0x18, 0xA6, 0x9E, 0xD0, 0x4A, 0xA6, 0x9F, 0x86, 0x9E, 0xA6, 0xA0, 0x86, 0x9F, 0xA6, 0xA1, +0x86, 0xA0, 0xA6, 0xAC, 0x86, 0xA1, 0x84, 0xAC, 0x69, 0x08, 0xC9, 0x20, 0xD0, 0xE4, 0xA9, 0x00, +0x85, 0x9D, 0x85, 0xA2, 0x60, 0x65, 0x92, 0x85, 0xAC, 0xA5, 0xA1, 0x65, 0xA9, 0x85, 0xA1, 0xA5, +0xA0, 0x65, 0xA8, 0x85, 0xA0, 0xA5, 0x9F, 0x65, 0xA7, 0x85, 0x9F, 0xA5, 0x9E, 0x65, 0xA6, 0x85, +0x9E, 0x4C, 0x8D, 0xE8, 0x69, 0x01, 0x06, 0xAC, 0x26, 0xA1, 0x26, 0xA0, 0x26, 0x9F, 0x26, 0x9E, +0x10, 0xF2, 0x38, 0xE5, 0x9D, 0xB0, 0xC7, 0x49, 0xFF, 0x69, 0x01, 0x85, 0x9D, 0x90, 0x0E, 0xE6, +0x9D, 0xF0, 0x42, 0x66, 0x9E, 0x66, 0x9F, 0x66, 0xA0, 0x66, 0xA1, 0x66, 0xAC, 0x60, 0xA5, 0xA2, +0x49, 0xFF, 0x85, 0xA2, 0xA5, 0x9E, 0x49, 0xFF, 0x85, 0x9E, 0xA5, 0x9F, 0x49, 0xFF, 0x85, 0x9F, +0xA5, 0xA0, 0x49, 0xFF, 0x85, 0xA0, 0xA5, 0xA1, 0x49, 0xFF, 0x85, 0xA1, 0xA5, 0xAC, 0x49, 0xFF, +0x85, 0xAC, 0xE6, 0xAC, 0xD0, 0x0E, 0xE6, 0xA1, 0xD0, 0x0A, 0xE6, 0xA0, 0xD0, 0x06, 0xE6, 0x9F, +0xD0, 0x02, 0xE6, 0x9E, 0x60, 0xA2, 0x45, 0x4C, 0x12, 0xD4, 0xA2, 0x61, 0xB4, 0x04, 0x84, 0xAC, +0xB4, 0x03, 0x94, 0x04, 0xB4, 0x02, 0x94, 0x03, 0xB4, 0x01, 0x94, 0x02, 0xA4, 0xA4, 0x94, 0x01, +0x69, 0x08, 0x30, 0xE8, 0xF0, 0xE6, 0xE9, 0x08, 0xA8, 0xA5, 0xAC, 0xB0, 0x14, 0x16, 0x01, 0x90, +0x02, 0xF6, 0x01, 0x76, 0x01, 0x76, 0x01, 0x76, 0x02, 0x76, 0x03, 0x76, 0x04, 0x6A, 0xC8, 0xD0, +0xEC, 0x18, 0x60, 0x81, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0x5E, 0x56, 0xCB, 0x79, 0x80, 0x13, +0x9B, 0x0B, 0x64, 0x80, 0x76, 0x38, 0x93, 0x16, 0x82, 0x38, 0xAA, 0x3B, 0x20, 0x80, 0x35, 0x04, +0xF3, 0x34, 0x81, 0x35, 0x04, 0xF3, 0x34, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x31, 0x72, 0x17, +0xF8, 0x20, 0x82, 0xEB, 0xF0, 0x02, 0x10, 0x03, 0x4C, 0x99, 0xE1, 0xA5, 0x9D, 0xE9, 0x7F, 0x48, +0xA9, 0x80, 0x85, 0x9D, 0xA9, 0x2D, 0xA0, 0xE9, 0x20, 0xBE, 0xE7, 0xA9, 0x32, 0xA0, 0xE9, 0x20, +0x66, 0xEA, 0xA9, 0x13, 0xA0, 0xE9, 0x20, 0xA7, 0xE7, 0xA9, 0x18, 0xA0, 0xE9, 0x20, 0x5C, 0xEF, +0xA9, 0x37, 0xA0, 0xE9, 0x20, 0xBE, 0xE7, 0x68, 0x20, 0xD5, 0xEC, 0xA9, 0x3C, 0xA0, 0xE9, 0x20, +0xE3, 0xE9, 0xD0, 0x03, 0x4C, 0xE2, 0xE9, 0x20, 0x0E, 0xEA, 0xA9, 0x00, 0x85, 0x62, 0x85, 0x63, +0x85, 0x64, 0x85, 0x65, 0xA5, 0xAC, 0x20, 0xB0, 0xE9, 0xA5, 0xA1, 0x20, 0xB0, 0xE9, 0xA5, 0xA0, +0x20, 0xB0, 0xE9, 0xA5, 0x9F, 0x20, 0xB0, 0xE9, 0xA5, 0x9E, 0x20, 0xB5, 0xE9, 0x4C, 0xE6, 0xEA, +0xD0, 0x03, 0x4C, 0xDA, 0xE8, 0x4A, 0x09, 0x80, 0xA8, 0x90, 0x19, 0x18, 0xA5, 0x65, 0x65, 0xA9, +0x85, 0x65, 0xA5, 0x64, 0x65, 0xA8, 0x85, 0x64, 0xA5, 0x63, 0x65, 0xA7, 0x85, 0x63, 0xA5, 0x62, +0x65, 0xA6, 0x85, 0x62, 0x66, 0x62, 0x66, 0x63, 0x66, 0x64, 0x66, 0x65, 0x66, 0xAC, 0x98, 0x4A, +0xD0, 0xD6, 0x60, 0x85, 0x5E, 0x84, 0x5F, 0xA0, 0x04, 0xB1, 0x5E, 0x85, 0xA9, 0x88, 0xB1, 0x5E, +0x85, 0xA8, 0x88, 0xB1, 0x5E, 0x85, 0xA7, 0x88, 0xB1, 0x5E, 0x85, 0xAA, 0x45, 0xA2, 0x85, 0xAB, +0xA5, 0xAA, 0x09, 0x80, 0x85, 0xA6, 0x88, 0xB1, 0x5E, 0x85, 0xA5, 0xA5, 0x9D, 0x60, 0xA5, 0xA5, +0xF0, 0x1F, 0x18, 0x65, 0x9D, 0x90, 0x04, 0x30, 0x1D, 0x18, 0x2C, 0x10, 0x14, 0x69, 0x80, 0x85, +0x9D, 0xD0, 0x03, 0x4C, 0x52, 0xE8, 0xA5, 0xAB, 0x85, 0xA2, 0x60, 0xA5, 0xA2, 0x49, 0xFF, 0x30, +0x05, 0x68, 0x68, 0x4C, 0x4E, 0xE8, 0x4C, 0xD5, 0xE8, 0x20, 0x63, 0xEB, 0xAA, 0xF0, 0x10, 0x18, +0x69, 0x02, 0xB0, 0xF2, 0xA2, 0x00, 0x86, 0xAB, 0x20, 0xCE, 0xE7, 0xE6, 0x9D, 0xF0, 0xE7, 0x60, +0x84, 0x20, 0x00, 0x00, 0x00, 0x20, 0x63, 0xEB, 0xA9, 0x50, 0xA0, 0xEA, 0xA2, 0x00, 0x86, 0xAB, +0x20, 0xF9, 0xEA, 0x4C, 0x69, 0xEA, 0x20, 0xE3, 0xE9, 0xF0, 0x76, 0x20, 0x72, 0xEB, 0xA9, 0x00, +0x38, 0xE5, 0x9D, 0x85, 0x9D, 0x20, 0x0E, 0xEA, 0xE6, 0x9D, 0xF0, 0xBA, 0xA2, 0xFC, 0xA9, 0x01, +0xA4, 0xA6, 0xC4, 0x9E, 0xD0, 0x10, 0xA4, 0xA7, 0xC4, 0x9F, 0xD0, 0x0A, 0xA4, 0xA8, 0xC4, 0xA0, +0xD0, 0x04, 0xA4, 0xA9, 0xC4, 0xA1, 0x08, 0x2A, 0x90, 0x09, 0xE8, 0x95, 0x65, 0xF0, 0x32, 0x10, +0x34, 0xA9, 0x01, 0x28, 0xB0, 0x0E, 0x06, 0xA9, 0x26, 0xA8, 0x26, 0xA7, 0x26, 0xA6, 0xB0, 0xE6, +0x30, 0xCE, 0x10, 0xE2, 0xA8, 0xA5, 0xA9, 0xE5, 0xA1, 0x85, 0xA9, 0xA5, 0xA8, 0xE5, 0xA0, 0x85, +0xA8, 0xA5, 0xA7, 0xE5, 0x9F, 0x85, 0xA7, 0xA5, 0xA6, 0xE5, 0x9E, 0x85, 0xA6, 0x98, 0x4C, 0xA6, +0xEA, 0xA9, 0x40, 0xD0, 0xCE, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x85, 0xAC, 0x28, 0x4C, 0xE6, +0xEA, 0xA2, 0x85, 0x4C, 0x12, 0xD4, 0xA5, 0x62, 0x85, 0x9E, 0xA5, 0x63, 0x85, 0x9F, 0xA5, 0x64, +0x85, 0xA0, 0xA5, 0x65, 0x85, 0xA1, 0x4C, 0x2E, 0xE8, 0x85, 0x5E, 0x84, 0x5F, 0xA0, 0x04, 0xB1, +0x5E, 0x85, 0xA1, 0x88, 0xB1, 0x5E, 0x85, 0xA0, 0x88, 0xB1, 0x5E, 0x85, 0x9F, 0x88, 0xB1, 0x5E, +0x85, 0xA2, 0x09, 0x80, 0x85, 0x9E, 0x88, 0xB1, 0x5E, 0x85, 0x9D, 0x84, 0xAC, 0x60, 0xA2, 0x98, +0x2C, 0xA2, 0x93, 0xA0, 0x00, 0xF0, 0x04, 0xA6, 0x85, 0xA4, 0x86, 0x20, 0x72, 0xEB, 0x86, 0x5E, +0x84, 0x5F, 0xA0, 0x04, 0xA5, 0xA1, 0x91, 0x5E, 0x88, 0xA5, 0xA0, 0x91, 0x5E, 0x88, 0xA5, 0x9F, +0x91, 0x5E, 0x88, 0xA5, 0xA2, 0x09, 0x7F, 0x25, 0x9E, 0x91, 0x5E, 0x88, 0xA5, 0x9D, 0x91, 0x5E, +0x84, 0xAC, 0x60, 0xA5, 0xAA, 0x85, 0xA2, 0xA2, 0x05, 0xB5, 0xA4, 0x95, 0x9C, 0xCA, 0xD0, 0xF9, +0x86, 0xAC, 0x60, 0x20, 0x72, 0xEB, 0xA2, 0x06, 0xB5, 0x9C, 0x95, 0xA4, 0xCA, 0xD0, 0xF9, 0x86, +0xAC, 0x60, 0xA5, 0x9D, 0xF0, 0xFB, 0x06, 0xAC, 0x90, 0xF7, 0x20, 0xC6, 0xE8, 0xD0, 0xF2, 0x4C, +0x8F, 0xE8, 0xA5, 0x9D, 0xF0, 0x09, 0xA5, 0xA2, 0x2A, 0xA9, 0xFF, 0xB0, 0x02, 0xA9, 0x01, 0x60, +0x20, 0x82, 0xEB, 0x85, 0x9E, 0xA9, 0x00, 0x85, 0x9F, 0xA2, 0x88, 0xA5, 0x9E, 0x49, 0xFF, 0x2A, +0xA9, 0x00, 0x85, 0xA1, 0x85, 0xA0, 0x86, 0x9D, 0x85, 0xAC, 0x85, 0xA2, 0x4C, 0x29, 0xE8, 0x46, +0xA2, 0x60, 0x85, 0x60, 0x84, 0x61, 0xA0, 0x00, 0xB1, 0x60, 0xC8, 0xAA, 0xF0, 0xC4, 0xB1, 0x60, +0x45, 0xA2, 0x30, 0xC2, 0xE4, 0x9D, 0xD0, 0x21, 0xB1, 0x60, 0x09, 0x80, 0xC5, 0x9E, 0xD0, 0x19, +0xC8, 0xB1, 0x60, 0xC5, 0x9F, 0xD0, 0x12, 0xC8, 0xB1, 0x60, 0xC5, 0xA0, 0xD0, 0x0B, 0xC8, 0xA9, +0x7F, 0xC5, 0xAC, 0xB1, 0x60, 0xE5, 0xA1, 0xF0, 0x28, 0xA5, 0xA2, 0x90, 0x02, 0x49, 0xFF, 0x4C, +0x88, 0xEB, 0xA5, 0x9D, 0xF0, 0x4A, 0x38, 0xE9, 0xA0, 0x24, 0xA2, 0x10, 0x09, 0xAA, 0xA9, 0xFF, +0x85, 0xA4, 0x20, 0xA4, 0xE8, 0x8A, 0xA2, 0x9D, 0xC9, 0xF9, 0x10, 0x06, 0x20, 0xF0, 0xE8, 0x84, +0xA4, 0x60, 0xA8, 0xA5, 0xA2, 0x29, 0x80, 0x46, 0x9E, 0x05, 0x9E, 0x85, 0x9E, 0x20, 0x07, 0xE9, +0x84, 0xA4, 0x60, 0xA5, 0x9D, 0xC9, 0xA0, 0xB0, 0x20, 0x20, 0xF2, 0xEB, 0x84, 0xAC, 0xA5, 0xA2, +0x84, 0xA2, 0x49, 0x80, 0x2A, 0xA9, 0xA0, 0x85, 0x9D, 0xA5, 0xA1, 0x85, 0x0D, 0x4C, 0x29, 0xE8, +0x85, 0x9E, 0x85, 0x9F, 0x85, 0xA0, 0x85, 0xA1, 0xA8, 0x60, 0xA0, 0x00, 0xA2, 0x0A, 0x94, 0x99, +0xCA, 0x10, 0xFB, 0x90, 0x0F, 0xC9, 0x2D, 0xD0, 0x04, 0x86, 0xA3, 0xF0, 0x04, 0xC9, 0x2B, 0xD0, +0x05, 0x20, 0xB1, 0x00, 0x90, 0x5B, 0xC9, 0x2E, 0xF0, 0x2E, 0xC9, 0x45, 0xD0, 0x30, 0x20, 0xB1, +0x00, 0x90, 0x17, 0xC9, 0xC9, 0xF0, 0x0E, 0xC9, 0x2D, 0xF0, 0x0A, 0xC9, 0xC8, 0xF0, 0x08, 0xC9, +0x2B, 0xF0, 0x04, 0xD0, 0x07, 0x66, 0x9C, 0x20, 0xB1, 0x00, 0x90, 0x5C, 0x24, 0x9C, 0x10, 0x0E, +0xA9, 0x00, 0x38, 0xE5, 0x9A, 0x4C, 0xA0, 0xEC, 0x66, 0x9B, 0x24, 0x9B, 0x50, 0xC3, 0xA5, 0x9A, +0x38, 0xE5, 0x99, 0x85, 0x9A, 0xF0, 0x12, 0x10, 0x09, 0x20, 0x55, 0xEA, 0xE6, 0x9A, 0xD0, 0xF9, +0xF0, 0x07, 0x20, 0x39, 0xEA, 0xC6, 0x9A, 0xD0, 0xF9, 0xA5, 0xA3, 0x30, 0x01, 0x60, 0x4C, 0xD0, +0xEE, 0x48, 0x24, 0x9B, 0x10, 0x02, 0xE6, 0x99, 0x20, 0x39, 0xEA, 0x68, 0x38, 0xE9, 0x30, 0x20, +0xD5, 0xEC, 0x4C, 0x61, 0xEC, 0x48, 0x20, 0x63, 0xEB, 0x68, 0x20, 0x93, 0xEB, 0xA5, 0xAA, 0x45, +0xA2, 0x85, 0xAB, 0xA6, 0x9D, 0x4C, 0xC1, 0xE7, 0xA5, 0x9A, 0xC9, 0x0A, 0x90, 0x09, 0xA9, 0x64, +0x24, 0x9C, 0x30, 0x11, 0x4C, 0xD5, 0xE8, 0x0A, 0x0A, 0x18, 0x65, 0x9A, 0x0A, 0x18, 0xA0, 0x00, +0x71, 0xB8, 0x38, 0xE9, 0x30, 0x85, 0x9A, 0x4C, 0x87, 0xEC, 0x9B, 0x3E, 0xBC, 0x1F, 0xFD, 0x9E, +0x6E, 0x6B, 0x27, 0xFD, 0x9E, 0x6E, 0x6B, 0x28, 0x00, 0xA9, 0x58, 0xA0, 0xD3, 0x20, 0x31, 0xED, +0xA5, 0x76, 0xA6, 0x75, 0x85, 0x9E, 0x86, 0x9F, 0xA2, 0x90, 0x38, 0x20, 0xA0, 0xEB, 0x20, 0x34, +0xED, 0x4C, 0x3A, 0xDB, 0xA0, 0x01, 0xA9, 0x2D, 0x88, 0x24, 0xA2, 0x10, 0x04, 0xC8, 0x99, 0xFF, +0x00, 0x85, 0xA2, 0x84, 0xAD, 0xC8, 0xA9, 0x30, 0xA6, 0x9D, 0xD0, 0x03, 0x4C, 0x57, 0xEE, 0xA9, +0x00, 0xE0, 0x80, 0xF0, 0x02, 0xB0, 0x09, 0xA9, 0x14, 0xA0, 0xED, 0x20, 0x7F, 0xE9, 0xA9, 0xF7, +0x85, 0x99, 0xA9, 0x0F, 0xA0, 0xED, 0x20, 0xB2, 0xEB, 0xF0, 0x1E, 0x10, 0x12, 0xA9, 0x0A, 0xA0, +0xED, 0x20, 0xB2, 0xEB, 0xF0, 0x02, 0x10, 0x0E, 0x20, 0x39, 0xEA, 0xC6, 0x99, 0xD0, 0xEE, 0x20, +0x55, 0xEA, 0xE6, 0x99, 0xD0, 0xDC, 0x20, 0xA0, 0xE7, 0x20, 0xF2, 0xEB, 0xA2, 0x01, 0xA5, 0x99, +0x18, 0x69, 0x0A, 0x30, 0x09, 0xC9, 0x0B, 0xB0, 0x06, 0x69, 0xFF, 0xAA, 0xA9, 0x02, 0x38, 0xE9, +0x02, 0x85, 0x9A, 0x86, 0x99, 0x8A, 0xF0, 0x02, 0x10, 0x13, 0xA4, 0xAD, 0xA9, 0x2E, 0xC8, 0x99, +0xFF, 0x00, 0x8A, 0xF0, 0x06, 0xA9, 0x30, 0xC8, 0x99, 0xFF, 0x00, 0x84, 0xAD, 0xA0, 0x00, 0xA2, +0x80, 0xA5, 0xA1, 0x18, 0x79, 0x6C, 0xEE, 0x85, 0xA1, 0xA5, 0xA0, 0x79, 0x6B, 0xEE, 0x85, 0xA0, +0xA5, 0x9F, 0x79, 0x6A, 0xEE, 0x85, 0x9F, 0xA5, 0x9E, 0x79, 0x69, 0xEE, 0x85, 0x9E, 0xE8, 0xB0, +0x04, 0x10, 0xDE, 0x30, 0x02, 0x30, 0xDA, 0x8A, 0x90, 0x04, 0x49, 0xFF, 0x69, 0x0A, 0x69, 0x2F, +0xC8, 0xC8, 0xC8, 0xC8, 0x84, 0x83, 0xA4, 0xAD, 0xC8, 0xAA, 0x29, 0x7F, 0x99, 0xFF, 0x00, 0xC6, +0x99, 0xD0, 0x06, 0xA9, 0x2E, 0xC8, 0x99, 0xFF, 0x00, 0x84, 0xAD, 0xA4, 0x83, 0x8A, 0x49, 0xFF, +0x29, 0x80, 0xAA, 0xC0, 0x24, 0xD0, 0xAA, 0xA4, 0xAD, 0xB9, 0xFF, 0x00, 0x88, 0xC9, 0x30, 0xF0, +0xF8, 0xC9, 0x2E, 0xF0, 0x01, 0xC8, 0xA9, 0x2B, 0xA6, 0x9A, 0xF0, 0x2E, 0x10, 0x08, 0xA9, 0x00, +0x38, 0xE5, 0x9A, 0xAA, 0xA9, 0x2D, 0x99, 0x01, 0x01, 0xA9, 0x45, 0x99, 0x00, 0x01, 0x8A, 0xA2, +0x2F, 0x38, 0xE8, 0xE9, 0x0A, 0xB0, 0xFB, 0x69, 0x3A, 0x99, 0x03, 0x01, 0x8A, 0x99, 0x02, 0x01, +0xA9, 0x00, 0x99, 0x04, 0x01, 0xF0, 0x08, 0x99, 0xFF, 0x00, 0xA9, 0x00, 0x99, 0x00, 0x01, 0xA9, +0x00, 0xA0, 0x01, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x0A, 0x1F, 0x00, 0x00, 0x98, 0x96, +0x80, 0xFF, 0xF0, 0xBD, 0xC0, 0x00, 0x01, 0x86, 0xA0, 0xFF, 0xFF, 0xD8, 0xF0, 0x00, 0x00, 0x03, +0xE8, 0xFF, 0xFF, 0xFF, 0x9C, 0x00, 0x00, 0x00, 0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x63, 0xEB, +0xA9, 0x64, 0xA0, 0xEE, 0x20, 0xF9, 0xEA, 0xF0, 0x70, 0xA5, 0xA5, 0xD0, 0x03, 0x4C, 0x50, 0xE8, +0xA2, 0x8A, 0xA0, 0x00, 0x20, 0x2B, 0xEB, 0xA5, 0xAA, 0x10, 0x0F, 0x20, 0x23, 0xEC, 0xA9, 0x8A, +0xA0, 0x00, 0x20, 0xB2, 0xEB, 0xD0, 0x03, 0x98, 0xA4, 0x0D, 0x20, 0x55, 0xEB, 0x98, 0x48, 0x20, +0x41, 0xE9, 0xA9, 0x8A, 0xA0, 0x00, 0x20, 0x7F, 0xE9, 0x20, 0x09, 0xEF, 0x68, 0x4A, 0x90, 0x0A, +0xA5, 0x9D, 0xF0, 0x06, 0xA5, 0xA2, 0x49, 0xFF, 0x85, 0xA2, 0x60, 0x81, 0x38, 0xAA, 0x3B, 0x29, +0x07, 0x71, 0x34, 0x58, 0x3E, 0x56, 0x74, 0x16, 0x7E, 0xB3, 0x1B, 0x77, 0x2F, 0xEE, 0xE3, 0x85, +0x7A, 0x1D, 0x84, 0x1C, 0x2A, 0x7C, 0x63, 0x59, 0x58, 0x0A, 0x7E, 0x75, 0xFD, 0xE7, 0xC6, 0x80, +0x31, 0x72, 0x18, 0x10, 0x81, 0x00, 0x00, 0x00, 0x00, 0xA9, 0xDB, 0xA0, 0xEE, 0x20, 0x7F, 0xE9, +0xA5, 0xAC, 0x69, 0x50, 0x90, 0x03, 0x20, 0x7A, 0xEB, 0x85, 0x92, 0x20, 0x66, 0xEB, 0xA5, 0x9D, +0xC9, 0x88, 0x90, 0x03, 0x20, 0x2B, 0xEA, 0x20, 0x23, 0xEC, 0xA5, 0x0D, 0x18, 0x69, 0x81, 0xF0, +0xF3, 0x38, 0xE9, 0x01, 0x48, 0xA2, 0x05, 0xB5, 0xA5, 0xB4, 0x9D, 0x95, 0x9D, 0x94, 0xA5, 0xCA, +0x10, 0xF5, 0xA5, 0x92, 0x85, 0xAC, 0x20, 0xAA, 0xE7, 0x20, 0xD0, 0xEE, 0xA9, 0xE0, 0xA0, 0xEE, +0x20, 0x72, 0xEF, 0xA9, 0x00, 0x85, 0xAB, 0x68, 0x20, 0x10, 0xEA, 0x60, 0x85, 0xAD, 0x84, 0xAE, +0x20, 0x21, 0xEB, 0xA9, 0x93, 0x20, 0x7F, 0xE9, 0x20, 0x76, 0xEF, 0xA9, 0x93, 0xA0, 0x00, 0x4C, +0x7F, 0xE9, 0x85, 0xAD, 0x84, 0xAE, 0x20, 0x1E, 0xEB, 0xB1, 0xAD, 0x85, 0xA3, 0xA4, 0xAD, 0xC8, +0x98, 0xD0, 0x02, 0xE6, 0xAE, 0x85, 0xAD, 0xA4, 0xAE, 0x20, 0x7F, 0xE9, 0xA5, 0xAD, 0xA4, 0xAE, +0x18, 0x69, 0x05, 0x90, 0x01, 0xC8, 0x85, 0xAD, 0x84, 0xAE, 0x20, 0xBE, 0xE7, 0xA9, 0x98, 0xA0, +0x00, 0xC6, 0xA3, 0xD0, 0xE4, 0x60, 0x98, 0x35, 0x44, 0x7A, 0x68, 0x28, 0xB1, 0x46, 0x20, 0x82, +0xEB, 0xAA, 0x30, 0x18, 0xA9, 0xC9, 0xA0, 0x00, 0x20, 0xF9, 0xEA, 0x8A, 0xF0, 0xE7, 0xA9, 0xA6, +0xA0, 0xEF, 0x20, 0x7F, 0xE9, 0xA9, 0xAA, 0xA0, 0xEF, 0x20, 0xBE, 0xE7, 0xA6, 0xA1, 0xA5, 0x9E, +0x85, 0xA1, 0x86, 0x9E, 0xA9, 0x00, 0x85, 0xA2, 0xA5, 0x9D, 0x85, 0xAC, 0xA9, 0x80, 0x85, 0x9D, +0x20, 0x2E, 0xE8, 0xA2, 0xC9, 0xA0, 0x00, 0x4C, 0x2B, 0xEB, 0xA9, 0x66, 0xA0, 0xF0, 0x20, 0xBE, +0xE7, 0x20, 0x63, 0xEB, 0xA9, 0x6B, 0xA0, 0xF0, 0xA6, 0xAA, 0x20, 0x5E, 0xEA, 0x20, 0x63, 0xEB, +0x20, 0x23, 0xEC, 0xA9, 0x00, 0x85, 0xAB, 0x20, 0xAA, 0xE7, 0xA9, 0x70, 0xA0, 0xF0, 0x20, 0xA7, +0xE7, 0xA5, 0xA2, 0x48, 0x10, 0x0D, 0x20, 0xA0, 0xE7, 0xA5, 0xA2, 0x30, 0x09, 0xA5, 0x16, 0x49, +0xFF, 0x85, 0x16, 0x20, 0xD0, 0xEE, 0xA9, 0x70, 0xA0, 0xF0, 0x20, 0xBE, 0xE7, 0x68, 0x10, 0x03, +0x20, 0xD0, 0xEE, 0xA9, 0x75, 0xA0, 0xF0, 0x4C, 0x5C, 0xEF, 0x20, 0x21, 0xEB, 0xA9, 0x00, 0x85, +0x16, 0x20, 0xF1, 0xEF, 0xA2, 0x8A, 0xA0, 0x00, 0x20, 0xE7, 0xEF, 0xA9, 0x93, 0xA0, 0x00, 0x20, +0xF9, 0xEA, 0xA9, 0x00, 0x85, 0xA2, 0xA5, 0x16, 0x20, 0x62, 0xF0, 0xA9, 0x8A, 0xA0, 0x00, 0x4C, +0x66, 0xEA, 0x48, 0x4C, 0x23, 0xF0, 0x81, 0x49, 0x0F, 0xDA, 0xA2, 0x83, 0x49, 0x0F, 0xDA, 0xA2, +0x7F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x84, 0xE6, 0x1A, 0x2D, 0x1B, 0x86, 0x28, 0x07, 0xFB, 0xF8, +0x87, 0x99, 0x68, 0x89, 0x01, 0x87, 0x23, 0x35, 0xDF, 0xE1, 0x86, 0xA5, 0x5D, 0xE7, 0x28, 0x83, +0x49, 0x0F, 0xDA, 0xA2, 0xA6, 0xD3, 0xC1, 0xC8, 0xD4, 0xC8, 0xD5, 0xC4, 0xCE, 0xCA, 0xA5, 0xA2, +0x48, 0x10, 0x03, 0x20, 0xD0, 0xEE, 0xA5, 0x9D, 0x48, 0xC9, 0x81, 0x90, 0x07, 0xA9, 0x13, 0xA0, +0xE9, 0x20, 0x66, 0xEA, 0xA9, 0xCE, 0xA0, 0xF0, 0x20, 0x5C, 0xEF, 0x68, 0xC9, 0x81, 0x90, 0x07, +0xA9, 0x66, 0xA0, 0xF0, 0x20, 0xA7, 0xE7, 0x68, 0x10, 0x03, 0x4C, 0xD0, 0xEE, 0x60, 0x0B, 0x76, +0xB3, 0x83, 0xBD, 0xD3, 0x79, 0x1E, 0xF4, 0xA6, 0xF5, 0x7B, 0x83, 0xFC, 0xB0, 0x10, 0x7C, 0x0C, +0x1F, 0x67, 0xCA, 0x7C, 0xDE, 0x53, 0xCB, 0xC1, 0x7D, 0x14, 0x64, 0x70, 0x4C, 0x7D, 0xB7, 0xEA, +0x51, 0x7A, 0x7D, 0x63, 0x30, 0x88, 0x7E, 0x7E, 0x92, 0x44, 0x99, 0x3A, 0x7E, 0x4C, 0xCC, 0x91, +0xC7, 0x7F, 0xAA, 0xAA, 0xAA, 0x13, 0x81, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xB8, 0xD0, 0x02, 0xE6, +0xB9, 0xAD, 0x60, 0xEA, 0xC9, 0x3A, 0xB0, 0x0A, 0xC9, 0x20, 0xF0, 0xEF, 0x38, 0xE9, 0x30, 0x38, +0xE9, 0xD0, 0x60, 0x80, 0x4F, 0xC7, 0x52, 0x58, 0xA2, 0xFF, 0x86, 0x76, 0xA2, 0xFB, 0x9A, 0xA9, +0x28, 0xA0, 0xF1, 0x85, 0x01, 0x84, 0x02, 0x85, 0x04, 0x84, 0x05, 0x20, 0x73, 0xF2, 0xA9, 0x4C, +0x85, 0x00, 0x85, 0x03, 0x85, 0x90, 0x85, 0x0A, 0xA9, 0x99, 0xA0, 0xE1, 0x85, 0x0B, 0x84, 0x0C, +0xA2, 0x1C, 0xBD, 0x0A, 0xF1, 0x95, 0xB0, 0x86, 0xF1, 0xCA, 0xD0, 0xF6, 0x86, 0xF2, 0x8A, 0x85, +0xA4, 0x85, 0x54, 0x48, 0xA9, 0x03, 0x85, 0x8F, 0x20, 0xFB, 0xDA, 0xA9, 0x01, 0x8D, 0xFD, 0x01, +0x8D, 0xFC, 0x01, 0xA2, 0x55, 0x86, 0x52, 0xA9, 0x00, 0xA0, 0x08, 0x85, 0x50, 0x84, 0x51, 0xA0, +0x00, 0xE6, 0x51, 0xB1, 0x50, 0x49, 0xFF, 0x91, 0x50, 0xD1, 0x50, 0xD0, 0x08, 0x49, 0xFF, 0x91, +0x50, 0xD1, 0x50, 0xF0, 0xEC, 0xA4, 0x50, 0xA5, 0x51, 0x29, 0xF0, 0x84, 0x73, 0x85, 0x74, 0x84, +0x6F, 0x85, 0x70, 0xA2, 0x00, 0xA0, 0x08, 0x86, 0x67, 0x84, 0x68, 0xA0, 0x00, 0x84, 0xD6, 0x98, +0x91, 0x67, 0xE6, 0x67, 0xD0, 0x02, 0xE6, 0x68, 0xA5, 0x67, 0xA4, 0x68, 0x20, 0xE3, 0xD3, 0x20, +0x4B, 0xD6, 0xA9, 0x3A, 0xA0, 0xDB, 0x85, 0x04, 0x84, 0x05, 0xA9, 0x3C, 0xA0, 0xD4, 0x85, 0x01, +0x84, 0x02, 0x6C, 0x01, 0x00, 0x20, 0x67, 0xDD, 0x20, 0x52, 0xE7, 0x6C, 0x50, 0x00, 0x20, 0xF8, +0xE6, 0x8A, 0x4C, 0x8B, 0xFE, 0x20, 0xF8, 0xE6, 0x8A, 0x4C, 0x95, 0xFE, 0x20, 0xF8, 0xE6, 0xE0, +0x50, 0xB0, 0x13, 0x86, 0xF0, 0xA9, 0x2C, 0x20, 0xC0, 0xDE, 0x20, 0xF8, 0xE6, 0xE0, 0x30, 0xB0, +0x05, 0x86, 0x2C, 0x86, 0x2D, 0x60, 0x4C, 0x99, 0xE1, 0x20, 0xEC, 0xF1, 0xE4, 0xF0, 0xB0, 0x08, +0xA5, 0xF0, 0x85, 0x2C, 0x85, 0x2D, 0x86, 0xF0, 0xA9, 0xC5, 0x20, 0xC0, 0xDE, 0x20, 0xF8, 0xE6, +0xE0, 0x50, 0xB0, 0xE2, 0x60, 0x20, 0xEC, 0xF1, 0xA4, 0xF0, 0x20, 0x75, 0xF7, 0x8A, 0x4C, 0x9F, +0xF3, 0x00, 0x20, 0xD9, 0xF8, 0xA4, 0x2C, 0x20, 0x75, 0xF7, 0xE0, 0x30, 0xB0, 0xC8, 0x4C, 0x96, +0xF7, 0x20, 0x09, 0xF2, 0x8A, 0xA8, 0x20, 0x75, 0xF7, 0xA5, 0xF0, 0x4C, 0x83, 0xF7, 0x00, 0x20, +0xF8, 0xE6, 0x8A, 0x4C, 0x64, 0xF8, 0x20, 0xF8, 0xE6, 0xCA, 0x8A, 0xC9, 0x18, 0xB0, 0xA7, 0x4C, +0x5B, 0xFB, 0x20, 0xF8, 0xE6, 0x8A, 0x49, 0xFF, 0xAA, 0xE8, 0x86, 0xF1, 0x60, 0x38, 0x90, 0x18, +0x66, 0xF2, 0x60, 0xA9, 0xFF, 0xD0, 0x02, 0xA9, 0x3F, 0xA2, 0x00, 0x85, 0x32, 0x86, 0xF3, 0x60, +0xA9, 0x7F, 0xA2, 0x40, 0xD0, 0xF5, 0x20, 0x67, 0xDD, 0x20, 0x52, 0xE7, 0xA5, 0x50, 0xC5, 0x6D, +0xA5, 0x51, 0xE5, 0x6E, 0xB0, 0x03, 0x4C, 0x10, 0xD4, 0xA5, 0x50, 0x85, 0x73, 0x85, 0x6F, 0xA5, +0x51, 0x85, 0x74, 0x85, 0x70, 0x60, 0x20, 0x67, 0xDD, 0x20, 0x52, 0xE7, 0xA5, 0x50, 0xC5, 0x73, +0xA5, 0x51, 0xE5, 0x74, 0xB0, 0xE0, 0xA5, 0x50, 0xC5, 0x69, 0xA5, 0x51, 0xE5, 0x6A, 0x90, 0xD6, +0xA5, 0x50, 0x85, 0x69, 0xA5, 0x51, 0x85, 0x6A, 0x4C, 0x6C, 0xD6, 0xA9, 0xAB, 0x20, 0xC0, 0xDE, +0xA5, 0xB8, 0x85, 0xF4, 0xA5, 0xB9, 0x85, 0xF5, 0x38, 0x66, 0xD8, 0xA5, 0x75, 0x85, 0xF6, 0xA5, +0x76, 0x85, 0xF7, 0x20, 0xA6, 0xD9, 0x4C, 0x98, 0xD9, 0x86, 0xDE, 0xA6, 0xF8, 0x86, 0xDF, 0xA5, +0x75, 0x85, 0xDA, 0xA5, 0x76, 0x85, 0xDB, 0xA5, 0x79, 0x85, 0xDC, 0xA5, 0x7A, 0x85, 0xDD, 0xA5, +0xF4, 0x85, 0xB8, 0xA5, 0xF5, 0x85, 0xB9, 0xA5, 0xF6, 0x85, 0x75, 0xA5, 0xF7, 0x85, 0x76, 0x20, +0xB7, 0x00, 0x20, 0x3E, 0xD9, 0x4C, 0xD2, 0xD7, 0xA5, 0xDA, 0x85, 0x75, 0xA5, 0xDB, 0x85, 0x76, +0xA5, 0xDC, 0x85, 0xB8, 0xA5, 0xDD, 0x85, 0xB9, 0xA6, 0xDF, 0x9A, 0x4C, 0xD2, 0xD7, 0x4C, 0xC9, +0xDE, 0xB0, 0xFB, 0xA6, 0xAF, 0x86, 0x69, 0xA6, 0xB0, 0x86, 0x6A, 0x20, 0x0C, 0xDA, 0x20, 0x1A, +0xD6, 0xA5, 0x9B, 0x85, 0x60, 0xA5, 0x9C, 0x85, 0x61, 0xA9, 0x2C, 0x20, 0xC0, 0xDE, 0x20, 0x0C, +0xDA, 0xE6, 0x50, 0xD0, 0x02, 0xE6, 0x51, 0x20, 0x1A, 0xD6, 0xA5, 0x9B, 0xC5, 0x60, 0xA5, 0x9C, +0xE5, 0x61, 0xB0, 0x01, 0x60, 0xA0, 0x00, 0xB1, 0x9B, 0x91, 0x60, 0xE6, 0x9B, 0xD0, 0x02, 0xE6, +0x9C, 0xE6, 0x60, 0xD0, 0x02, 0xE6, 0x61, 0xA5, 0x69, 0xC5, 0x9B, 0xA5, 0x6A, 0xE5, 0x9C, 0xB0, +0xE6, 0xA6, 0x61, 0xA4, 0x60, 0xD0, 0x01, 0xCA, 0x88, 0x86, 0x6A, 0x84, 0x69, 0x4C, 0xF2, 0xD4, +0xAD, 0x56, 0xC0, 0xAD, 0x53, 0xC0, 0x4C, 0xEC, 0xD8, 0xAD, 0x54, 0xC0, 0x4C, 0x39, 0xFB, 0x4A, +0x08, 0x20, 0x47, 0xF8, 0x28, 0xA9, 0x0F, 0x90, 0x02, 0x69, 0xE0, 0x85, 0x2E, 0x5A, 0x20, 0xBB, +0xF7, 0x90, 0x0A, 0xDA, 0xA5, 0x30, 0xAA, 0x4A, 0x8A, 0x6A, 0x38, 0x85, 0x30, 0x20, 0x0E, 0xF8, +0x90, 0x07, 0xAD, 0x54, 0xC0, 0x86, 0x30, 0xFA, 0x18, 0x7A, 0x60, 0x20, 0x3A, 0xF9, 0x49, 0x80, +0x2D, 0x18, 0xC0, 0x2D, 0x1F, 0xC0, 0x0A, 0x60, 0x2C, 0x55, 0xC0, 0x2C, 0x52, 0xC0, 0xA9, 0x40, +0xD0, 0x08, 0xA9, 0x20, 0x2C, 0x54, 0xC0, 0x2C, 0x53, 0xC0, 0x85, 0xE6, 0xAD, 0x57, 0xC0, 0xAD, +0x50, 0xC0, 0xA9, 0x00, 0x85, 0x1C, 0xA5, 0xE6, 0x85, 0x1B, 0xA0, 0x00, 0x84, 0x1A, 0xA5, 0x1C, +0x91, 0x1A, 0x20, 0x7E, 0xF4, 0xC8, 0xD0, 0xF6, 0xE6, 0x1B, 0xA5, 0x1B, 0x29, 0x1F, 0xD0, 0xEE, +0x60, 0x85, 0xE2, 0x86, 0xE0, 0x84, 0xE1, 0x48, 0x29, 0xC0, 0x85, 0x26, 0x4A, 0x4A, 0x05, 0x26, +0x85, 0x26, 0x68, 0x85, 0x27, 0x0A, 0x0A, 0x0A, 0x26, 0x27, 0x0A, 0x26, 0x27, 0x0A, 0x66, 0x26, +0xA5, 0x27, 0x29, 0x1F, 0x05, 0xE6, 0x85, 0x27, 0x8A, 0xC0, 0x00, 0xF0, 0x05, 0xA0, 0x23, 0x69, +0x04, 0xC8, 0xE9, 0x07, 0xB0, 0xFB, 0x84, 0xE5, 0xAA, 0xBD, 0xB9, 0xF4, 0x85, 0x30, 0x98, 0x4A, +0xA5, 0xE4, 0x85, 0x1C, 0xB0, 0x28, 0x60, 0x20, 0x11, 0xF4, 0xA5, 0x1C, 0x51, 0x26, 0x25, 0x30, +0x51, 0x26, 0x91, 0x26, 0x60, 0x10, 0x23, 0xA5, 0x30, 0x4A, 0xB0, 0x05, 0x49, 0xC0, 0x85, 0x30, +0x60, 0x88, 0x10, 0x02, 0xA0, 0x27, 0xA9, 0xC0, 0x85, 0x30, 0x84, 0xE5, 0xA5, 0x1C, 0x0A, 0xC9, +0xC0, 0x10, 0x06, 0xA5, 0x1C, 0x49, 0x7F, 0x85, 0x1C, 0x60, 0xA5, 0x30, 0x0A, 0x49, 0x80, 0x30, +0xDD, 0xA9, 0x81, 0xC8, 0xC0, 0x28, 0x90, 0xE0, 0xA0, 0x00, 0xB0, 0xDC, 0x18, 0xA5, 0xD1, 0x29, +0x04, 0xF0, 0x25, 0xA9, 0x7F, 0x25, 0x30, 0x31, 0x26, 0xD0, 0x19, 0xE6, 0xEA, 0xA9, 0x7F, 0x25, +0x30, 0x10, 0x11, 0x18, 0xA5, 0xD1, 0x29, 0x04, 0xF0, 0x0E, 0xB1, 0x26, 0x45, 0x1C, 0x25, 0x30, +0xD0, 0x02, 0xE6, 0xEA, 0x51, 0x26, 0x91, 0x26, 0xA5, 0xD1, 0x65, 0xD3, 0x29, 0x03, 0xC9, 0x02, +0x6A, 0xB0, 0x92, 0x30, 0x30, 0x18, 0xA5, 0x27, 0x2C, 0xB9, 0xF5, 0xD0, 0x22, 0x06, 0x26, 0xB0, +0x1A, 0x2C, 0xCD, 0xF4, 0xF0, 0x05, 0x69, 0x1F, 0x38, 0xB0, 0x12, 0x69, 0x23, 0x48, 0xA5, 0x26, +0x69, 0xB0, 0xB0, 0x02, 0x69, 0xF0, 0x85, 0x26, 0x68, 0xB0, 0x02, 0x69, 0x1F, 0x66, 0x26, 0x69, +0xFC, 0x85, 0x27, 0x60, 0x18, 0xA5, 0x27, 0x69, 0x04, 0x2C, 0xB9, 0xF5, 0xD0, 0xF3, 0x06, 0x26, +0x90, 0x18, 0x69, 0xE0, 0x18, 0x2C, 0x08, 0xF5, 0xF0, 0x12, 0xA5, 0x26, 0x69, 0x50, 0x49, 0xF0, +0xF0, 0x02, 0x49, 0xF0, 0x85, 0x26, 0xA5, 0xE6, 0x90, 0x02, 0x69, 0xE0, 0x66, 0x26, 0x90, 0xD1, +0x48, 0xA9, 0x00, 0x85, 0xE0, 0x85, 0xE1, 0x85, 0xE2, 0x68, 0x48, 0x38, 0xE5, 0xE0, 0x48, 0x8A, +0xE5, 0xE1, 0x85, 0xD3, 0xB0, 0x0A, 0x68, 0x49, 0xFF, 0x69, 0x01, 0x48, 0xA9, 0x00, 0xE5, 0xD3, +0x85, 0xD1, 0x85, 0xD5, 0x68, 0x85, 0xD0, 0x85, 0xD4, 0x68, 0x85, 0xE0, 0x86, 0xE1, 0x98, 0x18, +0xE5, 0xE2, 0x90, 0x04, 0x49, 0xFF, 0x69, 0xFE, 0x85, 0xD2, 0x84, 0xE2, 0x66, 0xD3, 0x38, 0xE5, +0xD0, 0xAA, 0xA9, 0xFF, 0xE5, 0xD1, 0x85, 0x1D, 0xA4, 0xE5, 0xB0, 0x05, 0x0A, 0x20, 0x65, 0xF4, +0x38, 0xA5, 0xD4, 0x65, 0xD2, 0x85, 0xD4, 0xA5, 0xD5, 0xE9, 0x00, 0x85, 0xD5, 0xB1, 0x26, 0x45, +0x1C, 0x25, 0x30, 0x51, 0x26, 0x91, 0x26, 0xE8, 0xD0, 0x04, 0xE6, 0x1D, 0xF0, 0x62, 0xA5, 0xD3, +0xB0, 0xDA, 0x20, 0xD3, 0xF4, 0x18, 0xA5, 0xD4, 0x65, 0xD0, 0x85, 0xD4, 0xA5, 0xD5, 0x65, 0xD1, +0x50, 0xD9, 0x81, 0x82, 0x84, 0x88, 0x90, 0xA0, 0xC0, 0x1C, 0xFF, 0xFE, 0xFA, 0xF4, 0xEC, 0xE1, +0xD4, 0xC5, 0xB4, 0xA1, 0x8D, 0x78, 0x61, 0x49, 0x31, 0x18, 0xFF, 0xA5, 0x26, 0x0A, 0xA5, 0x27, +0x29, 0x03, 0x2A, 0x05, 0x26, 0x0A, 0x0A, 0x0A, 0x85, 0xE2, 0xA5, 0x27, 0x4A, 0x4A, 0x29, 0x07, +0x05, 0xE2, 0x85, 0xE2, 0xA5, 0xE5, 0x0A, 0x65, 0xE5, 0x0A, 0xAA, 0xCA, 0xA5, 0x30, 0x29, 0x7F, +0xE8, 0x4A, 0xD0, 0xFC, 0x85, 0xE1, 0x8A, 0x18, 0x65, 0xE5, 0x90, 0x02, 0xE6, 0xE1, 0x85, 0xE0, +0x60, 0x86, 0x1A, 0x84, 0x1B, 0xAA, 0x4A, 0x4A, 0x4A, 0x4A, 0x85, 0xD3, 0x8A, 0x29, 0x0F, 0xAA, +0xBC, 0xBA, 0xF5, 0x84, 0xD0, 0x49, 0x0F, 0xAA, 0xBC, 0xBB, 0xF5, 0xC8, 0x84, 0xD2, 0xA4, 0xE5, +0xA2, 0x00, 0x86, 0xEA, 0xA1, 0x1A, 0x85, 0xD1, 0xA2, 0x80, 0x86, 0xD4, 0x86, 0xD5, 0xA6, 0xE7, +0xA5, 0xD4, 0x38, 0x65, 0xD0, 0x85, 0xD4, 0x90, 0x04, 0x20, 0xB3, 0xF4, 0x18, 0xA5, 0xD5, 0x65, +0xD2, 0x85, 0xD5, 0x90, 0x03, 0x20, 0xB4, 0xF4, 0xCA, 0xD0, 0xE5, 0xA5, 0xD1, 0x4A, 0x4A, 0x4A, +0xD0, 0xD4, 0xE6, 0x1A, 0xD0, 0x02, 0xE6, 0x1B, 0xA1, 0x1A, 0xD0, 0xCA, 0x60, 0x86, 0x1A, 0x84, +0x1B, 0xAA, 0x4A, 0x4A, 0x4A, 0x4A, 0x85, 0xD3, 0x8A, 0x29, 0x0F, 0xAA, 0xBC, 0xBA, 0xF5, 0x84, +0xD0, 0x49, 0x0F, 0xAA, 0xBC, 0xBB, 0xF5, 0xC8, 0x84, 0xD2, 0xA4, 0xE5, 0xA2, 0x00, 0x86, 0xEA, +0xA1, 0x1A, 0x85, 0xD1, 0xA2, 0x80, 0x86, 0xD4, 0x86, 0xD5, 0xA6, 0xE7, 0xA5, 0xD4, 0x38, 0x65, +0xD0, 0x85, 0xD4, 0x90, 0x04, 0x20, 0x9C, 0xF4, 0x18, 0xA5, 0xD5, 0x65, 0xD2, 0x85, 0xD5, 0x90, +0x03, 0x20, 0x9D, 0xF4, 0xCA, 0xD0, 0xE5, 0xA5, 0xD1, 0x4A, 0x4A, 0x4A, 0xD0, 0xD4, 0xE6, 0x1A, +0xD0, 0x02, 0xE6, 0x1B, 0xA1, 0x1A, 0xD0, 0xCA, 0x60, 0x20, 0x67, 0xDD, 0x20, 0x52, 0xE7, 0xA4, +0x51, 0xA6, 0x50, 0xC0, 0x01, 0x90, 0x06, 0xD0, 0x1D, 0xE0, 0x18, 0xB0, 0x19, 0x8A, 0x48, 0x98, +0x48, 0xA9, 0x2C, 0x20, 0xC0, 0xDE, 0x20, 0xF8, 0xE6, 0xE0, 0xC0, 0xB0, 0x09, 0x86, 0x9D, 0x68, +0xA8, 0x68, 0xAA, 0xA5, 0x9D, 0x60, 0x4C, 0x06, 0xF2, 0x20, 0xF8, 0xE6, 0xE0, 0x08, 0xB0, 0xF6, +0xBD, 0xF6, 0xF6, 0x85, 0xE4, 0x60, 0x00, 0x2A, 0x55, 0x7F, 0x80, 0xAA, 0xD5, 0xFF, 0xC9, 0xC1, +0xF0, 0x0D, 0x20, 0xB9, 0xF6, 0x20, 0x57, 0xF4, 0x20, 0xB7, 0x00, 0xC9, 0xC1, 0xD0, 0xE6, 0x20, +0xC0, 0xDE, 0x20, 0xB9, 0xF6, 0x84, 0x9D, 0xA8, 0x8A, 0xA6, 0x9D, 0x20, 0x3A, 0xF5, 0x4C, 0x08, +0xF7, 0x20, 0xF8, 0xE6, 0x86, 0xF9, 0x60, 0x20, 0xF8, 0xE6, 0x86, 0xE7, 0x60, 0x20, 0xF8, 0xE6, +0xA5, 0xE8, 0x85, 0x1A, 0xA5, 0xE9, 0x85, 0x1B, 0x8A, 0xA2, 0x00, 0xC1, 0x1A, 0xF0, 0x02, 0xB0, +0xA5, 0x0A, 0x90, 0x03, 0xE6, 0x1B, 0x18, 0xA8, 0xB1, 0x1A, 0x65, 0x1A, 0xAA, 0xC8, 0xB1, 0x1A, +0x65, 0xE9, 0x85, 0x1B, 0x86, 0x1A, 0x20, 0xB7, 0x00, 0xC9, 0xC5, 0xD0, 0x09, 0x20, 0xC0, 0xDE, +0x20, 0xB9, 0xF6, 0x20, 0x11, 0xF4, 0xA5, 0xF9, 0x60, 0x20, 0x2D, 0xF7, 0x4C, 0x05, 0xF6, 0x20, +0x2D, 0xF7, 0x4C, 0x61, 0xF6, 0x20, 0xCB, 0xF3, 0xB0, 0x04, 0xC0, 0x28, 0xB0, 0xC1, 0xC0, 0x50, +0xB0, 0xBD, 0x60, 0x48, 0xA5, 0x2D, 0xC9, 0x30, 0x68, 0xB0, 0xB4, 0x48, 0x20, 0x9F, 0xF3, 0x68, +0xC5, 0x2D, 0x1A, 0x90, 0xF6, 0x60, 0x8A, 0xA4, 0xF0, 0x20, 0x9F, 0xF3, 0xC4, 0x2C, 0xB0, 0xF5, +0xC8, 0x20, 0xAD, 0xF3, 0x80, 0xF6, 0x48, 0x20, 0xBB, 0xF7, 0x68, 0x08, 0x20, 0x71, 0xF8, 0x28, +0x90, 0x08, 0x8D, 0x54, 0xC0, 0xC9, 0x08, 0x0A, 0x29, 0x0F, 0x60, 0x20, 0xCB, 0xF3, 0x90, 0x0A, +0x98, 0x49, 0x01, 0x4A, 0xA8, 0x90, 0x03, 0xAD, 0x55, 0xC0, 0x60, 0x8A, 0x2C, 0x1F, 0xC0, 0x30, +0x12, 0x2C, 0x85, 0x24, 0x38, 0x8A, 0xE5, 0x24, 0x60, 0xA9, 0x40, 0x85, 0x14, 0x20, 0xE3, 0xDF, +0x64, 0x14, 0x60, 0xED, 0x7B, 0x05, 0x60, 0x20, 0xF8, 0xE6, 0xCA, 0xA9, 0x28, 0xC5, 0x21, 0xB0, +0x02, 0xA5, 0x21, 0x20, 0xD2, 0xF7, 0x86, 0x24, 0x90, 0xDE, 0xAA, 0x20, 0xFB, 0xDA, 0x80, 0xEB, +0x4A, 0x08, 0x20, 0x47, 0xF8, 0x28, 0xA9, 0x0F, 0x90, 0x02, 0x69, 0xE0, 0x85, 0x2E, 0xB1, 0x26, +0x45, 0x30, 0x25, 0x2E, 0x51, 0x26, 0x91, 0x26, 0x60, 0x20, 0x00, 0xF8, 0xC4, 0x2C, 0xB0, 0x11, +0xC8, 0x20, 0x0E, 0xF8, 0x90, 0xF6, 0x69, 0x01, 0x48, 0x20, 0x00, 0xF8, 0x68, 0xC5, 0x2D, 0x90, +0xF5, 0x60, 0xA0, 0x2F, 0xD0, 0x02, 0xA0, 0x27, 0x84, 0x2D, 0xA0, 0x27, 0xA9, 0x00, 0x85, 0x30, +0x20, 0x28, 0xF8, 0x88, 0x10, 0xF6, 0x60, 0x48, 0x4A, 0x29, 0x03, 0x09, 0x04, 0x85, 0x27, 0x68, +0x29, 0x18, 0x90, 0x02, 0x69, 0x7F, 0x85, 0x26, 0x0A, 0x0A, 0x05, 0x26, 0x85, 0x26, 0x60, 0xA5, +0x30, 0x18, 0x69, 0x03, 0x29, 0x0F, 0x85, 0x30, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x30, 0x85, 0x30, +0x60, 0x4A, 0x08, 0x20, 0x47, 0xF8, 0xB1, 0x26, 0x28, 0x90, 0x04, 0x4A, 0x4A, 0x4A, 0x4A, 0x29, +0x0F, 0x60, 0xF4, 0xE1, 0xE1, 0xAB, 0xAB, 0x60, 0xA0, 0x94, 0x80, 0x10, 0xA1, 0x3A, 0x38, 0x90, +0x18, 0x4C, 0xCC, 0xFF, 0x4C, 0x59, 0xA9, 0x4C, 0x5E, 0xA9, 0xA0, 0xA0, 0x08, 0x18, 0xFB, 0x28, +0xE2, 0x30, 0x48, 0xAD, 0x36, 0xC0, 0x48, 0x09, 0x80, 0x8D, 0x36, 0xC0, 0x22, 0x88, 0x9F, 0xFF, +0x68, 0x8D, 0x36, 0xC0, 0x68, 0x08, 0x38, 0xFB, 0x28, 0x60, 0x9C, 0x00, 0x08, 0x18, 0xFB, 0xC2, +0x30, 0xA2, 0x00, 0x08, 0x9B, 0xC8, 0xA9, 0xFE, 0xB7, 0x54, 0x00, 0x00, 0x80, 0xE7, 0x00, 0x00, +0xA0, 0x99, 0x80, 0xC8, 0x08, 0x18, 0xFB, 0x28, 0x6B, 0x20, 0xF8, 0xE6, 0xE0, 0x50, 0xB0, 0x11, +0x86, 0xF0, 0x20, 0xBE, 0xDE, 0x20, 0xF8, 0xE6, 0xE0, 0x50, 0x86, 0x2C, 0x86, 0x2D, 0x4C, 0x0C, +0xF2, 0x4C, 0x06, 0xF2, 0x20, 0xBA, 0xF8, 0x20, 0x60, 0xFB, 0xA0, 0x9D, 0x20, 0x9C, 0xF8, 0x20, +0xDA, 0xF9, 0xAF, 0x41, 0x01, 0xE1, 0x30, 0x01, 0x60, 0x18, 0xFB, 0x22, 0x12, 0x92, 0xFF, 0x38, +0xFB, 0x4C, 0x62, 0xFA, 0x5A, 0xA0, 0x9A, 0x90, 0x02, 0xA0, 0x9F, 0x20, 0x9C, 0xF8, 0x7A, 0x60, +0xEB, 0xAF, 0x36, 0x01, 0xE1, 0x4A, 0x90, 0x06, 0xD0, 0x04, 0x8F, 0x36, 0x01, 0xE1, 0xEB, 0x60, +0xC6, 0xAE, 0xA0, 0xC2, 0xE1, 0xE3, 0xE8, 0xED, 0xE1, 0xEE, 0xAD, 0x46, 0xC0, 0x0A, 0x0A, 0x60, +0x98, 0x20, 0xDA, 0xFD, 0x8A, 0x4C, 0xDA, 0xFD, 0xA2, 0x03, 0xA9, 0xA0, 0x20, 0xED, 0xFD, 0xCA, +0xD0, 0xF8, 0x60, 0x38, 0xA5, 0x2F, 0xA4, 0x3B, 0xAA, 0x10, 0x01, 0x88, 0x65, 0x3A, 0x90, 0x01, +0xC8, 0x60, 0xE2, 0x40, 0x18, 0xFB, 0x08, 0xC2, 0x30, 0x50, 0xB8, 0xF4, 0xE1, 0x00, 0xF4, 0x70, +0x01, 0xA2, 0x03, 0x12, 0x70, 0x03, 0xA2, 0x03, 0x13, 0x22, 0x00, 0x00, 0xE1, 0xB0, 0xEB, 0x28, +0xA9, 0x08, 0x0C, 0x41, 0xC0, 0xFB, 0x60, 0xBC, 0xB2, 0xBE, 0x9A, 0xEF, 0xC4, 0xE9, 0xA9, 0xBB, +0xA6, 0xA4, 0x06, 0x95, 0x07, 0x02, 0x05, 0x00, 0xF1, 0xEB, 0x93, 0xA7, 0xC6, 0x99, 0x96, 0xED, +0xEC, 0x9B, 0xF5, 0xF3, 0xEA, 0xEE, 0xAB, 0xAD, 0xA3, 0xF8, 0x9C, 0xC7, 0xAC, 0x12, 0xC9, 0xDA, +0xDB, 0x8C, 0xDD, 0x96, 0xEB, 0x0A, 0x0A, 0xDC, 0xFD, 0x83, 0x7F, 0xD4, 0xD0, 0xCF, 0xD6, 0x0A, +0x0A, 0xF5, 0x00, 0xD5, 0xD8, 0xD7, 0xD1, 0xD3, 0xD2, 0xBE, 0xCE, 0xE0, 0x4D, 0x0A, 0x0A, 0xB3, +0xCD, 0x18, 0xFB, 0x08, 0x22, 0x03, 0x1C, 0xFF, 0x28, 0xFB, 0x78, 0xA9, 0x10, 0x0C, 0x27, 0xC0, +0x58, 0xAF, 0x38, 0x01, 0xE1, 0x8D, 0x2D, 0xC0, 0xA4, 0x00, 0x5A, 0xA4, 0x01, 0x5A, 0xA9, 0x00, +0x48, 0xA9, 0xC8, 0x64, 0x00, 0x85, 0x01, 0x18, 0x68, 0x2A, 0x48, 0xA0, 0x05, 0xC6, 0x01, 0xA5, +0x01, 0xC9, 0xC4, 0x90, 0x14, 0xB1, 0x00, 0xD9, 0x01, 0xFB, 0xD0, 0xEB, 0x88, 0x88, 0x10, 0xF5, +0xB1, 0x00, 0xF0, 0xE4, 0x1A, 0xD0, 0xE0, 0xF0, 0xDF, 0x68, 0x7A, 0x84, 0x01, 0x7A, 0x84, 0x00, +0x4C, 0xDB, 0xFF, 0xAF, 0xD9, 0x02, 0xE1, 0xD0, 0x02, 0x1A, 0x60, 0xA2, 0x00, 0xAD, 0x05, 0xC3, +0xC9, 0x38, 0xD0, 0x0A, 0xAD, 0x07, 0xC3, 0xC9, 0x18, 0xD0, 0x03, 0xE8, 0xD0, 0xEF, 0x60, 0x00, +0x4C, 0x74, 0xC0, 0x20, 0x3A, 0xFF, 0x20, 0xDA, 0xF9, 0x4C, 0x6C, 0xFF, 0x28, 0x20, 0x4C, 0xFF, +0x68, 0x85, 0x3A, 0x68, 0x85, 0x3B, 0x6C, 0xF0, 0x03, 0xA0, 0x93, 0x20, 0x9C, 0xF8, 0x80, 0xE3, +0x00, 0x00, 0xA9, 0x01, 0x0C, 0x29, 0xC0, 0xA9, 0xFB, 0x78, 0xD8, 0x1B, 0x20, 0x36, 0xFE, 0xA9, +0x0C, 0x8D, 0x68, 0xC0, 0xA0, 0x09, 0x20, 0x9C, 0xF8, 0xAD, 0xFF, 0xCF, 0x2C, 0x10, 0xC0, 0x20, +0x23, 0xFA, 0xD0, 0x03, 0x20, 0x12, 0xFD, 0x20, 0x9A, 0xF8, 0xAD, 0xF3, 0x03, 0x49, 0xA5, 0xCD, +0xF4, 0x03, 0xD0, 0x12, 0xAD, 0xF2, 0x03, 0xD0, 0x42, 0xA9, 0xE0, 0xCD, 0xF3, 0x03, 0xD0, 0x3B, +0xA0, 0x03, 0x4C, 0xE6, 0xFE, 0x00, 0x20, 0xF4, 0xF8, 0xA2, 0x05, 0xBD, 0xFC, 0xFA, 0x9D, 0xEF, +0x03, 0xCA, 0xD0, 0xF7, 0x80, 0x2B, 0x85, 0x01, 0x64, 0x00, 0xA0, 0x05, 0xC6, 0x01, 0xA9, 0x00, +0xA5, 0x01, 0xC9, 0xC0, 0xF0, 0x32, 0x8D, 0xF8, 0x07, 0xB1, 0x00, 0xD9, 0x01, 0xFB, 0xD0, 0xEA, +0x88, 0x88, 0x10, 0xF5, 0x6C, 0x00, 0x00, 0xA0, 0xA5, 0x80, 0x1F, 0x20, 0xD1, 0xF9, 0x6C, 0xF2, +0x03, 0xAF, 0xE8, 0x02, 0xE1, 0xF0, 0x0D, 0xC9, 0x07, 0xF0, 0x39, 0x90, 0x02, 0xA9, 0x05, 0x09, +0xC0, 0x1A, 0x80, 0xC2, 0xA9, 0xC8, 0x80, 0xBE, 0xA0, 0x98, 0x4C, 0x9C, 0xF8, 0x59, 0xFA, 0x00, +0xE0, 0x45, 0x20, 0xFF, 0x00, 0xFF, 0x03, 0xFF, 0x3C, 0xC1, 0xF0, 0xF0, 0xEC, 0xE5, 0xA0, 0xDD, +0xDB, 0xC4, 0xC2, 0xC1, 0xFF, 0xC3, 0xFF, 0xFF, 0xCD, 0xC1, 0xD8, 0xD9, 0xD0, 0xD3, 0x4C, 0xEB, +0xFB, 0x4C, 0xE6, 0xFB, 0x2C, 0x2D, 0xC0, 0x30, 0xC6, 0x4C, 0xE0, 0xC7, 0x4C, 0x7B, 0xA9, 0xA9, +0x00, 0x85, 0x48, 0xAD, 0x56, 0xC0, 0xAD, 0x54, 0xC0, 0xAD, 0x51, 0xC0, 0xA9, 0x00, 0xF0, 0x0B, +0xAD, 0x50, 0xC0, 0xAD, 0x53, 0xC0, 0x20, 0x36, 0xF8, 0xA9, 0x14, 0x85, 0x22, 0xA9, 0x00, 0x85, +0x20, 0xA0, 0x0C, 0x80, 0xA5, 0x7F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x85, 0x25, 0x4C, 0x22, 0xFC, +0x20, 0x58, 0xFC, 0xA0, 0xA4, 0x80, 0x93, 0x05, 0x07, 0x0B, 0xFB, 0x38, 0x18, 0x01, 0xD6, 0xAD, +0xF3, 0x03, 0x49, 0xA5, 0x8D, 0xF4, 0x03, 0x60, 0xC9, 0x8D, 0xD0, 0x18, 0xAC, 0x00, 0xC0, 0x10, +0x13, 0xC0, 0x93, 0xD0, 0x0F, 0x2C, 0x10, 0xC0, 0xAC, 0x00, 0xC0, 0x10, 0xFB, 0xC0, 0x83, 0xF0, +0x03, 0x2C, 0x10, 0xC0, 0x80, 0x67, 0xA8, 0xB9, 0x48, 0xFA, 0x20, 0xAC, 0xFB, 0x20, 0x02, 0xFD, +0xC9, 0xCE, 0xB0, 0x08, 0xC9, 0xC9, 0x90, 0x04, 0xC9, 0xCC, 0xD0, 0xEA, 0xC9, 0xB8, 0x38, 0xD0, +0x7B, 0x80, 0x01, 0x06, 0x20, 0x2B, 0xFA, 0xD0, 0x73, 0x20, 0x90, 0xFC, 0x4C, 0xEF, 0xFE, 0x00, +0xE0, 0x48, 0x4A, 0x29, 0x03, 0x09, 0x04, 0x85, 0x29, 0x68, 0x29, 0x18, 0x90, 0x02, 0x69, 0x7F, +0x85, 0x28, 0x0A, 0x0A, 0x05, 0x28, 0x85, 0x28, 0x60, 0xC9, 0x87, 0xD0, 0x1F, 0xA0, 0x9E, 0x80, +0x48, 0xEA, 0x80, 0xF9, 0x80, 0xF7, 0xBD, 0x64, 0xC0, 0x10, 0xFB, 0xA0, 0x95, 0x80, 0x3A, 0x00, +0xA4, 0x24, 0x91, 0x28, 0xE6, 0x24, 0xA5, 0x24, 0xC5, 0x21, 0xB0, 0x66, 0x60, 0x80, 0x5D, 0xB0, +0xEF, 0xA8, 0x10, 0xEC, 0xC9, 0x8D, 0xF0, 0x5A, 0xC9, 0x8A, 0xF0, 0x5A, 0xC9, 0x88, 0xD0, 0x75, +0x5A, 0xA0, 0x9B, 0x20, 0x9C, 0xF8, 0x30, 0x63, 0x7A, 0x60, 0xA5, 0x22, 0xC5, 0x25, 0xB0, 0xDC, +0xC6, 0x25, 0xA5, 0x25, 0x85, 0x28, 0x98, 0xA0, 0x04, 0x4C, 0x9C, 0xF8, 0x49, 0xC0, 0xF0, 0x28, +0x69, 0xFD, 0x90, 0xC0, 0xF0, 0xDA, 0x69, 0xFD, 0x90, 0x2C, 0xF0, 0xDE, 0x69, 0xFD, 0x90, 0x5C, +0xD0, 0xBA, 0xA0, 0x0A, 0xD0, 0xE3, 0x2C, 0x1F, 0xC0, 0x10, 0x04, 0xA0, 0x00, 0x80, 0xDA, 0x98, +0x48, 0x20, 0x78, 0xFB, 0x68, 0xA4, 0x35, 0x60, 0xA0, 0x05, 0x80, 0xCD, 0xEB, 0x4C, 0xEB, 0xFC, +0x00, 0x00, 0xA9, 0x00, 0x85, 0x24, 0xE6, 0x25, 0xA5, 0x25, 0xC5, 0x23, 0x90, 0xB6, 0xC6, 0x25, +0xA0, 0x06, 0x80, 0xB5, 0x90, 0x02, 0x25, 0x32, 0x4C, 0xF7, 0xFD, 0xA5, 0x21, 0xA0, 0x9C, 0x20, +0x9C, 0xF8, 0x7A, 0x80, 0x95, 0xC9, 0x9E, 0xF0, 0x03, 0x4C, 0xD9, 0xFB, 0xA9, 0x81, 0x80, 0x02, +0xA9, 0x40, 0x8F, 0x36, 0x01, 0xE1, 0x60, 0xA0, 0x97, 0x80, 0x8E, 0x00, 0x38, 0x90, 0x18, 0x84, +0x2A, 0xA0, 0x07, 0xB0, 0x84, 0xC8, 0x80, 0x81, 0x48, 0xAD, 0x36, 0xC0, 0xEB, 0xA9, 0x80, 0x1C, +0x36, 0xC0, 0x80, 0x25, 0xE6, 0x42, 0xD0, 0x02, 0xE6, 0x43, 0xA5, 0x3C, 0xC5, 0x3E, 0xA5, 0x3D, +0xE5, 0x3F, 0xE6, 0x3C, 0xD0, 0x02, 0xE6, 0x3D, 0x60, 0x60, 0xB9, 0x00, 0x02, 0xC8, 0xC9, 0xE1, +0x90, 0x06, 0xC9, 0xFB, 0xB0, 0x02, 0x29, 0xDF, 0x60, 0x68, 0x38, 0x48, 0xE9, 0x01, 0xD0, 0xFC, +0x68, 0xE9, 0x01, 0xD0, 0xF6, 0xEB, 0x8D, 0x36, 0xC0, 0xEB, 0x60, 0xAF, 0x36, 0x01, 0xE1, 0x0A, +0x30, 0x20, 0xEB, 0x90, 0x08, 0x8F, 0x34, 0x01, 0xE1, 0xA9, 0x01, 0x80, 0x95, 0xC9, 0xA0, 0x4C, +0xFF, 0xFB, 0x20, 0x0C, 0xFD, 0xA0, 0x01, 0x80, 0x90, 0x4E, 0xF8, 0x07, 0xA0, 0x0B, 0xD0, 0x0F, +0x80, 0x06, 0xA0, 0xA2, 0x80, 0x83, 0x00, 0x00, 0x6C, 0x38, 0x00, 0xA0, 0x03, 0x80, 0xE8, 0x20, +0x9C, 0xF8, 0x80, 0xEC, 0x20, 0x20, 0xF9, 0xB0, 0x4C, 0xC9, 0x88, 0x80, 0x25, 0x00, 0x00, 0x20, +0x02, 0xFD, 0x20, 0xA0, 0xFB, 0x20, 0x09, 0xFD, 0xC9, 0x9B, 0xF0, 0xF3, 0x60, 0x6C, 0xFE, 0x03, +0xA0, 0x0D, 0x20, 0x9C, 0xF8, 0xA4, 0x24, 0x9D, 0x00, 0x02, 0x20, 0xED, 0xFD, 0xBD, 0x00, 0x02, +0x80, 0xD2, 0xF0, 0x1D, 0xC9, 0x98, 0xF0, 0x0A, 0xE0, 0xF8, 0x90, 0x03, 0x20, 0x3A, 0xFF, 0xE8, +0xD0, 0x13, 0xA9, 0xDC, 0x20, 0xED, 0xFD, 0x20, 0x8E, 0xFD, 0xA5, 0x33, 0x20, 0xED, 0xFD, 0xA2, +0x01, 0x8A, 0xF0, 0xF3, 0xCA, 0x20, 0x35, 0xFD, 0xC9, 0x95, 0xD0, 0x08, 0xB1, 0x28, 0x2C, 0x1F, +0xC0, 0x30, 0xBD, 0xEA, 0x20, 0xBE, 0xFD, 0xC9, 0x8D, 0xD0, 0xBF, 0x20, 0x9C, 0xFC, 0xA9, 0x8D, +0x80, 0x5B, 0xA4, 0x3D, 0xA6, 0x3C, 0x20, 0x8E, 0xFD, 0x20, 0x40, 0xF9, 0xA0, 0x00, 0xA9, 0xBA, +0x80, 0x4B, 0x20, 0x75, 0xFE, 0x05, 0x3C, 0x85, 0x3E, 0xA5, 0x3D, 0x85, 0x3F, 0x4C, 0x6D, 0xFE, +0x48, 0x68, 0xF0, 0xF9, 0xC9, 0xAE, 0xF0, 0xF5, 0x5A, 0xA0, 0xA1, 0x4C, 0x1B, 0xF9, 0xC9, 0xFF, +0xD0, 0x11, 0xEB, 0xAF, 0x36, 0x01, 0xE1, 0x0A, 0xEB, 0x90, 0x06, 0x2C, 0x1F, 0xC0, 0x10, 0x03, +0x1A, 0x29, 0x88, 0x9D, 0x00, 0x02, 0x60, 0x4C, 0x46, 0xFC, 0x48, 0x4A, 0x4A, 0x4A, 0x4A, 0x20, +0xE5, 0xFD, 0x68, 0x29, 0x0F, 0x09, 0xB0, 0xC9, 0xBA, 0x90, 0x02, 0x69, 0x06, 0x6C, 0x36, 0x00, +0x48, 0xC9, 0xA0, 0x4C, 0x74, 0xFC, 0x48, 0x84, 0x35, 0xA8, 0x68, 0x80, 0xDA, 0xC6, 0x34, 0xF0, +0xA1, 0xCA, 0xD0, 0x0C, 0xC9, 0xBA, 0xD0, 0xA8, 0x4C, 0xDA, 0xFE, 0xA4, 0x34, 0xB9, 0xFF, 0x01, +0x85, 0x31, 0x60, 0x18, 0xFB, 0x5C, 0xA0, 0x00, 0xE1, 0x38, 0xFB, 0x4C, 0xF8, 0x03, 0x00, 0xAD, +0x55, 0xFB, 0xAE, 0x57, 0xFB, 0xAC, 0x59, 0xFB, 0x18, 0x60, 0x00, 0x00, 0xB1, 0x3C, 0x91, 0x42, +0x20, 0xB4, 0xFC, 0x90, 0xF7, 0x60, 0x8F, 0x00, 0x01, 0x01, 0x8F, 0x01, 0x01, 0x01, 0xA0, 0xA3, +0x20, 0x9C, 0xF8, 0x20, 0x84, 0xFE, 0x20, 0x2F, 0xFB, 0x20, 0x93, 0xFE, 0x80, 0x3B, 0xA9, 0x80, +0x1C, 0x29, 0xC0, 0xAD, 0x51, 0xC0, 0xAD, 0x52, 0xC0, 0x64, 0x22, 0x80, 0x53, 0x00, 0xA0, 0x83, +0x80, 0x11, 0x8A, 0xF0, 0x07, 0xB5, 0x3C, 0x95, 0x3A, 0xCA, 0x10, 0xF9, 0x60, 0x48, 0x98, 0x09, +0x80, 0xA8, 0x68, 0x80, 0x36, 0xA5, 0x21, 0xC9, 0x48, 0xA9, 0x0F, 0xB0, 0x02, 0xA9, 0x07, 0x60, +0xA0, 0x3F, 0xD0, 0x02, 0xA0, 0xFF, 0x84, 0x32, 0x60, 0xA9, 0x00, 0x85, 0x3E, 0xA2, 0x38, 0xA0, +0x1B, 0xD0, 0x08, 0xA9, 0x00, 0x85, 0x3E, 0xA2, 0x36, 0xA0, 0xF0, 0xA5, 0x3E, 0x29, 0x0F, 0xF0, +0x04, 0x09, 0xC0, 0xA0, 0x00, 0x94, 0x00, 0x95, 0x01, 0xA0, 0x0E, 0x80, 0x36, 0x4C, 0x03, 0xE0, +0xAD, 0x54, 0xC0, 0x60, 0x80, 0x5A, 0x20, 0x62, 0xFE, 0x20, 0x3F, 0xFF, 0x6C, 0x3A, 0x00, 0xAD, +0xD0, 0x03, 0xC9, 0x4C, 0xF0, 0x01, 0x60, 0x4C, 0xD0, 0x03, 0x4C, 0xD7, 0xFA, 0x60, 0xC8, 0xC8, +0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0x80, +0x8C, 0xA0, 0x96, 0x4C, 0x9C, 0xF8, 0x8C, 0xF2, 0x03, 0x20, 0xD1, 0xF9, 0x4C, 0x00, 0xE0, 0x68, +0x68, 0xA9, 0x98, 0x4C, 0xED, 0xFD, 0x20, 0xFD, 0xFD, 0x68, 0x68, 0x80, 0x6F, 0x60, 0xAF, 0x3E, +0x01, 0xE1, 0x8F, 0x3F, 0x01, 0xE1, 0xA2, 0x01, 0xB5, 0x3E, 0x95, 0x42, 0xCA, 0x10, 0xF9, 0x60, +0xC8, 0x80, 0xBB, 0x20, 0xCA, 0xFC, 0xC9, 0xA0, 0xF0, 0xF9, 0x60, 0xB0, 0x6D, 0xC9, 0xA0, 0xD0, +0x28, 0xB9, 0x00, 0x02, 0xA2, 0x07, 0xC9, 0x8D, 0xF0, 0x7D, 0xC8, 0xD0, 0x63, 0xA9, 0xC5, 0x20, +0xED, 0xFD, 0xA9, 0xD2, 0x20, 0xED, 0xFD, 0x20, 0xED, 0xFD, 0xA9, 0x87, 0x4C, 0xED, 0xFD, 0xA5, +0x48, 0x48, 0xA5, 0x45, 0xA6, 0x46, 0xA4, 0x47, 0x28, 0x60, 0x85, 0x45, 0x86, 0x46, 0x84, 0x47, +0x08, 0x68, 0x85, 0x48, 0xBA, 0x86, 0x49, 0xD8, 0x60, 0x20, 0x43, 0xFE, 0x80, 0x07, 0xA9, 0xAA, +0x85, 0x33, 0x4C, 0x67, 0xFD, 0xD8, 0x4C, 0x43, 0xFA, 0x20, 0xE1, 0xFE, 0xEA, 0x20, 0x5E, 0xFF, +0x20, 0xD1, 0xFF, 0x20, 0x88, 0xF8, 0x84, 0x34, 0xA0, 0x25, 0x88, 0x30, 0xE8, 0xD9, 0x87, 0xF9, +0xD0, 0xF8, 0x20, 0xBE, 0xFF, 0xA4, 0x34, 0x4C, 0x73, 0xFF, 0xA2, 0x03, 0x0A, 0x0A, 0x0A, 0x0A, +0x0A, 0x26, 0x3E, 0x26, 0x3F, 0xCA, 0x10, 0xF8, 0xA5, 0x31, 0xD0, 0x06, 0xB5, 0x3F, 0x95, 0x3D, +0x95, 0x41, 0xE8, 0xF0, 0xF3, 0xD0, 0x06, 0xA2, 0x00, 0x86, 0x3E, 0x86, 0x3F, 0x20, 0xCA, 0xFC, +0xEA, 0x49, 0xB0, 0xC9, 0x0A, 0x90, 0xD3, 0x69, 0x88, 0xC9, 0xFA, 0x4C, 0x1B, 0xFF, 0xA9, 0xFE, +0x48, 0xB9, 0xAC, 0xF9, 0x48, 0xA5, 0x31, 0xA0, 0x00, 0x84, 0x31, 0x60, 0xA0, 0x00, 0x80, 0x20, +0xEF, 0x64, 0x34, 0x20, 0xC7, 0xFF, 0xAD, 0x36, 0xC0, 0x29, 0x7F, 0x0F, 0x37, 0x01, 0xE1, 0x8D, +0x36, 0xC0, 0x60, 0x00, 0x7B, 0xC0, 0x71, 0xC0, 0x79, 0xC0, 0xFB, 0x03, 0xE6, 0xE2, 0x74, 0xC0, +0x4C, 0x14, 0xF9, 0x00, 0x7B, 0xC0, 0xE9, 0x67, 0x79, 0xC0, 0xFB, 0x03, 0x62, 0xFA, 0x74, 0xC0}; + + diff --git a/Common/svnversion.h b/Common/svnversion.h new file mode 100644 index 0000000..6b52a2c --- /dev/null +++ b/Common/svnversion.h @@ -0,0 +1,56 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#define ACTIVEGSMAJOR 3 +#define ACTIVEGSMINOR 7 +#ifdef KEGS_BETAVERSION +#define ACTIVEGSSTATE " BETA" +#else +#define ACTIVEGSSTATE "" +#endif + +#define ACTIVEGSBUILD 1199 +#define ACTIVEGSDATE "2015-06-02 22:41:06" + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#if defined(_DEBUG)|| defined(_GLIBCXX_DEBUG) +#define ACTIVEGSRELEASE " [Debug]" +#else +#define ACTIVEGSRELEASE +#endif + +#if defined(_WIN32) + #if defined(XP_WIN32) + #define ACTIVEGSAPP "Win32/Plugin" + #elif defined(_USRDLL) + #define ACTIVEGSAPP "Win32/ActiveX" + #else + #define ACTIVEGSAPP "Win32" + #endif +#elif defined(ACTIVEGS_ANDROID) + #define ACTIVEGSAPP "Android" + #elif defined(ACTIVEIPHONE) + # define ACTIVEGSAPP "iPhone" + #else + // MAC + # if defined(ACTIVEGSPLUGIN) + #define ACTIVEGSAPP "MacOSX/Plugin" + #else + #define ACTIVEGSAPP "MacOSX" + # endif + #endif + +#ifdef __LP64__ +#define ACTIVEGSARCHI " (64BITS)" +#else +#define ACTIVEGSARCHI +#endif +#define ACTIVEGSBUILDSTR TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) ACTIVEGSRELEASE +#define ACTIVEGSVERSIONSTR "ActiveGS v" TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) ACTIVEGSRELEASE ACTIVEGSSTATE +#define ACTIVEGSVERSIONSTRFULL "ActiveGS " ACTIVEGSAPP " v" TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) ACTIVEGSRELEASE ACTIVEGSSTATE ACTIVEGSARCHI + diff --git a/Common/svnversion.h.ref b/Common/svnversion.h.ref new file mode 100644 index 0000000..9e1c08f --- /dev/null +++ b/Common/svnversion.h.ref @@ -0,0 +1,51 @@ + +#define ACTIVEGSMAJOR $MAJORVER$ +#define ACTIVEGSMINOR $MINORVER$ +#ifdef KEGS_BETAVERSION +#define ACTIVEGSSTATE " BETA" +#else +#define ACTIVEGSSTATE "" +#endif + +#define ACTIVEGSBUILD $WCREV$ +#define ACTIVEGSDATE "$WCNOW$" + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#if defined(_DEBUG)|| defined(_GLIBCXX_DEBUG) +#define ACTIVEGSRELEASE " [Debug]" +#else +#define ACTIVEGSRELEASE +#endif + +#if defined(_WIN32) + #if defined(XP_WIN32) + #define ACTIVEGSAPP "Win32/Plugin" + #elif defined(_USRDLL) + #define ACTIVEGSAPP "Win32/ActiveX" + #else + #define ACTIVEGSAPP "Win32" + #endif +#elif defined(ACTIVEGS_ANDROID) + #define ACTIVEGSAPP "Android" + #elif defined(ACTIVEIPHONE) + # define ACTIVEGSAPP "iPhone" + #else + // MAC + # if defined(ACTIVEGSPLUGIN) + #define ACTIVEGSAPP "MacOSX/Plugin" + #else + #define ACTIVEGSAPP "MacOSX" + # endif + #endif + +#ifdef __LP64__ +#define ACTIVEGSARCHI " (64BITS)" +#else +#define ACTIVEGSARCHI +#endif +#define ACTIVEGSBUILDSTR TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) ACTIVEGSRELEASE +#define ACTIVEGSVERSIONSTR "ActiveGS v" TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) ACTIVEGSRELEASE ACTIVEGSSTATE +#define ACTIVEGSVERSIONSTRFULL "ActiveGS " ACTIVEGSAPP " v" TOSTRING(ACTIVEGSMAJOR) "." TOSTRING(ACTIVEGSMINOR) "." TOSTRING(ACTIVEGSBUILD) ACTIVEGSRELEASE ACTIVEGSSTATE ACTIVEGSARCHI + diff --git a/DefaultPackage/BLUE_HELMET.FTA b/DefaultPackage/BLUE_HELMET.FTA new file mode 100644 index 0000000..f7ee374 Binary files /dev/null and b/DefaultPackage/BLUE_HELMET.FTA differ diff --git a/DefaultPackage/BOUNCIN_FERNO.FTA b/DefaultPackage/BOUNCIN_FERNO.FTA new file mode 100644 index 0000000..ce003d9 Binary files /dev/null and b/DefaultPackage/BOUNCIN_FERNO.FTA differ diff --git a/DefaultPackage/DELTA.FTA b/DefaultPackage/DELTA.FTA new file mode 100644 index 0000000..20537ff Binary files /dev/null and b/DefaultPackage/DELTA.FTA differ diff --git a/DefaultPackage/MINIPRIX.FTA b/DefaultPackage/MINIPRIX.FTA new file mode 100644 index 0000000..1eec112 Binary files /dev/null and b/DefaultPackage/MINIPRIX.FTA differ diff --git a/DefaultPackage/MODULAE.FTA b/DefaultPackage/MODULAE.FTA new file mode 100644 index 0000000..b5188c3 Binary files /dev/null and b/DefaultPackage/MODULAE.FTA differ diff --git a/DefaultPackage/NOISETRACKER.FTA b/DefaultPackage/NOISETRACKER.FTA new file mode 100644 index 0000000..8f0b356 Binary files /dev/null and b/DefaultPackage/NOISETRACKER.FTA differ diff --git a/DefaultPackage/NUCLEUS.FTA b/DefaultPackage/NUCLEUS.FTA new file mode 100644 index 0000000..bd5221b Binary files /dev/null and b/DefaultPackage/NUCLEUS.FTA differ diff --git a/DefaultPackage/Oil_Landers.fta b/DefaultPackage/Oil_Landers.fta new file mode 100644 index 0000000..124926c Binary files /dev/null and b/DefaultPackage/Oil_Landers.fta differ diff --git a/DefaultPackage/PHOTONIX.FTA b/DefaultPackage/PHOTONIX.FTA new file mode 100644 index 0000000..a35e866 Binary files /dev/null and b/DefaultPackage/PHOTONIX.FTA differ diff --git a/DefaultPackage/SPACE_HARRIER.FTA b/DefaultPackage/SPACE_HARRIER.FTA new file mode 100644 index 0000000..dd44917 Binary files /dev/null and b/DefaultPackage/SPACE_HARRIER.FTA differ diff --git a/DefaultPackage/StarWizard (2002).fta b/DefaultPackage/StarWizard (2002).fta new file mode 100644 index 0000000..37fe95b Binary files /dev/null and b/DefaultPackage/StarWizard (2002).fta differ diff --git a/DefaultPackage/XMASDEMO.FTA b/DefaultPackage/XMASDEMO.FTA new file mode 100644 index 0000000..1b2ba8e Binary files /dev/null and b/DefaultPackage/XMASDEMO.FTA differ diff --git a/DefaultPackage/bestof.activegsxml b/DefaultPackage/bestof.activegsxml new file mode 100644 index 0000000..03e4fb8 --- /dev/null +++ b/DefaultPackage/bestof.activegsxml @@ -0,0 +1,42 @@ + + + + Best of + + + + Karateka + 1984 + Jordan Mechner + + thumb_karateka.png + APPLE2 + + karateka.dsk.zip + 6 + joyXScale:1200;joyYScale:1200 + speed:slow;border:black;background:black;font:white;driveEmulation:fast + + + + Prince of Persia + 1989 + Jordan Mechner + + thumb_pop.png + + pop_1.png + pop_2.png + pop_3.png + APPLE2 + pop.2mg.zip + 5 + joyXScale:1000;joyYScale:1200 + speed:normal;border:black;background:black;font:white;driveEmulation:fast + + + \ No newline at end of file diff --git a/DefaultPackage/bluehelmet_1.png b/DefaultPackage/bluehelmet_1.png new file mode 100644 index 0000000..26aa66a Binary files /dev/null and b/DefaultPackage/bluehelmet_1.png differ diff --git a/DefaultPackage/bluehelmet_2.png b/DefaultPackage/bluehelmet_2.png new file mode 100644 index 0000000..f4b7daa Binary files /dev/null and b/DefaultPackage/bluehelmet_2.png differ diff --git a/DefaultPackage/bouncinferno_1.png b/DefaultPackage/bouncinferno_1.png new file mode 100644 index 0000000..d250961 Binary files /dev/null and b/DefaultPackage/bouncinferno_1.png differ diff --git a/DefaultPackage/bouncinferno_2.png b/DefaultPackage/bouncinferno_2.png new file mode 100644 index 0000000..f3f234d Binary files /dev/null and b/DefaultPackage/bouncinferno_2.png differ diff --git a/DefaultPackage/bouncinferno_3.png b/DefaultPackage/bouncinferno_3.png new file mode 100644 index 0000000..979438a Binary files /dev/null and b/DefaultPackage/bouncinferno_3.png differ diff --git a/DefaultPackage/bouncinferno_4.png b/DefaultPackage/bouncinferno_4.png new file mode 100644 index 0000000..81ca2f3 Binary files /dev/null and b/DefaultPackage/bouncinferno_4.png differ diff --git a/DefaultPackage/bouncinferno_5.png b/DefaultPackage/bouncinferno_5.png new file mode 100644 index 0000000..8b765ba Binary files /dev/null and b/DefaultPackage/bouncinferno_5.png differ diff --git a/DefaultPackage/bouncinferno_6.png b/DefaultPackage/bouncinferno_6.png new file mode 100644 index 0000000..48050db Binary files /dev/null and b/DefaultPackage/bouncinferno_6.png differ diff --git a/DefaultPackage/bouncinferno_7.png b/DefaultPackage/bouncinferno_7.png new file mode 100644 index 0000000..8e44545 Binary files /dev/null and b/DefaultPackage/bouncinferno_7.png differ diff --git a/DefaultPackage/delta_1.png b/DefaultPackage/delta_1.png new file mode 100644 index 0000000..56a48e1 Binary files /dev/null and b/DefaultPackage/delta_1.png differ diff --git a/DefaultPackage/delta_2.png b/DefaultPackage/delta_2.png new file mode 100644 index 0000000..5abd10d Binary files /dev/null and b/DefaultPackage/delta_2.png differ diff --git a/DefaultPackage/delta_3.png b/DefaultPackage/delta_3.png new file mode 100644 index 0000000..581100d Binary files /dev/null and b/DefaultPackage/delta_3.png differ diff --git a/DefaultPackage/delta_4.png b/DefaultPackage/delta_4.png new file mode 100644 index 0000000..4ddd731 Binary files /dev/null and b/DefaultPackage/delta_4.png differ diff --git a/DefaultPackage/delta_5.png b/DefaultPackage/delta_5.png new file mode 100644 index 0000000..c8a14ba Binary files /dev/null and b/DefaultPackage/delta_5.png differ diff --git a/DefaultPackage/delta_6.png b/DefaultPackage/delta_6.png new file mode 100644 index 0000000..3e729c9 Binary files /dev/null and b/DefaultPackage/delta_6.png differ diff --git a/DefaultPackage/delta_7.png b/DefaultPackage/delta_7.png new file mode 100644 index 0000000..97d00fc Binary files /dev/null and b/DefaultPackage/delta_7.png differ diff --git a/DefaultPackage/floby1.png b/DefaultPackage/floby1.png new file mode 100644 index 0000000..674d82b Binary files /dev/null and b/DefaultPackage/floby1.png differ diff --git a/DefaultPackage/floby2.png b/DefaultPackage/floby2.png new file mode 100644 index 0000000..3445e54 Binary files /dev/null and b/DefaultPackage/floby2.png differ diff --git a/DefaultPackage/floby3.png b/DefaultPackage/floby3.png new file mode 100644 index 0000000..f72eeb5 Binary files /dev/null and b/DefaultPackage/floby3.png differ diff --git a/DefaultPackage/flobynoid (2002).dsk.zip b/DefaultPackage/flobynoid (2002).dsk.zip new file mode 100644 index 0000000..c55df90 Binary files /dev/null and b/DefaultPackage/flobynoid (2002).dsk.zip differ diff --git a/DefaultPackage/harrier1.png b/DefaultPackage/harrier1.png new file mode 100644 index 0000000..12a9557 Binary files /dev/null and b/DefaultPackage/harrier1.png differ diff --git a/DefaultPackage/list.activegsxml b/DefaultPackage/list.activegsxml new file mode 100644 index 0000000..2747b69 --- /dev/null +++ b/DefaultPackage/list.activegsxml @@ -0,0 +1,361 @@ + + + + + ActiveGS - Best of FTA + + + + Flobynoid + 1987 + Second Sight Software + + + The game was fully programmed by entering each byte code directly onto the sectors using a disk editor (Moby Disk II): + years after, it is hard to imagine that it could even run but, at that time, we didn't know what an assembler was + (nor the difference between object and source code).
+ + Under the Second Sight Software Label, the was presented at the French Apple Expo in 1987, + and sent to major US publishing companies in the USA (Epyx, DataSoft, Electronics Art, ...). + It received very good feedback from those professionals, which impressed the teenagers we were.
+ + Unfortunately, the Apple II was fading away and publishing new titles did not make much sense + while the IIGS was just being launched : eventually, the game finished its life as a freeware for the pleasure of players all around the world! + ]]>
+ floby3.png + APPLE2 + flobynoid (2002).dsk.zip + floby1.png + floby2.png + floby3.png + floby_editor.png + 6 +
+ + + + Star Wizard + 1989 + Sergent Claude + + + 2GS + StarWizard (2002).fta + starwizard_3.png + starwizard_2.png + starwizard_4.png + starwizard_5.png + 5 + + + + + Nucleus + 1989 + FTA + The demo that has made FTA the famous beyond their Dijon & Aix-Les-Bains hideouts !

+

+ It has evolved from a simple parametric-based animation (thanks to Arkanoid for the sprites!) to a full 3D-powered demo with modern graphics and fancy musics. + Even though there was a bug in the 3D calculation (the shapes should never have collapsed onto themselves), people loved the demo. +

+

+ In less than 2 weeks, the first version spread quickly from Dijon to Cupertino, + where the Green Software Engineering team reviewed it. Unfortunately, due to a glitch in a low level drive command, it was incompatible with the upcoming ROM03 Motherboard which Apple was about to release. + Through their Switzerland office, Apple sent us a prototype of the ROM03 motherboard to make it work in time for the upcoming AppleFest in San Francisco, + where then VP Jean-Louis Gassée used it during his talk. +

+

The rest is history ;)

+ +

+ Eventually, Nucleus was later customized to serve as an advertisment for the SPIT company (unfortunately, no copy could be retrieved) +

+ ]]>
+ nucleus_2.png + nucleus.png + nucleus_2.png + nucleus_c.png + nucleus_t.png + 2GSNUCLEUS.FTA + 5 +
+ + + Photonix II + 1990 + FTA + + One of the successes of the first version of Nucleus was its very fast loading routines (even though most of the users + only know the ROM03 version which does not include them!) + Those fast routines came originally from SpeedySmith, a very fast disk copier but with limited features and raw (not to say crude) interface. +

+

+ After having written Nucleus during the summer, the FTA team gathered again the next month (just before going back to college) to create a new program that would be a mix between + Speedysmith (for the copying features) and Nucleus (for the fancy graphics) : this is how Photonix started! +

+

+ Thanks to the speed of the copy, its large set of features (it was often used by Mac users to quickly format disks for example), and its appealing interface, it became + a very successful shareware program, and we were very pleased to receive (snail) mails from people around the world from persons liking our work and asking us to "keep up the good work" : + : it was then that we learnt how popular that expression was!
+ A commercial version of Photonix was later developed (Photonix II) and sold by Toolbox, before finishing its life as an abandonware. +

+

+ 15 years later, Photonix was recently brought to life as a prior-artifact in an anti-virus + patent infrigment lawsuit + : good programs never die! +

+ ]]>
+ photonix_2.png + photonix_1.png + photonix_2.png + 2GS + PHOTONIX.FTA + 5 +
+ + + Mini Prix + 1990 + FTA + A very realistic racing game simulation that did not want to compromise the fluidity of the control for the graphic immersion of the player ! + The game could easily win the-smallest-rendering-screen-ever-being-used-in-a-racing-game award, but nevertheless, the game was fun to play: easy to learn, hard to master! + miniprix_2.png + 2GS + MINIPRIX.FTA + miniprix_1.png + miniprix_2.png + miniprix_3.png + 5 + + + + Blue Helmet + 1990 + FTA + + + Even though Blue Helmet was far from being finished, it provided some pretty cool racing experience at the decent frame rate. + ]]> + + bluehelmet_1.png + 2GS + BLUE_HELMET.FTA + bluehelmet_1.png + bluehelmet_2.png + 5 + + + + + Space Harrier Demo + 1990 + FTA + + This project emerged after having seen the Atari ST version that was really appealing, and we wanted to build something similar to bring that hi-speed spirit onto the IIGS. + Actually, the project started with Atari ST development in order to extract (not to say rip) all the sprites from the computer memory while the game was running, + and then to transfer the files back to the IIGS. Exchanging information between computers seems so easy today, but at that time, it has required to build a custom + NULL Modem cable, and find communication software on both machines that would implement the ZModem protocol in a similar way: needless to say that the whole process took several weeks!
+ With those nice looking assets available, it encouraged us to develop some great graphic routines that would nicely use them.
+ The result is one of our favorite productions, and even now, the version easily matches the official Sega version on iPhone (ok, their version is based on the Megadrive port) + ]]>
+ harrier1.png + 2GS + SPACE_HARRIER.FTA + harrier1.png + harrier_1.png + harrier_2.png + harrier_5.png + 5 +
+ + + Modulae + 1990 + FTA + Quite often,a demo starts from a set of small and independent routines developed without any idea on where they could be used. But at a certain point, and that's the magic + of software development, everything naturally fits together : alchemy in action!

+

This is how Moduale was created by reuniting all those routines into a nice package : its 3D content was outstanding at that time, and + it was the most polished program we ever produced.

+ ]]>
+ modulae_4.png + 2GS + MODULAE.FTA + modulae_1.png + modulae_10.png + modulae_11.png + modulae_2.png + modulae_3.png + modulae_4.png + modulae_5.png + modulae_6.png + modulae_7.png + modulae_8.png + modulae_9.png + 5 +
+ + + + XMAS Demo + 1990 + FTA/MRZ + After the success of our early programs, we kept on experimenting new techniques to go beyond what we had already done : new options were made possible by having a finer + control over the Apple IIGS hardware (pedal to the metal!), but on the other hand, it meant reprogramming almost every aspect of the computer. In retrospect, a lot of hard work was spent on invisible stuff, but + altogether, it is that continuous effort on every front that gives such a polished result. They were told it was impossible, so they did it. +

+

This is how the XMas demo was built, even though the technical exploits slightly outgrow the demo content : it was the first demo with music-enabled loading routines, + overscan scrolls, and more important entirely coded in Geneva!

+ ]]>
+ + xmas_2.png + 2GS + XMASDEMO.FTA + xmas_1.png + xmas_2.png + xmas_3.png + xmas_4.png + xmas_5.png + xmas_6.png + xmas_7.png + xmas_8.png + 5 +
+ + + + + + Oil Landers + 1991 + FTA + A Stellar7 tribute! + 2GS + Oil_Landers.fta + oillanders_1.png + oillanders_1.png + oillanders_2.png + oillanders_3.png + oillanders_4.png + oillanders_5.png + 5 + + + + Boucin'Ferno + 1991 + FTA + Marble madness look alike! + bouncinferno_4.png + 2GS + BOUNCIN_FERNO.FTA + bouncinferno_1.png + bouncinferno_2.png + bouncinferno_3.png + bouncinferno_4.png + bouncinferno_5.png + bouncinferno_6.png + bouncinferno_7.png + 5 + + + + Delta Demo + 1991 + FTA + + The final demo from the FTA

+

Even if it looks like a simple demo (as there's just one part), the Delta Demo contained some highly tuned code.
+ * First, for the first time on the IIGS, a MOD based music (thanks Moby!) that would go beyond the 64KB limit of the Ensoniq. + Those routines were later exposed in the NoiseTracker suite
+ *Second, a multi-threading simulator (!) : all the display was performed during the VBL interrupt, while the main processor + was creating the code to display the next object. Once the code was ready, then it was being used by the VBL interrupt, while the main processor works off the next object. + Quite fancy at that time, and this is what has allowed us to create 3D wireframe based real-time (or so) animation at 50hz per second on a 2.8Mhz processor! +

+

After having delivered so many products in 2 years, it was time for the team to move onto something else, but this version was a nice goodbye gift. +

For the record, it was called the Delta demo to honour an Amiga Demo Maker who used to create everything himself : code, art & music! + ]]> + + delta_3.png + 2GS + DELTA.FTA + delta_1.png + delta_2.png + delta_3.png + delta_4.png + delta_5.png + delta_6.png + delta_7.png + 5 + + + + + \ No newline at end of file diff --git a/DefaultPackage/list.xsl b/DefaultPackage/list.xsl new file mode 100644 index 0000000..d7330b9 --- /dev/null +++ b/DefaultPackage/list.xsl @@ -0,0 +1,11 @@ + + + +

Title

+ +
  • + +
  • +
    + + \ No newline at end of file diff --git a/DefaultPackage/miniprix_1.png b/DefaultPackage/miniprix_1.png new file mode 100644 index 0000000..51833a2 Binary files /dev/null and b/DefaultPackage/miniprix_1.png differ diff --git a/DefaultPackage/miniprix_2.png b/DefaultPackage/miniprix_2.png new file mode 100644 index 0000000..7be7325 Binary files /dev/null and b/DefaultPackage/miniprix_2.png differ diff --git a/DefaultPackage/miniprix_3.png b/DefaultPackage/miniprix_3.png new file mode 100644 index 0000000..8ccdba3 Binary files /dev/null and b/DefaultPackage/miniprix_3.png differ diff --git a/DefaultPackage/modulae_1.png b/DefaultPackage/modulae_1.png new file mode 100644 index 0000000..4fb6b11 Binary files /dev/null and b/DefaultPackage/modulae_1.png differ diff --git a/DefaultPackage/modulae_10.png b/DefaultPackage/modulae_10.png new file mode 100644 index 0000000..9d1df6b Binary files /dev/null and b/DefaultPackage/modulae_10.png differ diff --git a/DefaultPackage/modulae_11.png b/DefaultPackage/modulae_11.png new file mode 100644 index 0000000..fa71c9f Binary files /dev/null and b/DefaultPackage/modulae_11.png differ diff --git a/DefaultPackage/modulae_2.png b/DefaultPackage/modulae_2.png new file mode 100644 index 0000000..8d49ba5 Binary files /dev/null and b/DefaultPackage/modulae_2.png differ diff --git a/DefaultPackage/modulae_3.png b/DefaultPackage/modulae_3.png new file mode 100644 index 0000000..77b6923 Binary files /dev/null and b/DefaultPackage/modulae_3.png differ diff --git a/DefaultPackage/modulae_4.png b/DefaultPackage/modulae_4.png new file mode 100644 index 0000000..da81d22 Binary files /dev/null and b/DefaultPackage/modulae_4.png differ diff --git a/DefaultPackage/modulae_5.png b/DefaultPackage/modulae_5.png new file mode 100644 index 0000000..361e79e Binary files /dev/null and b/DefaultPackage/modulae_5.png differ diff --git a/DefaultPackage/modulae_6.png b/DefaultPackage/modulae_6.png new file mode 100644 index 0000000..29b0e52 Binary files /dev/null and b/DefaultPackage/modulae_6.png differ diff --git a/DefaultPackage/modulae_7.png b/DefaultPackage/modulae_7.png new file mode 100644 index 0000000..68805f8 Binary files /dev/null and b/DefaultPackage/modulae_7.png differ diff --git a/DefaultPackage/modulae_8.png b/DefaultPackage/modulae_8.png new file mode 100644 index 0000000..ee3b160 Binary files /dev/null and b/DefaultPackage/modulae_8.png differ diff --git a/DefaultPackage/modulae_9.png b/DefaultPackage/modulae_9.png new file mode 100644 index 0000000..5e98b12 Binary files /dev/null and b/DefaultPackage/modulae_9.png differ diff --git a/DefaultPackage/noisetracker_0.png b/DefaultPackage/noisetracker_0.png new file mode 100644 index 0000000..54a8f25 Binary files /dev/null and b/DefaultPackage/noisetracker_0.png differ diff --git a/DefaultPackage/noisetracker_1.png b/DefaultPackage/noisetracker_1.png new file mode 100644 index 0000000..9c8e7e3 Binary files /dev/null and b/DefaultPackage/noisetracker_1.png differ diff --git a/DefaultPackage/noisetracker_2.png b/DefaultPackage/noisetracker_2.png new file mode 100644 index 0000000..fc50b75 Binary files /dev/null and b/DefaultPackage/noisetracker_2.png differ diff --git a/DefaultPackage/noisetracker_3.png b/DefaultPackage/noisetracker_3.png new file mode 100644 index 0000000..099523b Binary files /dev/null and b/DefaultPackage/noisetracker_3.png differ diff --git a/DefaultPackage/nucleus.png b/DefaultPackage/nucleus.png new file mode 100644 index 0000000..fe491fa Binary files /dev/null and b/DefaultPackage/nucleus.png differ diff --git a/DefaultPackage/nucleus_2.png b/DefaultPackage/nucleus_2.png new file mode 100644 index 0000000..f938d0a Binary files /dev/null and b/DefaultPackage/nucleus_2.png differ diff --git a/DefaultPackage/nucleus_c.png b/DefaultPackage/nucleus_c.png new file mode 100644 index 0000000..a1917fb Binary files /dev/null and b/DefaultPackage/nucleus_c.png differ diff --git a/DefaultPackage/nucleus_t.png b/DefaultPackage/nucleus_t.png new file mode 100644 index 0000000..f47fe01 Binary files /dev/null and b/DefaultPackage/nucleus_t.png differ diff --git a/DefaultPackage/oillanders_1.png b/DefaultPackage/oillanders_1.png new file mode 100644 index 0000000..591ca1e Binary files /dev/null and b/DefaultPackage/oillanders_1.png differ diff --git a/DefaultPackage/oillanders_2.png b/DefaultPackage/oillanders_2.png new file mode 100644 index 0000000..e01a45d Binary files /dev/null and b/DefaultPackage/oillanders_2.png differ diff --git a/DefaultPackage/oillanders_3.png b/DefaultPackage/oillanders_3.png new file mode 100644 index 0000000..fa50372 Binary files /dev/null and b/DefaultPackage/oillanders_3.png differ diff --git a/DefaultPackage/oillanders_4.png b/DefaultPackage/oillanders_4.png new file mode 100644 index 0000000..71aa394 Binary files /dev/null and b/DefaultPackage/oillanders_4.png differ diff --git a/DefaultPackage/oillanders_5.png b/DefaultPackage/oillanders_5.png new file mode 100644 index 0000000..195516c Binary files /dev/null and b/DefaultPackage/oillanders_5.png differ diff --git a/DefaultPackage/photonix_1.png b/DefaultPackage/photonix_1.png new file mode 100644 index 0000000..a8b3353 Binary files /dev/null and b/DefaultPackage/photonix_1.png differ diff --git a/DefaultPackage/photonix_2.png b/DefaultPackage/photonix_2.png new file mode 100644 index 0000000..2044f54 Binary files /dev/null and b/DefaultPackage/photonix_2.png differ diff --git a/DefaultPackage/poms_1.png b/DefaultPackage/poms_1.png new file mode 100644 index 0000000..9290728 Binary files /dev/null and b/DefaultPackage/poms_1.png differ diff --git a/DefaultPackage/poms_2.png b/DefaultPackage/poms_2.png new file mode 100644 index 0000000..e210697 Binary files /dev/null and b/DefaultPackage/poms_2.png differ diff --git a/DefaultPackage/poms_3.png b/DefaultPackage/poms_3.png new file mode 100644 index 0000000..35eacd4 Binary files /dev/null and b/DefaultPackage/poms_3.png differ diff --git a/DefaultPackage/poms_4.png b/DefaultPackage/poms_4.png new file mode 100644 index 0000000..6047c78 Binary files /dev/null and b/DefaultPackage/poms_4.png differ diff --git a/DefaultPackage/poms_5.png b/DefaultPackage/poms_5.png new file mode 100644 index 0000000..fb58c5c Binary files /dev/null and b/DefaultPackage/poms_5.png differ diff --git a/DefaultPackage/poms_6.png b/DefaultPackage/poms_6.png new file mode 100644 index 0000000..2fa5800 Binary files /dev/null and b/DefaultPackage/poms_6.png differ diff --git a/DefaultPackage/starwizard.png b/DefaultPackage/starwizard.png new file mode 100644 index 0000000..d421c99 Binary files /dev/null and b/DefaultPackage/starwizard.png differ diff --git a/DefaultPackage/starwizard_2.png b/DefaultPackage/starwizard_2.png new file mode 100644 index 0000000..649a323 Binary files /dev/null and b/DefaultPackage/starwizard_2.png differ diff --git a/DefaultPackage/starwizard_3.png b/DefaultPackage/starwizard_3.png new file mode 100644 index 0000000..9579d7c Binary files /dev/null and b/DefaultPackage/starwizard_3.png differ diff --git a/DefaultPackage/starwizard_4.png b/DefaultPackage/starwizard_4.png new file mode 100644 index 0000000..889372c Binary files /dev/null and b/DefaultPackage/starwizard_4.png differ diff --git a/DefaultPackage/starwizard_5.png b/DefaultPackage/starwizard_5.png new file mode 100644 index 0000000..b3dda1f Binary files /dev/null and b/DefaultPackage/starwizard_5.png differ diff --git a/DefaultPackage/thumb_bouncinferno.png b/DefaultPackage/thumb_bouncinferno.png new file mode 100644 index 0000000..4b5e232 Binary files /dev/null and b/DefaultPackage/thumb_bouncinferno.png differ diff --git a/DefaultPackage/thumb_delta.png b/DefaultPackage/thumb_delta.png new file mode 100644 index 0000000..9f0c28f Binary files /dev/null and b/DefaultPackage/thumb_delta.png differ diff --git a/DefaultPackage/thumb_floby.png b/DefaultPackage/thumb_floby.png new file mode 100644 index 0000000..50939e1 Binary files /dev/null and b/DefaultPackage/thumb_floby.png differ diff --git a/DefaultPackage/thumb_gsos.png b/DefaultPackage/thumb_gsos.png new file mode 100644 index 0000000..2d5aa01 Binary files /dev/null and b/DefaultPackage/thumb_gsos.png differ diff --git a/DefaultPackage/thumb_harrier.png b/DefaultPackage/thumb_harrier.png new file mode 100644 index 0000000..58e0179 Binary files /dev/null and b/DefaultPackage/thumb_harrier.png differ diff --git a/DefaultPackage/thumb_karateka.png b/DefaultPackage/thumb_karateka.png new file mode 100755 index 0000000..a6a0558 Binary files /dev/null and b/DefaultPackage/thumb_karateka.png differ diff --git a/DefaultPackage/thumb_modulae.png b/DefaultPackage/thumb_modulae.png new file mode 100644 index 0000000..2c8e7f0 Binary files /dev/null and b/DefaultPackage/thumb_modulae.png differ diff --git a/DefaultPackage/thumb_noisetracker.png b/DefaultPackage/thumb_noisetracker.png new file mode 100644 index 0000000..36c0589 Binary files /dev/null and b/DefaultPackage/thumb_noisetracker.png differ diff --git a/DefaultPackage/thumb_nucleus.png b/DefaultPackage/thumb_nucleus.png new file mode 100644 index 0000000..6cfa48a Binary files /dev/null and b/DefaultPackage/thumb_nucleus.png differ diff --git a/DefaultPackage/thumb_photonix.png b/DefaultPackage/thumb_photonix.png new file mode 100644 index 0000000..23a90bb Binary files /dev/null and b/DefaultPackage/thumb_photonix.png differ diff --git a/DefaultPackage/thumb_poms.png b/DefaultPackage/thumb_poms.png new file mode 100644 index 0000000..5e38698 Binary files /dev/null and b/DefaultPackage/thumb_poms.png differ diff --git a/DefaultPackage/thumb_pop.png b/DefaultPackage/thumb_pop.png new file mode 100644 index 0000000..3738203 Binary files /dev/null and b/DefaultPackage/thumb_pop.png differ diff --git a/DefaultPackage/thumb_system6.png b/DefaultPackage/thumb_system6.png new file mode 100644 index 0000000..2d5aa01 Binary files /dev/null and b/DefaultPackage/thumb_system6.png differ diff --git a/DefaultPackage/thumb_xmas.png b/DefaultPackage/thumb_xmas.png new file mode 100644 index 0000000..1d6d9b8 Binary files /dev/null and b/DefaultPackage/thumb_xmas.png differ diff --git a/DefaultPackage/xmas_1.png b/DefaultPackage/xmas_1.png new file mode 100644 index 0000000..3a206a0 Binary files /dev/null and b/DefaultPackage/xmas_1.png differ diff --git a/DefaultPackage/xmas_2.png b/DefaultPackage/xmas_2.png new file mode 100644 index 0000000..0d820ea Binary files /dev/null and b/DefaultPackage/xmas_2.png differ diff --git a/DefaultPackage/xmas_3.png b/DefaultPackage/xmas_3.png new file mode 100644 index 0000000..6cd52d6 Binary files /dev/null and b/DefaultPackage/xmas_3.png differ diff --git a/DefaultPackage/xmas_4.png b/DefaultPackage/xmas_4.png new file mode 100644 index 0000000..f8514af Binary files /dev/null and b/DefaultPackage/xmas_4.png differ diff --git a/DefaultPackage/xmas_5.png b/DefaultPackage/xmas_5.png new file mode 100644 index 0000000..7c6e010 Binary files /dev/null and b/DefaultPackage/xmas_5.png differ diff --git a/DefaultPackage/xmas_6.png b/DefaultPackage/xmas_6.png new file mode 100644 index 0000000..09dbe04 Binary files /dev/null and b/DefaultPackage/xmas_6.png differ diff --git a/DefaultPackage/xmas_7.png b/DefaultPackage/xmas_7.png new file mode 100644 index 0000000..6c0e81a Binary files /dev/null and b/DefaultPackage/xmas_7.png differ diff --git a/DefaultPackage/xmas_8.png b/DefaultPackage/xmas_8.png new file mode 100644 index 0000000..5521ece Binary files /dev/null and b/DefaultPackage/xmas_8.png differ diff --git a/Drivers/activegs_driver.cpp b/Drivers/activegs_driver.cpp new file mode 100644 index 0000000..81e0a5e --- /dev/null +++ b/Drivers/activegs_driver.cpp @@ -0,0 +1,17 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../kegs/src/driver.h" + +extern void default_config_load_roms(); +void activegs_driver() +{ + g_driver.x_config_load_roms = default_config_load_roms; +#if !defined(ACTIVEGSKARATEKA) && defined(DRIVER_IOS) + extern void x_notify_eject(); + g_driver.x_notify_eject = x_notify_eject; +#endif +} diff --git a/Libraries/libpng/png.cpp b/Libraries/libpng/png.cpp new file mode 100644 index 0000000..62b86e1 --- /dev/null +++ b/Libraries/libpng/png.cpp @@ -0,0 +1,922 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#define PNG_NO_EXTERN +#include "png.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_2_37 Your_png_h_is_not_version_1_2_37; + +/* Version information for C files. This had better match the version + * string defined in png.h. */ + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* png_libpng_ver was changed to a function in version 1.0.5c */ +PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING; + +#ifdef PNG_READ_SUPPORTED + +/* png_sig was changed to a function in version 1.0.5c */ +/* Place to hold the signature string for a PNG file. */ +PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; +#endif /* PNG_READ_SUPPORTED */ + +/* Invoke global declarations for constant strings for known chunk types */ +PNG_IHDR; +PNG_IDAT; +PNG_IEND; +PNG_PLTE; +PNG_bKGD; +PNG_cHRM; +PNG_gAMA; +PNG_hIST; +PNG_iCCP; +PNG_iTXt; +PNG_oFFs; +PNG_pCAL; +PNG_sCAL; +PNG_pHYs; +PNG_sBIT; +PNG_sPLT; +PNG_sRGB; +PNG_tEXt; +PNG_tIME; +PNG_tRNS; +PNG_zTXt; + +#ifdef PNG_READ_SUPPORTED +/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + +/* Start of interlace block */ +PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + +/* Offset to next interlace block */ +PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + +/* Start of interlace block in the y direction */ +PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + +/* Offset to next interlace block in the y direction */ +PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + +/* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h +PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; +*/ + +/* Mask to determine which pixels are valid in a pass */ +PNG_CONST int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + +/* Mask to determine which pixels to overwrite while displaying */ +PNG_CONST int FARDATA png_pass_dsp_mask[] + = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + if (png_ptr == NULL) + return; + png_debug(1, "in png_set_sig_bytes"); + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature."); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) + num_to_check = 8; + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* (Obsolete) function to check signature bytes. It does not allow one + * to check a partial signature. This function might be removed in the + * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. + */ +int PNGAPI +png_check_sig(png_bytep sig, int num) +{ + return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib and clear it to 0. */ +#ifdef PNG_1_0_X +voidpf PNGAPI +#else +voidpf /* private */ +#endif +png_zalloc(voidpf png_ptr, uInt items, uInt size) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_uint_32 num_bytes; + + if (png_ptr == NULL) + return (NULL); + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_uint_32)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + +#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) + if (ptr == NULL) + return ((voidpf)ptr); + + if (num_bytes > (png_uint_32)0x8000L) + { + png_memset(ptr, 0, (png_size_t)0x8000L); + png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, + (png_size_t)(num_bytes - (png_uint_32)0x8000L)); + } + else + { + png_memset(ptr, 0, (png_size_t)num_bytes); + } +#endif + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +#ifdef PNG_1_0_X +void PNGAPI +#else +void /* private */ +#endif +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +png_infop PNGAPI +png_create_info_struct(png_structp png_ptr) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct"); + if (png_ptr == NULL) + return (NULL); +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + if (png_ptr == NULL) + return; + + png_debug(1, "in png_destroy_info_struct"); + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +#undef png_info_init +void PNGAPI +png_info_init(png_infop info_ptr) +{ + /* We only come here via pre-1.0.12-compiled applications */ + png_info_init_3(&info_ptr, 0); +} +#endif + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + if (info_ptr == NULL) + return; + + png_debug(1, "in png_info_init_3"); + + if (png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof(png_info)); +} + +#ifdef PNG_FREE_ME_SUPPORTED +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer."); +} +#endif + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + if (png_ptr == NULL || info_ptr == NULL) + return; + +#if defined(PNG_TEXT_SUPPORTED) + /* Free text item num or (if num == -1) all text items */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) +#else + if (mask & PNG_FREE_TEXT) +#endif + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#if defined(PNG_tRNS_SUPPORTED) + /* Free any tRNS entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) +#else + if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) +#endif + { + png_free(png_ptr, info_ptr->trans); + info_ptr->trans = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif + } +#endif + +#if defined(PNG_sCAL_SUPPORTED) + /* Free any sCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) +#else + if (mask & PNG_FREE_SCAL) +#endif + { +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#if defined(PNG_pCAL_SUPPORTED) + /* Free any pCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) +#else + if (mask & PNG_FREE_PCAL) +#endif + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i]=NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#if defined(PNG_iCCP_SUPPORTED) + /* Free any iCCP entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) +#else + if (mask & PNG_FREE_ICCP) +#endif + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#if defined(PNG_sPLT_SUPPORTED) + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) +#else + if (mask & PNG_FREE_SPLT) +#endif + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) +#else + if (mask & PNG_FREE_UNKN) +#endif + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#if defined(PNG_hIST_SUPPORTED) + /* Free any hIST entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) +#else + if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) +#endif + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif + } +#endif + + /* Free any PLTE entry that was internally allocated */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) +#else + if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) +#endif + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif + info_ptr->num_palette = 0; + } + +#if defined(PNG_INFO_IMAGE_SUPPORTED) + /* Free any image bits attached to the info structure */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) +#else + if (mask & PNG_FREE_ROWS) +#endif + { + if (info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row]=NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers=NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + +#ifdef PNG_FREE_ME_SUPPORTED + if (num == -1) + info_ptr->free_me &= ~mask; + else + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); +#endif +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list = 0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#if !defined(PNG_NO_STDIO) +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + if (png_ptr == NULL) + return; + png_ptr->io_ptr = (png_voidp)fp; +} +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr == NULL) + return (NULL); + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); + } + +#if defined(_WIN32_WCE) + { + wchar_t time_buf[29]; + wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, + NULL, NULL); + } +#else +#ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); + } +#else + png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +#endif +#endif /* _WIN32_WCE */ + return ((png_charp)png_ptr->time_buffer); +} +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_charp PNGAPI +png_get_copyright(png_structp png_ptr) +{ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) "\n libpng version 1.2.37 - June 4, 2009\n\ + Copyright (c) 1998-2009 Glenn Randers-Pehrson\n\ + Copyright (c) 1996-1997 Andreas Dilger\n\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_charp PNGAPI +png_get_libpng_ver(png_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_ver(png_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_version(png_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_HEADER_VERSION_STRING +#ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +#endif + "\n"); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; + for (i = png_ptr->num_chunk_list; i; i--, p -= 5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p + 4)); + return 0; +} +#endif + +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + return (inflateReset(&png_ptr->zstream)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32) PNG_LIBPNG_VER); +} + + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#if !defined(PNG_1_0_X) +/* This function was added to libpng 1.2.0 */ +int PNGAPI +png_mmx_support(void) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return -1; +} +#endif /* PNG_1_0_X */ +#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + return ((png_size_t)size); +} +#endif /* PNG_SIZE_T */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +#if defined(PNG_cHRM_SUPPORTED) +#if !defined(PNG_NO_CHECK_cHRM) + +/* + * Multiply two 32-bit numbers, V1 and V2, using 32-bit + * arithmetic, to produce a 64 bit result in the HI/LO words. + * + * A B + * x C D + * ------ + * AD || BD + * AC || CB || 0 + * + * where A and B are the high and low 16-bit words of V1, + * C and D are the 16-bit words of V2, AD is the product of + * A and D, and X || Y is (X << 16) + Y. +*/ + +void png_64bit_product (long v1, long v2, unsigned long *hi_product, + unsigned long *lo_product) +{ + int a, b, c, d; + long lo, hi, x, y; + + a = (v1 >> 16) & 0xffff; + b = v1 & 0xffff; + c = (v2 >> 16) & 0xffff; + d = v2 & 0xffff; + + lo = b * d; /* BD */ + x = a * d + c * b; /* AD + CB */ + y = ((lo >> 16) & 0xffff) + x; + + lo = (lo & 0xffff) | ((y & 0xffff) << 16); + hi = (y >> 16) & 0xffff; + + hi += a * c; /* AC */ + + *hi_product = (unsigned long)hi; + *lo_product = (unsigned long)lo; +} + +int /* private */ +png_check_cHRM_fixed(png_structp png_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + int ret = 1; + unsigned long xy_hi,xy_lo,yx_hi,yx_lo; + + png_debug(1, "in function png_check_cHRM_fixed"); + if (png_ptr == NULL) + return 0; + + if (white_x < 0 || white_y <= 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + ret = 0; + } + if (white_x > (png_fixed_point) PNG_UINT_31_MAX || + white_y > (png_fixed_point) PNG_UINT_31_MAX || + red_x > (png_fixed_point) PNG_UINT_31_MAX || + red_y > (png_fixed_point) PNG_UINT_31_MAX || + green_x > (png_fixed_point) PNG_UINT_31_MAX || + green_y > (png_fixed_point) PNG_UINT_31_MAX || + blue_x > (png_fixed_point) PNG_UINT_31_MAX || + blue_y > (png_fixed_point) PNG_UINT_31_MAX ) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + ret = 0; + } + if (white_x > 100000L - white_y) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + if (red_x > 100000L - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + if (green_x > 100000L - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + if (blue_x > 100000L - blue_y) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + ret = 0; + } + + png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo); + png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo); + + if (xy_hi == yx_hi && xy_lo == yx_lo) + { + png_warning(png_ptr, + "Ignoring attempt to set cHRM RGB triangle with zero area"); + ret = 0; + } + + return ret; +} +#endif /* NO_PNG_CHECK_cHRM */ +#endif /* PNG_cHRM_SUPPORTED */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/Libraries/libpng/png.h b/Libraries/libpng/png.h new file mode 100644 index 0000000..edcd13a --- /dev/null +++ b/Libraries/libpng/png.h @@ -0,0 +1,3690 @@ +/* png.h - header file for PNG reference library + * + * libpng version 1.2.37 - June 4, 2009 + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.2.37 - June 4, 2009: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 10.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 10.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-8 13 10210 12.so.0.10[.0] + * 1.2.10rc1-3 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.0.19rc1-5 10 10019 10.so.0.19[.0] + * 1.2.11rc1-5 13 10211 12.so.0.11[.0] + * 1.0.19 10 10019 10.so.0.19[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.0.20 10 10020 10.so.0.20[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.2.13beta1 13 10213 12.so.0.13[.0] + * 1.0.21 10 10021 10.so.0.21[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.2.14beta1-2 13 10214 12.so.0.14[.0] + * 1.0.22rc1 10 10022 10.so.0.22[.0] + * 1.2.14rc1 13 10214 12.so.0.14[.0] + * 1.0.22 10 10022 10.so.0.22[.0] + * 1.2.14 13 10214 12.so.0.14[.0] + * 1.2.15beta1-6 13 10215 12.so.0.15[.0] + * 1.0.23rc1-5 10 10023 10.so.0.23[.0] + * 1.2.15rc1-5 13 10215 12.so.0.15[.0] + * 1.0.23 10 10023 10.so.0.23[.0] + * 1.2.15 13 10215 12.so.0.15[.0] + * 1.2.16beta1-2 13 10216 12.so.0.16[.0] + * 1.2.16rc1 13 10216 12.so.0.16[.0] + * 1.0.24 10 10024 10.so.0.24[.0] + * 1.2.16 13 10216 12.so.0.16[.0] + * 1.2.17beta1-2 13 10217 12.so.0.17[.0] + * 1.0.25rc1 10 10025 10.so.0.25[.0] + * 1.2.17rc1-3 13 10217 12.so.0.17[.0] + * 1.0.25 10 10025 10.so.0.25[.0] + * 1.2.17 13 10217 12.so.0.17[.0] + * 1.0.26 10 10026 10.so.0.26[.0] + * 1.2.18 13 10218 12.so.0.18[.0] + * 1.2.19beta1-31 13 10219 12.so.0.19[.0] + * 1.0.27rc1-6 10 10027 10.so.0.27[.0] + * 1.2.19rc1-6 13 10219 12.so.0.19[.0] + * 1.0.27 10 10027 10.so.0.27[.0] + * 1.2.19 13 10219 12.so.0.19[.0] + * 1.2.20beta01-04 13 10220 12.so.0.20[.0] + * 1.0.28rc1-6 10 10028 10.so.0.28[.0] + * 1.2.20rc1-6 13 10220 12.so.0.20[.0] + * 1.0.28 10 10028 10.so.0.28[.0] + * 1.2.20 13 10220 12.so.0.20[.0] + * 1.2.21beta1-2 13 10221 12.so.0.21[.0] + * 1.2.21rc1-3 13 10221 12.so.0.21[.0] + * 1.0.29 10 10029 10.so.0.29[.0] + * 1.2.21 13 10221 12.so.0.21[.0] + * 1.2.22beta1-4 13 10222 12.so.0.22[.0] + * 1.0.30rc1 10 10030 10.so.0.30[.0] + * 1.2.22rc1 13 10222 12.so.0.22[.0] + * 1.0.30 10 10030 10.so.0.30[.0] + * 1.2.22 13 10222 12.so.0.22[.0] + * 1.2.23beta01-05 13 10223 12.so.0.23[.0] + * 1.2.23rc01 13 10223 12.so.0.23[.0] + * 1.2.23 13 10223 12.so.0.23[.0] + * 1.2.24beta01-02 13 10224 12.so.0.24[.0] + * 1.2.24rc01 13 10224 12.so.0.24[.0] + * 1.2.24 13 10224 12.so.0.24[.0] + * 1.2.25beta01-06 13 10225 12.so.0.25[.0] + * 1.2.25rc01-02 13 10225 12.so.0.25[.0] + * 1.0.31 10 10031 10.so.0.31[.0] + * 1.2.25 13 10225 12.so.0.25[.0] + * 1.2.26beta01-06 13 10226 12.so.0.26[.0] + * 1.2.26rc01 13 10226 12.so.0.26[.0] + * 1.2.26 13 10226 12.so.0.26[.0] + * 1.0.32 10 10032 10.so.0.32[.0] + * 1.2.27beta01-06 13 10227 12.so.0.27[.0] + * 1.2.27rc01 13 10227 12.so.0.27[.0] + * 1.0.33 10 10033 10.so.0.33[.0] + * 1.2.27 13 10227 12.so.0.27[.0] + * 1.0.34 10 10034 10.so.0.34[.0] + * 1.2.28 13 10228 12.so.0.28[.0] + * 1.2.29beta01-03 13 10229 12.so.0.29[.0] + * 1.2.29rc01 13 10229 12.so.0.29[.0] + * 1.0.35 10 10035 10.so.0.35[.0] + * 1.2.29 13 10229 12.so.0.29[.0] + * 1.0.37 10 10037 10.so.0.37[.0] + * 1.2.30beta01-04 13 10230 12.so.0.30[.0] + * 1.0.38rc01-08 10 10038 10.so.0.38[.0] + * 1.2.30rc01-08 13 10230 12.so.0.30[.0] + * 1.0.38 10 10038 10.so.0.38[.0] + * 1.2.30 13 10230 12.so.0.30[.0] + * 1.0.39rc01-03 10 10039 10.so.0.39[.0] + * 1.2.31rc01-03 13 10231 12.so.0.31[.0] + * 1.0.39 10 10039 10.so.0.39[.0] + * 1.2.31 13 10231 12.so.0.31[.0] + * 1.2.32beta01-02 13 10232 12.so.0.32[.0] + * 1.0.40rc01 10 10040 10.so.0.40[.0] + * 1.2.32rc01 13 10232 12.so.0.32[.0] + * 1.0.40 10 10040 10.so.0.40[.0] + * 1.2.32 13 10232 12.so.0.32[.0] + * 1.2.33beta01-02 13 10233 12.so.0.33[.0] + * 1.2.33rc01-02 13 10233 12.so.0.33[.0] + * 1.0.41rc01 10 10041 10.so.0.41[.0] + * 1.2.33 13 10233 12.so.0.33[.0] + * 1.0.41 10 10041 10.so.0.41[.0] + * 1.2.34beta01-07 13 10234 12.so.0.34[.0] + * 1.0.42rc01 10 10042 10.so.0.42[.0] + * 1.2.34rc01 13 10234 12.so.0.34[.0] + * 1.0.42 10 10042 10.so.0.42[.0] + * 1.2.34 13 10234 12.so.0.34[.0] + * 1.2.35beta01-03 13 10235 12.so.0.35[.0] + * 1.0.43rc01-02 10 10043 10.so.0.43[.0] + * 1.2.35rc01-02 13 10235 12.so.0.35[.0] + * 1.0.43 10 10043 10.so.0.43[.0] + * 1.2.35 13 10235 12.so.0.35[.0] + * 1.2.36beta01-05 13 10236 12.so.0.36[.0] + * 1.2.36rc01 13 10236 12.so.0.36[.0] + * 1.0.44 10 10044 10.so.0.44[.0] + * 1.2.36 13 10236 12.so.0.36[.0] + * 1.2.37beta01-03 13 10237 12.so.0.37[.0] + * 1.2.37rc01 13 10237 12.so.0.37[.0] + * 1.2.37 13 10237 12.so.0.37[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +#endif +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only, deprecated */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE 0x0800 /* WRITE only */ +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* WRITE only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf; /* used in png_error */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ +#ifndef PNG_NO_WRITE_FILTER + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ +#endif + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +#ifdef PNG_LEGACY_SUPPORTED + png_byte filler; /* filler byte for pixel expansion */ +#else + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif +#endif + +#if defined(PNG_bKGD_SUPPORTED) + png_byte background_gamma_type; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma; +# endif + png_color_16 background; /* background color in screen gamma space */ +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_flush_ptr output_flush_fn;/* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma; /* file gamma value */ + float screen_gamma; /* screen gamma value (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans; /* transparency values for paletted files */ + png_color_16 trans_values; /* transparency values for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# if defined(PNG_TEXT_SUPPORTED) + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* for the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* changed from png_byte to png_uint_32 at version 1.2.0 */ +#ifdef PNG_1_0_X + png_byte mng_features_permitted; +#else + png_uint_32 mng_features_permitted; +#endif /* PNG_1_0_X */ +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_byte filter_type; +#endif + +#if defined(PNG_1_0_X) +/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ + png_uint_32 row_buf_size; +#endif + +/* New members added in libpng-1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +# if !defined(PNG_1_0_X) +# if defined(PNG_MMX_CODE_SUPPORTED) + png_byte mmx_bitdepth_threshold; + png_uint_32 mmx_rowbytes_threshold; +# endif + png_uint_32 asm_flags; +# endif +#endif + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep dither_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is */ + /* in the palette */ + png_bytep palette_to_index; /* which original index points to this */ + /* palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk; +#endif + +/* New members added in libpng-1.2.26 */ + png_uint_32 old_big_row_buf_size, old_prev_row_size; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata; /* buffer for reading chunk data */ + +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_2_37; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); +#endif + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +#endif + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)); + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize the info structure (old interface - DEPRECATED) */ +extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); +#undef png_info_init +#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ + png_sizeof(png_info)); +#endif + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_WRITE_tIME_SUPPORTED */ +#endif /* _WIN32_WCE */ + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +#endif +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated */ +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); +#endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Turn on dithering, and reduce the palette to the number of colors available. */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ +/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)); +#endif +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* writes the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* free all memory used by the read (old method - NOT DLL EXPORTED) */ +/* Debian note: exporting as it is required by legacy applications */ +extern PNG_EXPORT(void,png_read_destroy) PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +/* Debian note: exporting as it is required by legacy applications */ +extern PNG_EXPORT(void,png_write_destroy) PNGARG((png_structp png_ptr)); + +/* set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#if !defined(PNG_NO_STDIO) +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_uint_32 size)); +#endif + +/* frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +#if defined(PNG_1_0_X) +/* Function to allocate memory for zlib. */ +extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, + uInt size)); + +/* Function to free memory for zlib */ +extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); +#endif + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +#ifdef PNG_FREE_ME_SUPPORTED +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +#endif +/* assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)); + +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)); + +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#ifndef PNG_NO_ERROR_TEXT +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); +#else +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)); +#endif + +#ifndef PNG_NO_WARNINGS +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_NO_WARNINGS */ + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* Returns row_pointers, which is an array of pointers to scanlines that was +returned from png_read_png(). */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use +by png_write_png(). */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* + * Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#if defined(PNG_TEXT_SUPPORTED) +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + If you need to turn it off for a chunk that your application has freed, + you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include +#if (PNG_DEBUG > 1) +#ifndef _DEBUG +# define _DEBUG +#endif +#ifndef png_debug +#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +#endif +#ifndef png_debug1 +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +#endif +#ifndef png_debug2 +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +#endif +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ + +#if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } +# endif +# endif /* __STDC __ */ +#endif /* (PNG_DEBUG > 1) */ + +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Added to version 1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#if defined(PNG_MMX_CODE_SUPPORTED) +#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 +#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 +#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 +#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 +#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 +#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ + +#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) +#define PNG_MMX_WRITE_FLAGS ( 0 ) + +#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ + | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ + | PNG_MMX_READ_FLAGS \ + | PNG_MMX_WRITE_FLAGS ) + +#define PNG_SELECT_READ 1 +#define PNG_SELECT_WRITE 2 +#endif /* PNG_MMX_CODE_SUPPORTED */ + +#if !defined(PNG_1_0_X) +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) + PNGARG((int flag_select, int *compilerID)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) + PNGARG((int flag_select)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flags) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) + PNGARG((png_structp png_ptr)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_asm_flags) + PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_mmx_thresholds) + PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold)); + +#endif /* PNG_1_0_X */ + +#if !defined(PNG_1_0_X) +/* png.c, pnggccrd.c, or pngvcrd.c */ +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); +#endif /* PNG_1_0_X */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +/* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +#endif + + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) + +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +/* Inline macros to do direct reads of bytes from the input buffer. These + * require that you are using an architecture that uses PNG byte ordering + * (MSB first) and supports unaligned data storage. I think that PowerPC + * in big-endian mode and 680x0 are the only ones that will support this. + * The x86 line of processors definitely do not. The png_get_int_32() + * routine also assumes we are using two's complement format for negative + * values, which is almost certainly true. + */ +#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) +# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) +# define png_get_int_32(buf) ( *((png_int_32p) (buf))) +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). + */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* These next functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + + +/* Various modes of operation, that are visible to applications because + * they are used for unknown chunk location. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 + +#if defined(PNG_INTERNAL) + +/* More modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ + /* 0x800000L unused */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + ideal-delta..ideal+delta. Each argument is evaluated twice. + "ideal" and "delta" should be constants, normally simple + integers, "value" a variable. Added to libpng-1.2.6 JB */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* place to hold the signature string for a PNG file. */ +#ifdef PNG_USE_GLOBAL_ARRAYS + PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8]; +#else +#endif +#endif /* PNG_NO_EXTERN */ + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro in png.c and + * wherever it's needed. + */ +#define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_tEXt png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize png_ptr struct for reading, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_read_struct instead). + */ +extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); +#undef png_read_init +#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +#endif + +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize png_ptr struct for writing, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_write_struct instead). + */ +extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); +#undef png_write_init +#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +#endif + +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_1_0_X +/* Function to allocate memory for zlib. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +#ifdef PNG_SIZE_T +/* Function to convert a sizeof an item to png_sizeof item */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +#endif + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +#endif +#endif +#else /* PNG_1_0_X */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif +#endif /* PNG_1_0_X */ + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using. */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* simple function to write the signature */ +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); + +/* write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point + file_gamma)); +#endif +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); +#endif + +/* combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) +/* expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* these are the functions that do the transformations */ +#if defined(PNG_READ_FILLER_SUPPORTED) +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); + +# if defined(PNG_CORRECT_PALETTE_SUPPORTED) +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background)); +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#if defined(PNG_READ_bKGD_SUPPORTED) +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_gAMA_SUPPORTED) +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_iCCP_SUPPORTED) +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sPLT_SUPPORTED) +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_sRGB_SUPPORTED) +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tRNS_SUPPORTED) +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#if defined(PNG_MMX_CODE_SUPPORTED) +/* png.c */ /* PRIVATE */ +PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); +#endif +#endif + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_pHYs_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* Added at libpng version 1.2.34 */ +#if defined(PNG_cHRM_SUPPORTED) +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#endif /* PNG_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* do not put anything past this line */ +#endif /* PNG_H */ diff --git a/Libraries/libpng/pngconf.h b/Libraries/libpng/pngconf.h new file mode 100644 index 0000000..025368d --- /dev/null +++ b/Libraries/libpng/pngconf.h @@ -0,0 +1,1496 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.2.37 - June 4, 2009 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#define PNG_1_2_X + +/* + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +#include "pngusr.h" +#endif + +/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */ +#ifdef PNG_CONFIGURE_LIBPNG +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +/* + * Added at libpng-1.2.8 + * + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +#ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +#endif + +#ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +#endif +#endif /* __STDC__ */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* End of material added to libpng-1.2.8 */ + +/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble + Restored at libpng-1.2.21 */ +#if !defined(PNG_NO_WARN_UNINITIALIZED_ROW) && \ + !defined(PNG_WARN_UNINITIALIZED_ROW) +# define PNG_WARN_UNINITIALIZED_ROW 1 +#endif +/* End of material added at libpng-1.2.19/1.2.21 */ + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. + */ +#if defined(__CYGWIN__) +# if defined(ALL_STATIC) +# if defined(PNG_BUILD_DLL) +# undef PNG_BUILD_DLL +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# if !defined(PNG_STATIC) +# define PNG_STATIC +# endif +# else +# if defined (PNG_BUILD_DLL) +# if defined(PNG_STATIC) +# undef PNG_STATIC +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# else +# if defined(PNG_STATIC) +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# else +# if !defined(PNG_USE_DLL) +# define PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if defined(_WIN32_WCE) +# include + /* Console I/O functions are not supported on WindowsCE */ +# define PNG_NO_CONSOLE_IO + /* abort() may not be supported on some/all Windows CE platforms */ +# define PNG_ABORT() exit(-1) +# ifdef PNG_DEBUG +# undef PNG_DEBUG +# endif +#endif + +#ifdef PNG_BUILD_DLL +# ifndef PNG_CONSOLE_IO_SUPPORTED +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif +# else +# if !defined(_WIN32_WCE) +/* "stdio.h" functions are not supported on WindowsCE */ +# include +# endif +# endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +# ifndef PNG_TYPECAST_NULL +# define PNG_TYPECAST_NULL +# endif +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) +# include +#endif + +#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + * + * You can bypass this test if you know that your application uses exactly + * the same setjmp.h that was included when libpng was built. Only define + * PNG_SKIP_SETJMP_CHECK while building your application, prior to the + * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK + * while building a separate libpng library for general use. + */ + +# ifndef PNG_SKIP_SETJMP_CHECK +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __pngconf.h__ in libpng already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ +# endif /* PNG_SKIP_SETJMP_CHECK */ + + /* include setjmp.h for error handling */ +# include + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# ifndef _BSD_SOURCE +# define _BSD_SOURCE +# endif +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include +#else +# include +#endif + +/* Other defines for things like memory and the like can go here. */ +#ifdef PNG_INTERNAL + +#include + +/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it is + * possible to have run-time registry of chunk-handling functions, some of + * these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) +# if defined(MACOS) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +/* I have no idea why is this necessary... */ +#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) +# include +#endif + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +#endif /* PNG_INTERNAL */ + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_NO_CONST +# define PNG_CONST const +#else +# define PNG_CONST +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS + * on the compile line, then pick and choose which ones to define without + * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency) + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * was turned on by default in libpng-1.3.0. + */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +# ifndef PNG_NO_iTXt_SUPPORTED +# define PNG_NO_iTXt_SUPPORTED +# endif +# ifndef PNG_NO_READ_iTXt +# define PNG_NO_READ_iTXt +# endif +# ifndef PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_iTXt +# endif +#endif + +#if !defined(PNG_NO_iTXt_SUPPORTED) +# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) +# define PNG_READ_iTXt +# endif +# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) +# define PNG_WRITE_iTXt +# endif +#endif + +/* The following support, added after version 1.0.0, can be turned off here en + * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility + * with old applications that require the length of png_struct and png_info + * to remain unchanged. + */ + +#ifdef PNG_LEGACY_SUPPORTED +# define PNG_NO_FREE_ME +# define PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_NO_READ_USER_CHUNKS +# define PNG_NO_READ_iCCP +# define PNG_NO_WRITE_iCCP +# define PNG_NO_READ_iTXt +# define PNG_NO_WRITE_iTXt +# define PNG_NO_READ_sCAL +# define PNG_NO_WRITE_sCAL +# define PNG_NO_READ_sPLT +# define PNG_NO_WRITE_sPLT +# define PNG_NO_INFO_IMAGE +# define PNG_NO_READ_RGB_TO_GRAY +# define PNG_NO_READ_USER_TRANSFORM +# define PNG_NO_WRITE_USER_TRANSFORM +# define PNG_NO_USER_MEM +# define PNG_NO_READ_EMPTY_PLTE +# define PNG_NO_MNG_FEATURES +# define PNG_NO_FIXED_POINT_SUPPORTED +#endif + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifndef PNG_NO_FREE_ME +# define PNG_FREE_ME_SUPPORTED +#endif + +#if defined(PNG_READ_SUPPORTED) + +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following line: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */ + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, will be removed from version 2.0.0. + Use PNG_MNG_FEATURES_SUPPORTED instead. */ +#ifndef PNG_NO_READ_EMPTY_PLTE +# define PNG_READ_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_WRITE_SUPPORTED) + +# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ +#ifndef PNG_NO_WRITE_EMPTY_PLTE +# define PNG_WRITE_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef PNG_1_0_X +# ifndef PNG_NO_ERROR_NUMBERS +# define PNG_ERROR_NUMBERS_SUPPORTED +# endif +#endif /* PNG_1_0_X */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_STDIO +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 + * and removed from version 1.2.20. The following will be removed + * from libpng-1.4.0 +*/ + +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE) +# ifndef PNG_OPTIMIZED_CODE_SUPPORTED +# define PNG_OPTIMIZED_CODE_SUPPORTED +# endif +#endif + +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) && defined(__i386__) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif + +# if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4) + /* work around 64-bit gcc compiler bugs in gcc-3.x */ +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if defined(__APPLE__) +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh)) +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_MMX_CODE_SUPPORTED +# endif + +#endif +/* end of obsolete code to be removed from libpng-1.4.0 */ + +#if !defined(PNG_1_0_X) +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#if !defined(PNG_1_0_X) +#ifndef PNG_SET_USER_LIMITS_SUPPORTED +#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) +# define PNG_SET_USER_LIMITS_SUPPORTED +#endif +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter + * how large, set these limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* Added at libpng-1.2.34 and 1.4.0 */ +#ifndef PNG_STRING_NEWLINE +#define PNG_STRING_NEWLINE "\n" +#endif + +/* These are currently experimental features, define them if you want */ + +/* very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ +/* +#define PNG_NO_POINTER_INDEXING +*/ + +/* These functions are turned off by default, as they will be phased out. */ +/* +#define PNG_USELESS_TESTS_SUPPORTED +#define PNG_CORRECT_PALETTE_SUPPORTED +*/ + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#if !defined(PNG_NO_READ_USER_CHUNKS) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# define PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# ifdef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS +# endif +# ifdef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN +# endif +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* need the time information for reading tIME chunks */ +#if defined(PNG_tIME_SUPPORTED) +# if !defined(_WIN32_WCE) + /* "time.h" functions are not supported on WindowsCE */ +# include +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may + * want to have unsigned int for png_uint_32 instead of unsigned long. + */ + +typedef unsigned long png_uint_32; +typedef long png_int_32; +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +/* This is usually size_t. It is typedef'ed just in case you need it to + change (I'm not sure if you will or not, so I thought I'd be safe) */ +#ifdef PNG_SIZE_T + typedef PNG_SIZE_T png_size_t; +# define png_sizeof(x) png_convert_size(sizeof(x)) +#else + typedef size_t png_size_t; +# define png_sizeof(x) sizeof(x) +#endif + +/* The following is needed for medium model support. It cannot be in the + * PNG_INTERNAL section. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + defines FAR. (SJT) */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#if defined(FAR) +# if defined(M_I86MM) +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +#if defined(_WIN32_WCE) +typedef HANDLE png_FILE_p; +#else +typedef FILE * png_FILE_p; +#endif +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* SPC - Is this stuff deprecated? */ +/* It'll be removed as of libpng-1.3.0 - GR-P */ +/* libpng typedefs for types in zlib. If zlib changes + * or another compression library is used, then change these. + * Eliminates need to change all the source files. + */ +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; +#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ + +/* + * Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif +/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. + * When building a static lib, default to no GLOBAL ARRAYS, but allow + * command-line override + */ +#if defined(__CYGWIN__) +# if !defined(PNG_STATIC) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +# else +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +#endif + +/* Do not use global arrays (helps with building DLL's) + * They are no longer used in libpng itself, since version 1.0.5c, + * but might be required for some pre-1.0.5c applications. + */ +#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# if defined(PNG_NO_GLOBAL_ARRAYS) || \ + (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) +# define PNG_USE_LOCAL_ARRAYS +# else +# define PNG_USE_GLOBAL_ARRAYS +# endif +#endif + +#if defined(__CYGWIN__) +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# if !defined(PNG_IMPEXP) + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# if !defined(PNG_IMPEXP) +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +# ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT +# endif +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# endif +#endif + +/* User may want to use these so they are not in PNG_INTERNAL. Any library + * functions that are passed far data must be model independent. + */ + +#ifndef PNG_ABORT +# define PNG_ABORT() abort() +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) +#endif + +#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ +/* use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_snprintf _fsnprintf /* Added to v 1.2.19 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else /* use the usual functions */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +# else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). */ +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# endif +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +#endif +/* End of memory model independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/Libraries/libpng/pngerror.cpp b/Libraries/libpng/pngerror.cpp new file mode 100644 index 0000000..71a2e53 --- /dev/null +++ b/Libraries/libpng/pngerror.cpp @@ -0,0 +1,361 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static void /* PRIVATE */ +png_default_error PNGARG((png_structp png_ptr, + png_const_charp error_message)); +#ifndef PNG_NO_WARNINGS +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_NO_WARNINGS */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifndef PNG_NO_ERROR_TEXT +void PNGAPI +png_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == '#') + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + else + error_message += offset; + } + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +void PNGAPI +png_err(png_structp png_ptr) +{ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, '\0'); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, '\0'); +} +#endif /* PNG_NO_ERROR_TEXT */ + +#ifndef PNG_NO_WARNINGS +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == '#') + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} +#endif /* PNG_NO_WARNINGS */ + + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 64 + +#if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = '['; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = ']'; + } + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT); + buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0'; + } +} + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp error_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED */ +#endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */ + +#ifndef PNG_NO_WARNINGS +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_NO_WARNINGS */ + + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void /* PRIVATE */ +png_default_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == '#') + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#endif + +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf jmpbuf; + png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); + longjmp(jmpbuf, 1); + } +# else + longjmp(png_ptr->jmpbuf, 1); +# endif + } +#else + PNG_ABORT(); +#endif +#ifdef PNG_NO_CONSOLE_IO + error_message = error_message; /* Make compiler happy */ +#endif +} + +#ifndef PNG_NO_WARNINGS +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == '#') + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + warning_message = warning_message; /* Make compiler happy */ +#endif + png_ptr = png_ptr; /* Make compiler happy */ +} +#endif /* PNG_NO_WARNINGS */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pnggccrd.cpp b/Libraries/libpng/pnggccrd.cpp new file mode 100644 index 0000000..e61523e --- /dev/null +++ b/Libraries/libpng/pnggccrd.cpp @@ -0,0 +1,103 @@ +/* pnggccrd.c was removed from libpng-1.2.20. */ + +/* This code snippet is for use by configure's compilation test. */ + +#if (!defined _MSC_VER) && \ + defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \ + defined(PNG_MMX_CODE_SUPPORTED) + +int PNGAPI png_dummy_mmx_support(void); + +static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested + +int PNGAPI +png_dummy_mmx_support(void) __attribute__((noinline)); + +int PNGAPI +png_dummy_mmx_support(void) +{ + int result; +#if defined(PNG_MMX_CODE_SUPPORTED) // superfluous, but what the heck + __asm__ __volatile__ ( +#if defined(__x86_64__) + "pushq %%rbx \n\t" // rbx gets clobbered by CPUID instruction + "pushq %%rcx \n\t" // so does rcx... + "pushq %%rdx \n\t" // ...and rdx (but rcx & rdx safe on Linux) + "pushfq \n\t" // save Eflag to stack + "popq %%rax \n\t" // get Eflag from stack into rax + "movq %%rax, %%rcx \n\t" // make another copy of Eflag in rcx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushq %%rax \n\t" // save modified Eflag back to stack + "popfq \n\t" // restore modified value to Eflag reg + "pushfq \n\t" // save Eflag to stack + "popq %%rax \n\t" // get Eflag from stack + "pushq %%rcx \n\t" // save original Eflag to stack + "popfq \n\t" // restore original Eflag +#else + "pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction + "pushl %%ecx \n\t" // so does ecx... + "pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux) + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack into eax + "movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushl %%eax \n\t" // save modified Eflag back to stack + "popfl \n\t" // restore modified value to Eflag reg + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack + "pushl %%ecx \n\t" // save original Eflag to stack + "popfl \n\t" // restore original Eflag +#endif + "xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag + "jz 0f \n\t" // if same, CPUID instr. is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero +// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode) + "cpuid \n\t" // get the CPU identification info + "cmpl $1, %%eax \n\t" // make sure eax return non-zero value + "jl 0f \n\t" // if eax is zero, MMX is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero and... + "incl %%eax \n\t" // ...increment eax to 1. This pair is + // faster than the instruction "mov eax, 1" + "cpuid \n\t" // get the CPU identification info again + "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23) + "cmpl $0, %%edx \n\t" // 0 = MMX not supported + "jz 0f \n\t" // non-zero = yes, MMX IS supported + + "movl $1, %%eax \n\t" // set return value to 1 + "jmp 1f \n\t" // DONE: have MMX support + + "0: \n\t" // .NOT_SUPPORTED: target label for jump instructions + "movl $0, %%eax \n\t" // set return value to 0 + "1: \n\t" // .RETURN: target label for jump instructions +#if defined(__x86_64__) + "popq %%rdx \n\t" // restore rdx + "popq %%rcx \n\t" // restore rcx + "popq %%rbx \n\t" // restore rbx +#else + "popl %%edx \n\t" // restore edx + "popl %%ecx \n\t" // restore ecx + "popl %%ebx \n\t" // restore ebx +#endif + +// "ret \n\t" // DONE: no MMX support + // (fall through to standard C "ret") + + : "=a" (result) // output list + + : // any variables used on input (none) + + // no clobber list +// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually +// , "memory" // if write to a variable gcc thought was in a reg +// , "cc" // "condition codes" (flag bits) + ); + _mmx_supported = result; +#else + _mmx_supported = 0; +#endif /* PNG_MMX_CODE_SUPPORTED */ + + return _mmx_supported; +} +#endif diff --git a/Libraries/libpng/pngget.cpp b/Libraries/libpng/pngget.cpp new file mode 100644 index 0000000..0022d95 --- /dev/null +++ b/Libraries/libpng/pngget.cpp @@ -0,0 +1,939 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + else + return(0); +} + +png_uint_32 PNGAPI +png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + else + return(0); +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +png_bytepp PNGAPI +png_get_rows(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + else + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + + else + return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + + else + return (info_ptr->y_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + + else + return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) + { + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + return (0.0); +#endif + return ((float)0.0); +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + + else + return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + + else + return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + + else + return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + + else + return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +float PNGAPI +png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_x_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +float PNGAPI +png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_y_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + else + return (0); +} + +png_bytep PNGAPI +png_get_signature(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + else + return (NULL); +} + +#if defined(PNG_bKGD_SUPPORTED) +png_uint_32 PNGAPI +png_get_bKGD(png_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + return (0); +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_structp png_ptr, png_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function", "gAMA"); + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *int_file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && int_file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function", "gAMA"); + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#endif + +#if defined(PNG_sRGB_SUPPORTED) +png_uint_32 PNGAPI +png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + png_debug1(1, "in %s retrieval function", "sRGB"); + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + return (0); +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +png_uint_32 PNGAPI +png_get_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + png_debug1(1, "in %s retrieval function", "iCCP"); + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* Compression_type is a dummy so the API won't have to change + * if we introduce multiple compression types later. + */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + return (0); +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sPLT(png_structp png_ptr, png_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + return (0); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +png_uint_32 PNGAPI +png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + png_debug1(1, "in %s retrieval function", "hIST"); + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && + bit_depth != NULL && color_type != NULL) + { + png_debug1(1, "in %s retrieval function", "IHDR"); + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) + png_error(png_ptr, "Invalid bit depth"); + + *color_type = info_ptr->color_type; + + if (info_ptr->color_type > 6) + png_error(png_ptr, "Invalid color type"); + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* Check for potential overflow of rowbytes */ + if (*width == 0 || *width > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image width"); + + if (*height == 0 || *height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image height"); + + if (info_ptr->width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + { + png_warning(png_ptr, + "Width too large for libpng to process image data."); + } + + return (1); + } + return (0); +} + +#if defined(PNG_oFFs_SUPPORTED) +png_uint_32 PNGAPI +png_get_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + png_debug1(1, "in %s retrieval function", "oFFs"); + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + return (0); +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +png_uint_32 PNGAPI +png_get_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + png_debug1(1, "in %s retrieval function", "pCAL"); + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + return (0); +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_structp png_ptr, png_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + return (retval); +} +#endif + +png_uint_32 PNGAPI +png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, + int *num_palette) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + png_debug1(1, "in %s retrieval function", "PLTE"); + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + return (0); +} + +#if defined(PNG_sBIT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + png_debug1(1, "in %s retrieval function", "sBIT"); + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + return (0); +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +png_uint_32 PNGAPI +png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, + int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return ((png_uint_32)info_ptr->num_text); + } + if (num_text != NULL) + *num_text = 0; + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +png_uint_32 PNGAPI +png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + png_debug1(1, "in %s retrieval function", "tIME"); + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + return (0); +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +png_uint_32 PNGAPI +png_get_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep *trans, int *num_trans, png_color_16p *trans_values) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans != NULL) + { + *trans = info_ptr->trans; + retval |= PNG_INFO_tRNS; + } + + if (trans_values != NULL) + *trans_values = &(info_ptr->trans_values); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_values != NULL) + { + *trans_values = &(info_ptr->trans_values); + retval |= PNG_INFO_tRNS; + } + + if (trans != NULL) + *trans = NULL; + } + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + return (retval); +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +png_uint_32 PNGAPI +png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); + } + return (0); +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +png_byte PNGAPI +png_get_rgb_to_gray_status (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +png_voidp PNGAPI +png_get_user_chunk_ptr(png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_ptr : NULL); +} +#endif + +#ifdef PNG_WRITE_SUPPORTED +png_uint_32 PNGAPI +png_get_compression_buffer_size(png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); +} +#endif + +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +#ifndef PNG_1_0_X +/* This function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flags (png_structp png_ptr) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0L: 0L); +} + +/* This function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flagmask (int flag_select) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + flag_select=flag_select; + return 0L; +} + + /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ +/* This function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_flagmask (int flag_select, int *compilerID) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + flag_select=flag_select; + *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ + return 0L; +} + +/* This function was added to libpng 1.2.0 */ +png_byte PNGAPI +png_get_mmx_bitdepth_threshold (png_structp png_ptr) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0: 0); +} + +/* This function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_rowbytes_threshold (png_structp png_ptr) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0L: 0L); +} +#endif /* ?PNG_1_0_X */ +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_width_max : 0); +} +png_uint_32 PNGAPI +png_get_user_height_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_height_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngmem.cpp b/Libraries/libpng/pngmem.cpp new file mode 100644 index 0000000..d1999b6 --- /dev/null +++ b/Libraries/libpng/pngmem.cpp @@ -0,0 +1,617 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* If you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (png_get_copyright(NULL)); + +#ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + else +#endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + else +#endif + + if (size != (size_t)size) + ret = NULL; + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* Try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if (png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of Memory."); +#endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +#endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof(png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of memory."); +#endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ + else + png_warning(png_ptr, "Out of Memory."); +#endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + else + ret = farmalloc(size); + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ + else + png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ + } +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). In the default + * configuration, png_ptr is not used, but is passed in case it + * is needed. If ptr is NULL, return without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || ptr == NULL) + return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + { + farfree(ptr); + } +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size, 1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +#endif + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); +# else + free(struct_ptr); +# endif +#endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ + + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + else +#endif + return NULL; + } +#endif + + /* Check for overflow */ +#if defined(__TURBOC__) && !defined(__FLAT__) + if (size != (unsigned long)size) + ret = NULL; + else + ret = farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + else + ret = halloc(size, 1); +# else + if (size != (size_t)size) + ret = NULL; + else + ret = malloc((size_t)size); +# endif +#endif + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else + png_free_default(png_ptr, ptr); +} +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); +# else + free(ptr); +# endif +#endif +} + +#endif /* Not Borland DOS special memory handler */ + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +png_voidp PNGAPI +png_malloc_warn(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ptr; + png_uint_32 save_flags; + if (png_ptr == NULL) + return (NULL); + + save_flags = png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} +#endif + +png_voidp PNGAPI +png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr, "Overflow in png_memcpy_check."); + + return(png_memcpy (s1, s2, size)); +} + +png_voidp PNGAPI +png_memset_check (png_structp png_ptr, png_voidp s1, int value, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr, "Overflow in png_memset_check."); + + return (png_memset (s1, value, size)); + +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngpread.cpp b/Libraries/libpng/pngpread.cpp new file mode 100644 index 0000000..9746c7a --- /dev/null +++ b/Libraries/libpng/pngpread.cpp @@ -0,0 +1,1724 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + +#if defined(PNG_READ_tEXt_SUPPORTED) + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_CONST PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_CONST PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_CONST PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_CONST PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_CONST PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_CONST PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_CONST PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_CONST PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_CONST PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_CONST PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_CONST PNG_sCAL; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_CONST PNG_sRGB; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_CONST PNG_sPLT; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_CONST PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_CONST PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_CONST PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_CONST PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } + +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, + (png_uint_32)new_max); + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + + /* Check for overflow */ + if ((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + + /* Check for overflow */ + if ((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + int ret; + + if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) + png_error(png_ptr, "Extra compression data"); + + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + for (;;) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK) + { + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_in) + png_error(png_ptr, "Extra compressed data"); + + if (!(png_ptr->zstream.avail_out)) + { + png_push_process_row(png_ptr); + } + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + else if (ret == Z_BUF_ERROR) + break; + + else + png_error(png_ptr, "Decompression Error"); + } + if (!(png_ptr->zstream.avail_out)) + { + if (( +#if defined(PNG_READ_INTERLACING_SUPPORTED) + png_ptr->interlaced && png_ptr->pass > 6) || + (!png_ptr->interlaced && +#endif + png_ptr->row_number == png_ptr->num_rows)) + { + if (png_ptr->zstream.avail_in) + png_warning(png_ptr, "Too much data in IDAT chunks"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + png_push_process_row(png_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + else + break; + } +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +#if defined(PNG_READ_tEXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place tEXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place zTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_uint_32)(png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place iTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_uint_32)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, + png_bytep old_row, png_bytep new_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; +#endif + if (png_ptr == NULL) + return; + + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/Libraries/libpng/pngread.cpp b/Libraries/libpng/pngread.cpp new file mode 100644 index 0000000..370ecba --- /dev/null +++ b/Libraries/libpng/pngread.cpp @@ -0,0 +1,1470 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) + +/* Create a PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct"); +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then encounter + a png_error() will longjmp here. Since the jmpbuf is then meaningless we + abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Initialize PNG structure for reading, and allocate any memory needed. + This interface is deprecated in favour of the png_create_read_struct(), + and it will disappear as of libpng-1.3.0. */ +#undef png_read_init +void PNGAPI +png_read_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ + if (png_ptr == NULL) + return; +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if (png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn = NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if (png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn = NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for reading is too small."); + } + if (png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn = NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "The info struct allocated by application for reading is too small."); + } + png_read_init_3(&png_ptr, user_png_ver, png_struct_size); +} +#endif /* PNG_1_0_X || PNG_1_2_X */ + +void PNGAPI +png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i = 0; + + png_structp png_ptr=*ptr_ptr; + + if (png_ptr == NULL) + return; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn = NULL; + png_warning(png_ptr, + "Application uses deprecated png_read_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_read_init_3"); + +#ifdef PNG_SETJMP_SUPPORTED + /* Save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + if (png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + png_ptr = *ptr_ptr; + } + + /* Reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof(png_struct)); + +#ifdef PNG_SETJMP_SUPPORTED + /* Restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + png_debug(1, "in png_read_info"); + /* If we haven't checked all of the PNG signature bytes, do so now. */ + if (png_ptr->sig_bytes < 8) + { + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + } + + for (;;) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_CONST PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_CONST PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_CONST PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_CONST PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_CONST PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_CONST PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_CONST PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_CONST PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_CONST PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_CONST PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_CONST PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_CONST PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_CONST PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_CONST PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_CONST PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_CONST PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_CONST PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } +#endif + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info"); + if (png_ptr == NULL) + return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + png_read_transform_info(png_ptr, info_ptr); +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + if (png_ptr == NULL) + return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; + PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, + 0xff}; + PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; +#endif + int ret; + if (png_ptr == NULL) + return; + png_debug2(1, "in png_read_row (row %lu, pass %d)", + png_ptr->row_number, png_ptr->pass); + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); +#endif + } + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* If interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if (png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + /* Old interface (pre-1.0.9): + * png_do_read_interlace(&(png_ptr->row_info), + * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); + } + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + if (png_ptr == NULL) + return; + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, png_bytep_NULL); + rp++; + } + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, png_bytep_NULL, dptr); + dp++; + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass = png_set_interlace_handling(png_ptr); +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled."); + pass = 1; +#endif + + + image_height=png_ptr->height; + png_ptr->num_rows = image_height; /* Make sure this is set correctly */ + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, png_bytep_NULL); + rp++; + } + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_end"); + if (png_ptr == NULL) + return; + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_CONST PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_CONST PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_CONST PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_CONST PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_CONST PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_CONST PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_CONST PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_CONST PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_CONST PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_CONST PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_CONST PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_CONST PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_CONST PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_CONST PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_CONST PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_CONST PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_CONST PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct"); + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + if (png_ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#if defined(PNG_TEXT_SUPPORTED) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#if defined(PNG_READ_TEXT_SUPPORTED) + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* Free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy"); + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->chunkdata); +#if defined(PNG_READ_DITHER_SUPPORTED) + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->dither_index); +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_table); +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; +#else + if (png_ptr->flags & PNG_FLAG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#else + if (png_ptr->flags & PNG_FLAG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif +#endif +#if defined(PNG_READ_hIST_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#else + if (png_ptr->flags & PNG_FLAG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->read_row_fn = read_row_fn; +} + + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL) + return; +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + /* Invert the alpha channel from opacity to transparency + */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + /* Tell libpng to strip 16 bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or dithering. + */ + +#if defined(PNG_READ_INVERT_SUPPORTED) + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + /* Flip the RGB pixels to BGR (or RGBA to BGRA) + */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) + */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + /* Swap bytes of 16 bit files to least significant byte first + */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); +#endif + if (info_ptr->row_pointers == NULL) + { + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + png_memset(info_ptr->row_pointers, 0, info_ptr->height + * png_sizeof(png_bytep)); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ROWS; +#endif + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + transforms = transforms; /* Quiet compiler warnings */ + params = params; + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/Libraries/libpng/pngrio.cpp b/Libraries/libpng/pngrio.cpp new file mode 100644 index 0000000..8e52962 --- /dev/null +++ b/Libraries/libpng/pngrio.cpp @@ -0,0 +1,177 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL read function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + + + if (png_ptr == NULL) + return; + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ +#if defined(_WIN32_WCE) + DWORD check; + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + png_size_t check; + + check = (png_size_t)fread(data, (png_size_t)1, length, + (png_FILE_p)png_ptr->io_ptr); +#endif + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fread(n_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) + err = 0; +#else + err = fread(buf, (png_size_t)1, read, io_ptr); +#endif + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +#endif +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png input data structure + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL."); + } + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/Libraries/libpng/pngrtran.cpp b/Libraries/libpng/pngrtran.cpp new file mode 100644 index 0000000..af396df --- /dev/null +++ b/Libraries/libpng/pngrtran.cpp @@ -0,0 +1,4382 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + /* Tell libpng how we react to CRC errors in critical chunks */ + if (png_ptr == NULL) + return; + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error."); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* Handle alpha and tRNS via a background color */ +void PNGAPI +png_set_background(png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_debug(1, "in png_set_background"); + if (png_ptr == NULL) + return; + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = (float)background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* Strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Dither file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_dither" indicates + * whether we need a dithering cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_dither(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_uint_16p histogram, + int full_dither) +{ + png_debug(1, "in png_set_dither"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_DITHER; + + if (!full_dither) + { + int i; + + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->dither_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the dither_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->dither_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->dither_sort[j]] + < histogram[png_ptr->dither_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->dither_sort[j]; + png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; + png_ptr->dither_sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_dither) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->dither_index[j] = (png_byte)i; + png_ptr->dither_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->dither_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->dither_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->dither_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->dither_sort); + png_ptr->dither_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * + png_sizeof(png_dsortp))); + png_memset(hash, 0, 769 * png_sizeof(png_dsortp)); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) + break; + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_dither) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->dither_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->dither_index[k] == + num_new_palette) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_dither) + { + int i; + png_bytep distance; + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + PNG_DITHER_BLUE_BITS; + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof(png_byte))); + png_memset(png_ptr->palette_lookup, 0, num_entries * + png_sizeof(png_byte)); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + * + * We will turn off gamma transformation later if no semitransparent entries + * are present in the tRNS array for palette images. We can't do it here + * because we don't necessarily have the tRNS chunk yet. + */ +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_debug(1, "in png_set_gamma"); + if (png_ptr == NULL) + return; + if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = (float)file_gamma; + png_ptr->screen_gamma = (float)scrn_gamma; +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha. + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +#if !defined(PNG_1_0_X) +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_EXPAND; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +/* Deprecated as of libpng-1.2.9 */ +void PNGAPI +png_set_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_1_2_4_to_8"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + if (png_ptr == NULL) + return; + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); +} +#endif + +void PNGAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + if (png_ptr == NULL) + return; + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#if defined(PNG_READ_EXPAND_SUPPORTED) + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if (red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if (red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = + (png_uint_16)(32768 - red_int - green_int); + } +} +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + if (png_ptr == NULL) + return; +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +#ifdef PNG_LEGACY_SUPPORTED + if (read_user_transform_fn) + png_warning(png_ptr, + "This version of libpng does not support user transforms"); +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (png_ptr != NULL) +#endif + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ + || defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* Detect gray background and attempt to enable optimization + * for gray --> RGB case + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + !(color_type & PNG_COLOR_MASK_COLOR)) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } else if ((png_ptr->transformations & PNG_BACKGROUND) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_GRAY_TO_RGB) && + png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } +#endif + + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* Expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0xff; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x55; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x11; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + + case 8: + + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) +#endif + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop; + istop=(int)png_ptr->num_trans; + for (i=0; itrans[i] = (png_byte)(255 - png_ptr->trans[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) + < PNG_GAMMA_THRESHOLD)) + { + int i, k; + k=0; + for (i=0; inum_trans; i++) + { + if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) + k=1; /* Partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= ~PNG_GAMMA; + } + + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && + png_ptr->gamma != 0.0) + { + png_build_gamma_table(png_ptr); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* Could skip if no transparency */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } + + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255, gs) * 255.0 + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); + } + + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + /* Prevent the transformations being done again, and make sure + * that the now spurious alpha channel is stripped - the code + * has just reduced background composition and gamma correction + * to a simple alpha channel strip. + */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations &= ~PNG_GAMMA; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } + + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + + /* Handled alpha, still need to strip the channel. */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info"); +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; +#if 0 /* Removed from libpng-1.2.27 */ + else + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = png_ptr->gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_ptr->int_gamma; +#endif + } +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#if defined(PNG_READ_FILLER_SUPPORTED) + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ +#if !defined(PNG_1_0_X) + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; +#endif + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + +#if !defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations"); + if (png_ptr->row_buf == NULL) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + + png_snprintf2(msg, 50, + "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#ifdef PNG_WARN_UNINITIALIZED_ROW + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + /* Application has failed to call either png_read_start_image() + * or png_read_update_info() after setting transforms that expand + * pixels. This check added to libpng-1.2.19 + */ +#if (PNG_WARN_UNINITIALIZED_ROW==1) + png_error(png_ptr, "Uninitialized row"); +#else + png_warning(png_ptr, "Uninitialized row"); +#endif +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values), &(png_ptr->background) +#if defined(PNG_READ_GAMMA_SUPPORTED) + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift +#endif +); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if ((png_ptr->transformations & PNG_GAMMA) && +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->dither_index); + if (png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_dither returned rowbytes=0"); + } +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* If gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if (png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#if defined(PNG_READ_PACK_SUPPORTED) +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth < 8) +#else + if (row_info->bit_depth < 8) +#endif + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && sig_bits != NULL && +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* Chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth == 16) +#else + if (row_info->bit_depth == 16) +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_invert_alpha"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } + } + } +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if (row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RGB to XRGB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if (row_info->bit_depth == 16) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } + } /* COLOR_TYPE == RGB */ +} +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + if (row_info->bit_depth >= 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * (THIS LINK IS DEAD June 2008) + * New link: + * + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue)>>15]; + } + else + *(dp++) = *(sp - 1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + else + *(dp++) = *(sp - 1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if (red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + +/* This function is currently unused. Do we really need it? */ +#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) +void /* PRIVATE */ +png_correct_palette(png_structp png_ptr, png_colorp palette, + int num_palette) +{ + png_debug(1, "in png_correct_palette"); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) + { + png_color back, back_1; + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g; + + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || + fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = png_ptr->background.red; + back.green = png_ptr->background.green; + back.blue = png_ptr->background.blue; + } + else + { + back.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + g = 1.0 / png_ptr->background_gamma; + + back_1.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back_1.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back_1.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_uint_32 i; + + for (i = 0; i < (png_uint_32)num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + png_byte v, w; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) + { + palette[i] = back; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + } + else +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < (int)png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i].red = back.red; + palette[i].green = back.green; + palette[i].blue = back.blue; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, png_ptr->palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, png_ptr->palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, png_ptr->palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } + else /* Assume grayscale palette (what else could it be?) */ + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (i == (png_byte)png_ptr->trans_values.gray) + { + palette[i].red = (png_byte)png_ptr->background.red; + palette[i].green = (png_byte)png_ptr->background.green; + palette[i].blue = (png_byte)png_ptr->background.blue; + } + } + } + } +#endif +} +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background +#if defined(PNG_READ_GAMMA_SUPPORTED) + , png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + int shift; + + png_debug(1, "in png_do_background"); + if (background != NULL && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_values->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + + case 2: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + + case 4: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + + case 8: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + + case 16: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + { + *dp = *sp; + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) +#else + else +#endif + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) +#else + else +#endif + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#endif + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_colorp palette, png_bytep trans, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray&0x01)*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (png_uint_16)((gray&0x03)*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (png_uint_16)((gray&0x0f)*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (gray >> 8) & 0xff; + png_byte gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + png_byte red = trans_value->red & 0xff; + png_byte green = trans_value->green & 0xff; + png_byte blue = trans_value->blue & 0xff; + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (trans_value->red >> 8) & 0xff; + png_byte green_high = (trans_value->green >> 8) & 0xff; + png_byte blue_high = (trans_value->blue >> 8) & 0xff; + png_byte red_low = trans_value->red & 0xff; + png_byte green_low = trans_value->green & 0xff; + png_byte blue_low = trans_value->blue & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +void /* PRIVATE */ +png_do_dither(png_row_infop row_info, png_bytep row, + png_bytep palette_lookup, png_bytep dither_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_dither"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + dither_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = dither_lookup[*sp]; + } + } + } +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +#if defined(PNG_READ_GAMMA_SUPPORTED) +static PNG_CONST int png_gamma_shift[] = + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr) +{ + png_debug(1, "in png_build_gamma_table"); + + if (png_ptr->bit_depth <= 8) + { + int i; + double g; + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + + else + g = 1.0; + + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + + + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + if (png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + + else + g = png_ptr->gamma; /* Probably doing rgb_to_gray */ + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } + + if (sig_bit > 0) + shift = 16 - sig_bit; + + else + shift = 0; + + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } + + if (shift > 8) + shift = 8; + + if (shift < 0) + shift = 0; + + png_ptr->gamma_shift = (png_byte)shift; + + num = (1 << (8 - shift)); + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p))); + png_memset(png_ptr->gamma_16_table, 0, num * png_sizeof(png_uint_16p)); + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + } + + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p ))); + png_memset(png_ptr->gamma_16_to_1, 0, num * png_sizeof(png_uint_16p)); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + + if (png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + + else + g = png_ptr->gamma; /* Probably doing rgb_to_gray */ + + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p))); + png_memset(png_ptr->gamma_16_from_1, 0, + num * png_sizeof(png_uint_16p)); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } +} +#endif +/* To do: install integer version of png_build_gamma_table here */ +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/Libraries/libpng/pngrutil.cpp b/Libraries/libpng/pngrutil.cpp new file mode 100644 index 0000000..ae1e3f7 --- /dev/null +++ b/Libraries/libpng/pngrutil.cpp @@ -0,0 +1,3244 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) + +#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) +# define WIN32_WCE_OLD +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +# if defined(WIN32_WCE_OLD) +/* The strtod() function is not supported on WindowsCE */ +__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) +{ + double result = 0; + int len; + wchar_t *str, *end; + + len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); + str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t)); + if ( NULL != str ) + { + MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); + result = wcstod(str, &end); + len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); + *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); + png_free(png_ptr, str); + } + return result; +} +# else +# define png_strtod(p,a,b) strtod(a,b) +# endif +#endif + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_bytep buf) +{ +#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED + png_uint_32 i = png_get_uint_32(buf); +#else + /* Avoid an extra function call by inlining the result. */ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); +#endif + if (i > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range."); + return (i); +} +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 PNGAPI +png_get_uint_32(png_bytep buf) +{ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); + + return (i); +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. + */ +png_int_32 PNGAPI +png_get_int_32(png_bytep buf) +{ + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); + + return (i); +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 PNGAPI +png_get_uint_16(png_bytep buf) +{ + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); + + return (i); +} +#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + + /* Read the length and the chunk name */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, buf + 4, 4); + + png_debug2(0, "Reading %s chunk, length = %lu", + png_ptr->chunk_name, length); + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); + + /* Check to see if chunk name is valid */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if (png_ptr == NULL) + return; + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading a ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_error(png_ptr, "CRC error"); + } + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +void /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + static PNG_CONST char msg[] = "Error decoding compressed text"; + png_charp text; + png_size_t text_size; + + if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + int ret = Z_OK; + png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + text_size = 0; + text = NULL; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_warning(png_ptr, png_ptr->zstream.msg); + else + png_warning(png_ptr, msg); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (text == NULL) + { + text_size = prefix_size + png_sizeof(msg) + 1; + text = (png_charp)png_malloc_warn(png_ptr, text_size); + if (text == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_error(png_ptr, "Not enough memory to decompress chunk"); + } + png_memcpy(text, png_ptr->chunkdata, prefix_size); + } + + text[text_size - 1] = 0x00; + + /* Copy what we can of the error message into the text chunk */ + text_size = (png_size_t)(chunklength - + (text - png_ptr->chunkdata) - 1); + if (text_size > png_sizeof(msg)) + text_size = png_sizeof(msg); + png_memcpy(text + prefix_size, msg, text_size); + break; + } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) + { + text_size = prefix_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); + if (text == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_error(png_ptr, + "Not enough memory to decompress chunk."); + } + png_memcpy(text + prefix_size, png_ptr->zbuf, + text_size - prefix_size); + png_memcpy(text, png_ptr->chunkdata, prefix_size); + *(text + text_size) = 0x00; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(text_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); + if (text == NULL) + { + png_free(png_ptr, tmp); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_error(png_ptr, + "Not enough memory to decompress chunk.."); + } + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = 0x00; + } + if (ret == Z_STREAM_END) + break; + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + } + if (ret != Z_STREAM_END) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[52]; + + if (ret == Z_BUF_ERROR) + png_snprintf(umsg, 52, + "Buffer error in compressed datastream in %s chunk", + png_ptr->chunk_name); + + else if (ret == Z_DATA_ERROR) + png_snprintf(umsg, 52, + "Data error in compressed datastream in %s chunk", + png_ptr->chunk_name); + + else + png_snprintf(umsg, 52, + "Incomplete compressed datastream in %s chunk", + png_ptr->chunk_name); + + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, + "Incomplete compressed datastream in chunk other than IDAT"); +#endif + text_size = prefix_size; + if (text == NULL) + { + text = (png_charp)png_malloc_warn(png_ptr, text_size+1); + if (text == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_error(png_ptr, "Not enough memory for text."); + } + png_memcpy(text, png_ptr->chunkdata, prefix_size); + } + *(text + text_size) = 0x00; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength=text_size; + } + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[50]; + + png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + *(png_ptr->chunkdata + prefix_size) = 0x00; + *newlength = prefix_size; + } +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* Check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifndef PNG_NO_POINTER_INDEXING + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#if defined(PNG_READ_tRNS_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + png_crc_finish(png_ptr, length); + + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ +} + +#if defined(PNG_READ_gAMA_SUPPORTED) +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = (png_fixed_point)png_get_uint_32(buf); + /* Check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } + +#if defined(PNG_READ_sRGB_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO + fprintf(stderr, "gamma = (%d/100000)", (int)igamma); +#endif + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; +# ifdef PNG_READ_GAMMA_SUPPORTED + png_ptr->gamma = file_gamma; +# endif + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif +} +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[32]; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_uint_32 uint_x, uint_y; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 32); + if (png_crc_finish(png_ptr, 0)) + return; + + uint_x = png_get_uint_32(buf); + uint_y = png_get_uint_32(buf + 4); + int_x_white = (png_fixed_point)uint_x; + int_y_white = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 8); + uint_y = png_get_uint_32(buf + 12); + int_x_red = (png_fixed_point)uint_x; + int_y_red = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 16); + uint_y = png_get_uint_32(buf + 20); + int_x_green = (png_fixed_point)uint_x; + int_y_green = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 24); + uint_y = png_get_uint_32(buf + 28); + int_x_blue = (png_fixed_point)uint_x; + int_y_blue = (png_fixed_point)uint_y; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + int_x_white, int_y_white, int_x_red, int_y_red); + fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + int_x_green, int_y_green, int_x_blue, int_y_blue); +#endif +#endif /* PNG_NO_CONSOLE_IO */ + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif +} +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + /* Check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + png_fixed_point igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); +# endif +#endif + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=(%d/100000)\n", + (int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma); +# endif +# endif +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#if defined(PNG_READ_iCCP_SUPPORTED) +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size, profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (profile = png_ptr->chunkdata; *profile; profile++) + /* Empty loop to find end of name */ ; + + ++profile; + + /* There should be at least one zero (the compression type byte) + * following the separator, and we should be on it + */ + if ( profile >= png_ptr->chunkdata + slength - 1) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* Compression_type should always be zero */ + compression_type = *profile++; + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - png_ptr->chunkdata; + png_decompress_chunk(png_ptr, compression_type, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if ( prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(png_ptr->chunkdata + prefix_length); + profile_size = ((*(pC ))<<24) | + ((*(pC + 1))<<16) | + ((*(pC + 2))<< 8) | + ((*(pC + 3)) ); + + if (profile_size < profile_length) + profile_length = profile_size; + + if (profile_size > profile_length) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Ignoring truncated iCCP profile."); + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, png_ptr->chunkdata + prefix_length, profile_length); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_sPLT_SUPPORTED) +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_NO_POINTER_INDEXING + png_sPLT_entryp pp; +#endif + int data_length, entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_sPLT"); + + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++) + /* Empty loop to find end of name */ ; + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata)); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + new_palette.nentries = (png_int_32) ( data_length / entry_size); + if ((png_uint_32) new_palette.nentries > + (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry))) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0; i < new_palette.nentries; i++) + { + png_sPLT_entryp pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = png_ptr->chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_tRNS_SUPPORTED) +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_values.gray = png_get_uint_16(buf); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_values.red = png_get_uint_16(buf); + png_ptr->trans_values.green = png_get_uint_16(buf + 2); + png_ptr->trans_values.blue = png_get_uint_16(buf + 4); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_values)); +} +#endif + +#if defined(PNG_READ_bKGD_SUPPORTED) +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + if (num != (unsigned int) png_ptr->num_palette || num > + (unsigned int) PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)", + length + 1); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = png_ptr->chunkdata; *buf; buf++) + /* Empty loop */ ; + + endptr = png_ptr->chunkdata + slength; + + /* We need to have at least 12 bytes after the purpose string + in order to get the parameter information. */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + equation types. */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + params = (png_charpp)png_malloc_warn(png_ptr, + (png_uint_32)(nparams * png_sizeof(png_charp))) ; + if (params == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params."); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)", + length + 1); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + ep = png_ptr->chunkdata + 1; /* Skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed width string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + return; + } + png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + for (ep = png_ptr->chunkdata; *ep; ep++) + /* Empty loop */ ; + ep++; + + if (png_ptr->chunkdata + slength < ep) + { + png_warning(png_ptr, "Truncated sCAL chunk"); +#if defined(PNG_FIXED_POINT_SUPPORTED) && \ + !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed height string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (sheight == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + return; + } + png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + if (png_ptr->chunkdata + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; + } + + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight); +#endif +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif +} +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt"); + + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process text chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + key = png_ptr->chunkdata; + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk."); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk."); +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt"); + + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory processing zTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (text = png_ptr->chunkdata; *text; text++) + /* Empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text >= png_ptr->chunkdata + slength - 2) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else + { + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* Skip the compression_method byte */ + } + prefix_len = text - png_ptr->chunkdata; + + png_decompress_chunk(png_ptr, comp_type, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process zTXt chunk."); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = comp_type; + text_ptr->key = png_ptr->chunkdata; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = png_ptr->chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk."); +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt"); + + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (lang = png_ptr->chunkdata; *lang; lang++) + /* Empty loop */ ; + lang++; /* Skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + * translated keyword (possibly empty), and possibly some text after the + * keyword + */ + + if (lang >= png_ptr->chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + lang_key++; /* Skip NUL separator */ + + if (lang_key >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + for (text = lang_key; *text; text++) + /* Empty loop */ ; + text++; /* Skip NUL separator */ + if (text >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + prefix_len = text - png_ptr->chunkdata; + + key=png_ptr->chunkdata; + if (comp_flag) + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); + else + data_len = png_strlen(png_ptr->chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process iTXt chunk."); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); + text_ptr->lang = png_ptr->chunkdata + (lang - key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = png_ptr->chunkdata; + text_ptr->text = png_ptr->chunkdata + prefix_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk."); +} +#endif + +/* This function is called when we haven't found a handler for a + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown"); + + + if (png_ptr->mode & PNG_HAVE_IDAT) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) || + (png_ptr->read_user_chunk_fn != NULL)) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0'; + png_ptr->unknown_chunk.size = (png_size_t)length; + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row"); + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; +#ifdef PNG_USE_LOCAL_ARRAYS + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#if !defined(PNG_READ_PACKSWAP_SUPPORTED) + transformations = transformations; /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row"); + png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* Use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row = 0; + break; + } +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +#endif + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for (;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data."); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = + PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; + } + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + png_ptr->irowbytes = png_ptr->rowbytes + 1; + } + max_pixel_depth = png_ptr->pixel_depth; + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + } +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#if defined(PNG_READ_EXPAND_SUPPORTED) + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#if defined(PNG_READ_FILLER_SUPPORTED) + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 64 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 64); + if (png_ptr->interlaced) + png_memset(png_ptr->big_row_buf, 0, row_bytes + 64); + png_ptr->row_buf = png_ptr->big_row_buf + 32; + png_ptr->old_big_row_buf_size = row_bytes + 64; + } + +#ifdef PNG_MAX_MALLOC_64K + if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory."); + + if (row_bytes + 1 > png_ptr->old_prev_row_size) + { + png_free(png_ptr, png_ptr->prev_row); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + row_bytes + 1)); + png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1); + png_ptr->old_prev_row_size = row_bytes + 1; + } + + png_ptr->rowbytes = row_bytes; + + png_debug1(3, "width = %lu,", png_ptr->width); + png_debug1(3, "height = %lu,", png_ptr->height); + png_debug1(3, "iwidth = %lu,", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", png_ptr->irowbytes); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/Libraries/libpng/pngset.cpp b/Libraries/libpng/pngset.cpp new file mode 100644 index 0000000..fa68a2d --- /dev/null +++ b/Libraries/libpng/pngset.cpp @@ -0,0 +1,1255 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_bKGD_SUPPORTED) +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_white = (float)white_x; + info_ptr->y_white = (float)white_y; + info_ptr->x_red = (float)red_x; + info_ptr->y_red = (float)red_y; + info_ptr->x_green = (float)green_x; + info_ptr->y_green = (float)green_y; + info_ptr->x_blue = (float)blue_x; + info_ptr->y_blue = (float)blue_y; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); + info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); + info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); + info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); + info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); + info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); + info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); + info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM fixed"); + if (png_ptr == NULL || info_ptr == NULL) + return; + +#if !defined(PNG_NO_CHECK_cHRM) + if (png_check_cHRM_fixed(png_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) +#endif + { + info_ptr->int_x_white = white_x; + info_ptr->int_y_white = white_y; + info_ptr->int_x_red = red_x; + info_ptr->int_y_red = red_y; + info_ptr->int_x_green = green_x; + info_ptr->int_y_green = green_y; + info_ptr->int_x_blue = blue_x; + info_ptr->int_y_blue = blue_y; +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->x_white = (float)(white_x/100000.); + info_ptr->y_white = (float)(white_y/100000.); + info_ptr->x_red = (float)( red_x/100000.); + info_ptr->y_red = (float)( red_y/100000.); + info_ptr->x_green = (float)(green_x/100000.); + info_ptr->y_green = (float)(green_y/100000.); + info_ptr->x_blue = (float)( blue_x/100000.); + info_ptr->y_blue = (float)( blue_y/100000.); +#endif + info_ptr->valid |= PNG_INFO_cHRM; + } +} +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_cHRM_SUPPORTED */ + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + double png_gamma; + png_debug1(1, "in %s storage function", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check for overflow */ + if (file_gamma > 21474.83) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + png_gamma=21474.83; + } + else + png_gamma = file_gamma; + info_ptr->gamma = (float)png_gamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = (int)(png_gamma*100000.+.5); +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0.0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif +void PNGAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + int_gamma) +{ + png_fixed_point png_gamma; + + png_debug1(1, "in %s storage function", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + png_gamma=PNG_UINT_31_MAX; + } + else + { + if (int_gamma < 0) + { + png_warning(png_ptr, "Setting negative gamma to zero"); + png_gamma = 0; + } + else + png_gamma = int_gamma; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = (float)(png_gamma/100000.); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_gamma; +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped."); + return; + } + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); +#endif + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16))); + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data."); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_HIST; +#else + png_ptr->flags |= PNG_FLAG_FREE_HIST; +#endif +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check for width and height valid values */ + if (width == 0 || height == 0) + png_error(png_ptr, "Image width or height is zero in IHDR"); +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || height > png_ptr->user_height_max) + png_error(png_ptr, "image size exceeds user limits in IHDR"); +#else + if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX) + png_error(png_ptr, "image size exceeds user limits in IHDR"); +#endif + if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image size in IHDR"); + if ( width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth in IHDR"); + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + png_error(png_ptr, "Invalid color type in IHDR"); + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); + + if (interlace_type >= PNG_INTERLACE_LAST) + png_error(png_ptr, "Unknown interlace method in IHDR"); + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_error(png_ptr, "Unknown compression method in IHDR"); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + png_error(png_ptr, "Unknown filter method in IHDR"); + if (png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) + png_warning(png_ptr, "Invalid filter method in IHDR"); + } +#else + if (filter_type != PNG_FILTER_TYPE_BASE) + png_error(png_ptr, "Unknown filter method in IHDR"); +#endif + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type =(png_byte) color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* Check for potential overflow */ + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = (png_size_t)0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#if defined(PNG_oFFs_SUPPORTED) +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params) +{ + png_uint_32 length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose."); + return; + } + png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units."); + return; + } + png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params."); + return; + } + + png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter."); + return; + } + png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); + } + + info_ptr->valid |= PNG_INFO_pCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PCAL; +#endif +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + info_ptr->scal_pixel_width = width; + info_ptr->scal_pixel_height = height; + + info_ptr->valid |= PNG_INFO_sCAL; +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_charp swidth, png_charp sheight) +{ + png_uint_32 length; + + png_debug1(1, "in %s storage function", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + + length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", + (unsigned int)length); + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); + return; + } + png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); + + length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", + (unsigned int)length); + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); + return; + } + png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); + info_ptr->valid |= PNG_INFO_sCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SCAL; +#endif +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* + * It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); +#endif + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = (png_colorp)png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH * + png_sizeof(png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PLTE; +#else + png_ptr->flags |= PNG_FLAG_FREE_PLTE; +#endif + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#if defined(PNG_sBIT_SUPPORTED) +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#if defined(PNG_sRGB_SUPPORTED) +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int intent) +{ +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_file_gamma; +#endif +#endif +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y; +#endif + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, intent); + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float).45455; + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + int_file_gamma = 45455L; + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) + int_white_x = 31270L; + int_white_y = 32900L; + int_red_x = 64000L; + int_red_y = 33000L; + int_green_x = 30000L; + int_green_y = 60000L; + int_blue_x = 15000L; + int_blue_y = 6000L; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float).3127; + white_y = (float).3290; + red_x = (float).64; + red_y = (float).33; + green_x = (float).30; + green_y = (float).60; + blue_x = (float).15; + blue_y = (float).06; +#endif + +#if !defined(PNG_NO_CHECK_cHRM) + if (png_check_cHRM_fixed(png_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y)) +#endif + { +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y); +#endif +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif + } +#endif /* cHRM */ +} +#endif /* sRGB */ + + +#if defined(PNG_iCCP_SUPPORTED) +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_charp new_iccp_profile; + png_uint_32 length; + + png_debug1(1, "in %s storage function", "iCCP"); + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + length = png_strlen(name)+1; + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); + return; + } + png_memcpy(new_iccp_name, name, length); + new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, + "Insufficient memory to process iCCP profile."); + return; + } + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types */ + info_ptr->iccp_compression = (png_byte)compression_type; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ICCP; +#endif + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int i; + + png_debug1(1, "in %s storage function", (png_ptr->chunk_name[0] == '\0' ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TEXT; +#endif + } + png_debug1(3, "allocated %d entries for info_ptr->text", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length, key_len; + png_size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + key_len = png_strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + else +#ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } +#else + { + png_warning(png_ptr, "iTXt chunk not supported."); + continue; + } +#endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else +#endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32) + (key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) + return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text", + (png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + else +#endif + { +#ifdef PNG_iTXt_SUPPORTED + textp->lang=NULL; + textp->lang_key=NULL; +#endif + textp->text = textp->key + key_len + 1; + } + if (text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text + text_length) = '\0'; + +#ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else +#endif + { + textp->text_length = text_length; +#ifdef PNG_iTXt_SUPPORTED + textp->itxt_length = 0; +#endif + } + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep trans, int num_trans, png_color_16p trans_values) +{ + png_debug1(1, "in %s storage function", "tRNS"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans != NULL) + { + /* + * It may not actually be necessary to set png_ptr->trans here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); +#endif + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, + (png_uint_32)PNG_MAX_PALETTE_LENGTH); + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); + } + + if (trans_values != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_values->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_values->red > sample_max || + (int)trans_values->green > sample_max || + (int)trans_values->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + png_memcpy(&(info_ptr->trans_values), trans_values, + png_sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TRNS; +#else + png_ptr->flags |= PNG_FLAG_FREE_TRNS; +#endif + } +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * + (png_uint_32)png_sizeof(png_sPLT_t)); + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes."); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; + png_uint_32 length; + + length = png_strlen(from->name) + 1; + to->name = (png_charp)png_malloc_warn(png_ptr, length); + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + continue; + } + png_memcpy(to->name, from->name, length); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry))); + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr, to->name); + to->name = NULL; + continue; + } + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SPLT; +#endif +} +#endif /* PNG_sPLT_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk))); + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks=NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; + + png_memcpy((png_charp)to->name, + (png_charp)from->name, + png_sizeof(from->name)); + to->name[png_sizeof(to->name)-1] = '\0'; + to->size = from->size; + /* Note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + + if (from->size == 0) + to->data=NULL; + else + { + to->data = (png_bytep)png_malloc_warn(png_ptr, + (png_uint_32)from->size); + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + to->size = 0; + } + else + png_memcpy(to->data, from->data, from->size); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_UNKN; +#endif +} +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +void PNGAPI +png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) +{ + /* This function is deprecated in favor of png_permit_mng_features() + and will be removed from libpng-1.3.0 */ + png_debug(1, "in png_permit_empty_plte, DEPRECATED."); + if (png_ptr == NULL) + return; + png_ptr->mng_features_permitted = (png_byte) + ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) | + ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); +} +#endif +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + if (png_ptr == NULL) + return (png_uint_32)0; + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + if (num_chunks == 0) + { + if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks = png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_uint_32) + (5*(num_chunks + old_num_chunks))); + if (png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list + 5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + for (p = new_list + 5*old_num_chunks + 4, i = 0; inum_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; +#ifdef PNG_FREE_ME_SUPPORTED + png_ptr->free_me |= PNG_FREE_LIST; +#endif +} +#endif + +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + if (png_ptr == NULL) + return; + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +#ifdef PNG_WRITE_SUPPORTED +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, + png_uint_32 size) +{ + if (png_ptr == NULL) + return; + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = (png_size_t)size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} +#endif + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + +#ifndef PNG_1_0_X +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +/* Function was added to libpng 1.2.0 and should always exist by default */ +void PNGAPI +png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) +{ +/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ + if (png_ptr != NULL) + png_ptr->asm_flags = 0; + asm_flags = asm_flags; /* Quiet the compiler */ +} + +/* This function was added to libpng 1.2.0 */ +void PNGAPI +png_set_mmx_thresholds (png_structp png_ptr, + png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold) +{ +/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ + if (png_ptr == NULL) + return; + /* Quiet the compiler */ + mmx_bitdepth_threshold = mmx_bitdepth_threshold; + mmx_rowbytes_threshold = mmx_rowbytes_threshold; +} +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +#endif /* ?PNG_1_0_X */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngtrans.cpp b/Libraries/libpng/pngtrans.cpp new file mode 100644 index 0000000..f221f54 --- /dev/null +++ b/Libraries/libpng/pngtrans.cpp @@ -0,0 +1,674 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.2.36 [May 14, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap"); + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing"); + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_byte)filler; + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA? */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +#if !defined(PNG_1_0_X) +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + if (png_ptr == NULL) + return; + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} +#endif + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row == NULL || row_info == NULL) + return; +#endif + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=2) + { + *rp = (png_byte)(~(*rp)); + rp+=2; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=4) + { + *rp = (png_byte)(~(*rp)); + *(rp+1) = (png_byte)(~(*(rp+1))); + rp+=4; + } + } +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth < 8) + { + png_bytep rp, end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = (png_bytep)onebppswaptable; + else if (row_info->bit_depth == 2) + table = (png_bytep)twobppswaptable; + else if (row_info->bit_depth == 4) + table = (png_bytep)fourbppswaptable; + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; + + if ((row_info->color_type == PNG_COLOR_TYPE_RGB || + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || + (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + /* This converts from GX or GA to G */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + /* This converts from XG or AG to G */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + if (flags & PNG_FLAG_STRIP_ALPHA) + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + if (png_ptr == NULL) + return; +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +#else + if (user_transform_ptr || user_transform_depth || user_transform_channels) + png_warning(png_ptr, + "This version of libpng does not support user transform info"); +#endif +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +png_voidp PNGAPI +png_get_user_transform_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + return ((png_voidp)png_ptr->user_transform_ptr); +#else + return (NULL); +#endif +} +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngvcrd.cpp b/Libraries/libpng/pngvcrd.cpp new file mode 100644 index 0000000..ce4233e --- /dev/null +++ b/Libraries/libpng/pngvcrd.cpp @@ -0,0 +1 @@ +/* pnggvrd.c was removed from libpng-1.2.20. */ diff --git a/Libraries/libpng/pngwio.cpp b/Libraries/libpng/pngwio.cpp new file mode 100644 index 0000000..740b71d --- /dev/null +++ b/Libraries/libpng/pngwio.cpp @@ -0,0 +1,256 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL write function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + if (png_ptr == NULL) + return; +#if defined(_WIN32_WCE) + if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); +#endif + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + * can't handle far buffers in the medium and small models, we have to copy + * the data. + */ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(near_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) + err = 0; +#else + err = fwrite(buf, 1, written, io_ptr); +#endif + if (err != written) + break; + + else + check += err; + + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +#if !defined(PNG_NO_STDIO) +void PNGAPI +png_default_flush(png_structp png_ptr) +{ +#if !defined(_WIN32_WCE) + png_FILE_p io_ptr; +#endif + if (png_ptr == NULL) + return; +#if !defined(_WIN32_WCE) + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +#endif +} +#endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of ouput, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; +#else + png_ptr->output_flush_fn = output_flush_fn; +#endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL."); + } +} + +#if defined(USE_FAR_KEYWORD) +#if defined(_MSC_VER) +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (far_ptr != ptr) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# endif +# endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngwrite.cpp b/Libraries/libpng/pngwrite.cpp new file mode 100644 index 0000000..bd6263c --- /dev/null +++ b/Libraries/libpng/pngwrite.cpp @@ -0,0 +1,1558 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* Get internal access to png.h */ +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + png_write_sig(png_ptr); /* Write PNG signature */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted=0; + } +#endif + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + info_ptr->interlace_type); +#else + 0); +#endif + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#if defined(PNG_WRITE_gAMA_SUPPORTED) + if (info_ptr->valid & PNG_INFO_gAMA) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_gAMA(png_ptr, info_ptr->gamma); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif +#if defined(PNG_WRITE_iCCP_SUPPORTED) + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#if defined(PNG_WRITE_sBIT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_cHRM_SUPPORTED) + if (info_ptr->valid & PNG_INFO_cHRM) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#else +# ifdef PNG_FIXED_POINT_SUPPORTED + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#if defined(PNG_WRITE_tRNS_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tRNS) + { +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j=0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#if defined(PNG_WRITE_bKGD_SUPPORTED) + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_hIST_SUPPORTED) + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif +#if defined(PNG_WRITE_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif +#if defined(PNG_WRITE_pCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#if defined(PNG_sCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sCAL) +#if defined(PNG_WRITE_sCAL_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); +#else /* !FLOATING_POINT */ +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* FIXED_POINT */ +#endif /* FLOATING_POINT */ +#else /* !WRITE_sCAL */ + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written."); +#endif /* WRITE_sCAL */ +#endif /* sCAL */ + +#if defined(PNG_WRITE_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#if defined(PNG_WRITE_tIME_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#if defined(PNG_WRITE_sPLT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end"); + if (png_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#if defined(PNG_WRITE_TEXT_SUPPORTED) + int i; /* Local index variable */ +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . This kludge will be removed + * from libpng-1.4.0. + */ +#if defined(PNG_WRITE_FLUSH_SUPPORTED) && \ + defined(PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED) + png_flush(png_ptr); +#endif +} + +#if defined(PNG_WRITE_tIME_SUPPORTED) +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + int i; + png_debug(1, "in png_create_write_struct"); +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; + png_destroy_struct(png_ptr); + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i=0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then encounter + a png_error() will longjmp here. Since the jmpbuf is then meaningless we + abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +/* Initialize png_ptr structure, and allocate any memory needed */ +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Deprecated. */ +#undef png_write_init +void PNGAPI +png_write_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ + if (png_ptr == NULL) return; +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if (png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if (png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for writing is too small."); + } + if (png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by the application for writing is too small."); + } + png_write_init_3(&png_ptr, user_png_ver, png_struct_size); +} +#endif /* PNG_1_0_X || PNG_1_2_X */ + + +void PNGAPI +png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ + png_structp png_ptr=*ptr_ptr; +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* To save current jump buffer */ +#endif + + int i = 0; + + if (png_ptr == NULL) + return; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_write_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_write_init_3"); + +#ifdef PNG_SETJMP_SUPPORTED + /* Save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + if (png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + *ptr_ptr = png_ptr; + } + + /* Reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif +} + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* Row counter */ + png_bytepp rp; /* Row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* Row index */ + int pass, num_pass; /* Pass variables */ + png_bytepp rp; /* Points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr == NULL) + return; + png_debug2(1, "in png_write_row (row %ld, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row."); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); +#endif + + png_write_start_row(png_ptr); + } + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + /* Set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, + png_ptr->row_info.rowbytes); + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + if (png_ptr == NULL) + return; + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush"); + if (png_ptr == NULL) + return; + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while(wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* Free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct"); + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + if (png_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list = 0; + } +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* Save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy"); + /* Free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); +#ifndef PNG_NO_WRITE_FILTER + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_free(png_ptr, png_ptr->prev_filters); + png_free(png_ptr, png_ptr->filter_weights); + png_free(png_ptr, png_ptr->inv_filter_weights); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + if (png_ptr == NULL) + return; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifndef PNG_NO_WRITE_FILTER + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_NO_WRITE_FILTER */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter=PNG_FILTER_NONE; break; +#ifndef PNG_NO_WRITE_FILTER + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter=PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter=PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter=PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter=PNG_FILTER_PAETH; break; + default: png_ptr->do_filter = (png_byte)filters; break; +#else + default: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_NO_WRITE_FILTER */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifndef PNG_NO_WRITE_FILTER + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_NO_WRITE_FILTER */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_doublep filter_weights, + png_doublep filter_costs) +{ + int i; + + png_debug(1, "in png_set_filter_heuristics"); + if (png_ptr == NULL) + return; + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return; + } + + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) + { + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + } + + if (num_weights < 0 || filter_weights == NULL || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + num_weights = 0; + } + + png_ptr->num_prev_filters = (png_byte)num_weights; + png_ptr->heuristic_method = (png_byte)heuristic_method; + + if (num_weights > 0) + { + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } + + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } + + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } + } +} +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits=9; + } +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + if (png_ptr == NULL) + return; + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->write_row_fn = write_row_fn; +} + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#if defined(PNG_WRITE_INVERT_SUPPORTED) + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) + /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + transforms = transforms; /* Quiet compiler warnings */ + params = params; +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngwtran.cpp b/Libraries/libpng/pngwtran.cpp new file mode 100644 index 0000000..ac56339 --- /dev/null +++ b/Libraries/libpng/pngwtran.cpp @@ -0,0 +1,572 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.2.37 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#if defined(PNG_WRITE_PACK_SUPPORTED) +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + if (row_info->bit_depth == 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; + + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && +#else + if ( +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from ARGB to RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AARRGGBB to RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from AG to GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AAGG to GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + } +} +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Libraries/libpng/pngwutil.cpp b/Libraries/libpng/pngwutil.cpp new file mode 100644 index 0000000..22a83cc --- /dev/null +++ b/Libraries/libpng/pngwutil.cpp @@ -0,0 +1,2788 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.2.36 [June 4, 2009] + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void /* PRIVATE */ +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_bytep chunk_name, + png_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, (png_size_t)length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + + png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, + (unsigned long)length); + if (png_ptr == NULL) + return; + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_memcpy(buf + 4, chunk_name, 4); + png_write_data(png_ptr, buf, (png_size_t)8); + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, chunk_name, 4); + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* The uncompressed input data */ + int input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_charpp output_ptr; /* Array of pointers to output */ +} compression_state; + +/* Compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = 0; + + /* We may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + png_snprintf(msg, 50, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* Set up the compression buffers */ + png_ptr->zstream.avail_in = (uInt)text_len; + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; + + /* This is the same compression loop as in png_write_row() */ + do + { + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + /* Error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32) + (comp->max_output_ptr * png_sizeof(png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* Continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* Finish the compression */ + do + { + /* Tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof(png_charp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* We got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* Ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* Handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, + (png_size_t)comp->input_len); + return; + } + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + comp->output_ptr[i]=NULL; + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; + /* Write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + + /* Reset zlib for another zTXt/iTXt or image data */ + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; +#endif + int ret; + + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); + + /* Initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + if (ret != Z_OK) + { + if (ret == Z_VERSION_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- version error"); + if (ret == Z_STREAM_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- stream error"); + if (ret == Z_MEM_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- mem error"); + png_error(png_ptr, "zlib failed to initialize compressor"); + } + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* libpng is not interested in zstream.data_type */ + /* Set it to a predefined value, to avoid its evaluation inside zlib */ + png_ptr->zstream.data_type = Z_BINARY; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_PLTE; +#endif + png_uint_32 i; + png_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + if (( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, + (png_uint_32)(num_pal * 3)); +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#else + /* This is a little slower but some buggy compilers need to do this instead */ + pal_ptr=palette; + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* Write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + png_debug(1, "in png_write_IDAT"); + + /* Optimize the CMF field in the zlib stream. */ + /* This hack of the zlib stream is compliant to the stream specification. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. + * + * The conditions below are practically always satisfied; + * however, they still must be checked. + */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != (png_byte)z_cmf) + { + data[0] = (png_byte)z_cmf; + data[1] &= 0xe0; + data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); + } + } + } + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + + png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IEND; +#endif + png_debug(1, "in png_write_IEND"); + png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL, + (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +/* Write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA(png_structp png_ptr, double file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_uint_32 igamma; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + /* file_gamma is saved in 1/100,000ths */ + igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); + png_save_uint_32(buf, igamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sRGB; +#endif + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); +} +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iCCP; +#endif + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_bytep)profile ))<<24) | + ((*( (png_bytep)profile + 1))<<16) | + ((*( (png_bytep)profile + 2))<< 8) | + ((*( (png_bytep)profile + 3)) ); + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + png_free(png_ptr, new_name); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, + (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); + + /* Make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, + (png_uint_32)(name_len + profile_len + 2)); + new_name[name_len + 1] = 0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 2)); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sPLT; +#endif + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + int entry_size = (spalette->depth == 8 ? 6 : 10); + int palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifdef PNG_NO_POINTER_INDEXING + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) + return; + + /* Make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifndef PNG_NO_POINTER_INDEXING + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i=0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sBIT; +#endif + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); +} +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +/* Write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM(png_structp png_ptr, double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, + int_green_x, int_green_y, int_blue_x, int_blue_y; + + png_debug(1, "in png_write_cHRM"); + + int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5); + int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5); + int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5); + int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5); + int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5); + int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5); + int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5); + int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5); + +#if !defined(PNG_NO_CHECK_cHRM) + if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y, + int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y)) +#endif + { + /* Each value is saved in 1/100,000ths */ + + png_save_uint_32(buf, int_white_x); + png_save_uint_32(buf + 4, int_white_y); + + png_save_uint_32(buf + 8, int_red_x); + png_save_uint_32(buf + 12, int_red_y); + + png_save_uint_32(buf + 16, int_green_x); + png_save_uint_32(buf + 20, int_green_y); + + png_save_uint_32(buf + 24, int_blue_x); + png_save_uint_32(buf + 28, int_blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); + } +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + /* Each value is saved in 1/100,000ths */ +#if !defined(PNG_NO_CHECK_cHRM) + if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y)) +#endif + { + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); + } +} +#endif +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, + int num_trans, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tRNS; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid number of transparent colors specified"); + return; + } + /* Write the chunk out as it is */ + png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, + (png_size_t)num_trans); + } + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); + } + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_bKGD; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); + } + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); + } + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_hIST; +#endif + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, (png_bytep)png_hIST, + (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword"); + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) + { + if ((png_byte)*kp < 0x20 || + ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[40]; + + png_snprintf(msg, 40, + "invalid keyword character 0x%02X", (png_byte)*kp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + else + { + *dp = *kp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if (kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + *new_key=NULL; + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + (*new_key)[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tEXt; +#endif + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt"); + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if (text == NULL || *text == '\0') + text_len = 0; + else + text_len = png_strlen(text); + + /* Make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, + (png_uint_32)(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + if (text_len) + png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len, int compression) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_zTXt; +#endif + png_size_t key_len; + char buf[1]; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_free(png_ptr, new_key); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* Write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, + (png_uint_32)(key_len+text_len + 2)); + /* Write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + png_free(png_ptr, new_key); + + buf[0] = (png_byte)compression; + /* Write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp lang_key, png_charp text) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iTXt; +#endif + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang; + png_charp new_key = NULL; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + else + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression-2, + &comp); + + + /* Make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts */ + + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + /* Set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || \ + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + /* Set the compression method */ + cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), + (png_size_t)(lang_key_len + 1)); + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_oFFs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); +} +#endif +#if defined(PNG_WRITE_pCAL_SUPPORTED) +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pCAL; +#endif + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, + (png_uint_32)(nparams * png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + null terminator for the last parameter. */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long) params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)new_purpose, + (png_size_t)purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +/* Write the sCAL chunk */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +void /* PRIVATE */ +png_write_sCAL(png_structp png_ptr, int unit, double width, double height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + char buf[64]; + png_size_t total_len; + + png_debug(1, "in png_write_sCAL"); + + buf[0] = (char)unit; +#if defined(_WIN32_WCE) +/* sprintf() function is not supported on WindowsCE */ + { + wchar_t wc_buf[32]; + size_t wc_len; + swprintf(wc_buf, TEXT("%12.12e"), width); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL); + total_len = wc_len + 2; + swprintf(wc_buf, TEXT("%12.12e"), height); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, + NULL, NULL); + total_len += wc_len; + } +#else + png_snprintf(buf + 1, 63, "%12.12e", width); + total_len = 1 + png_strlen(buf + 1) + 1; + png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); + total_len += png_strlen(buf + total_len); +#endif + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, + png_charp height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len); +} +#endif +#endif +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pHYs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); +} +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_timep mod_time) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tIME; +#endif + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +#ifdef PNG_USE_LOCAL_ARRAYS + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row"); + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifndef PNG_NO_WRITE_FILTER + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)buf_size); + png_memset(png_ptr->prev_row, 0, buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_NO_WRITE_FILTER */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +#ifdef PNG_USE_LOCAL_ARRAYS + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif +#endif + + int ret; + + png_debug(1, "in png_write_finish_row"); + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* Tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + /* Check for an error */ + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1, "in png_do_write_interlace"); + /* We don't have to do anything on the last pass (6) */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && pass < 6) +#else + if (pass < 6) +#endif + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + /* Loop through the row, only looking at the pixels that + matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + /* Move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifndef PNG_NO_WRITE_FILTER + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_uint_32 row_bytes = row_info->rowbytes; +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifndef PNG_NO_WRITE_FILTER + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && + filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_NO_WRITE_FILTER */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifndef PNG_NO_WRITE_FILTER +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_NO_WRITE_FILTER */ +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_debug(1, "in png_write_filtered_row"); + png_debug1(2, "filter = %d", filtered_row[0]); + /* Set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + /* See if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* Repeat until all data has been compressed */ + } while (png_ptr->zstream.avail_in); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Libraries/unzip101e/crypt.h b/Libraries/unzip101e/crypt.h new file mode 100644 index 0000000..e3c0e51 --- /dev/null +++ b/Libraries/unzip101e/crypt.h @@ -0,0 +1,132 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(//passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd, /* password string */ + unsigned char *buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const unsigned long* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/Libraries/unzip101e/ioapi.cpp b/Libraries/unzip101e/ioapi.cpp new file mode 100644 index 0000000..880ca4a --- /dev/null +++ b/Libraries/unzip101e/ioapi.cpp @@ -0,0 +1,177 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +#include "../zlib123/zlib.h" +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_file_func OF(( + voidpf opaque, + voidpf stream)); + + +voidpf ZCALLBACK fopen_file_func (//opaque, filename, mode) + voidpf opaque, + const char* filename, + int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (//opaque, stream, buf, size) + voidpf opaque, + voidpf stream, + void* buf, + uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (//opaque, stream, buf, size) + voidpf opaque, + voidpf stream, + const void* buf, + uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (//opaque, stream) + voidpf opaque, + voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (//opaque, stream, offset, origin) + voidpf opaque, + voidpf stream, + uLong offset, + int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (//opaque, stream) + voidpf opaque, + voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (//opaque, stream) + voidpf opaque, + voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (//pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/Libraries/unzip101e/ioapi.h b/Libraries/unzip101e/ioapi.h new file mode 100644 index 0000000..e73a3b2 --- /dev/null +++ b/Libraries/unzip101e/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Libraries/unzip101e/iowin32.cpp b/Libraries/unzip101e/iowin32.cpp new file mode 100644 index 0000000..0c4dbbb --- /dev/null +++ b/Libraries/unzip101e/iowin32.cpp @@ -0,0 +1,274 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + This IO API version uses the Win32 API (for Microsoft Windows) + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifdef _WIN32 + +#include + +#include "../zlib123/zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +voidpf ZCALLBACK win32_open_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK win32_read_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK win32_write_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK win32_tell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK win32_seek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK win32_close_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK win32_error_file_func OF(( + voidpf opaque, + voidpf stream)); + +typedef struct +{ + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + +voidpf ZCALLBACK win32_open_file_func (//opaque, filename, mode) + voidpf opaque, + const char* filename, + int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = 0; + voidpf ret=NULL; + + dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + { + dwDesiredAccess = GENERIC_READ; + dwCreationDisposition = OPEN_EXISTING; + dwShareMode = FILE_SHARE_READ; + } + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + dwCreationDisposition = OPEN_EXISTING; + } + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + dwCreationDisposition = CREATE_ALWAYS; + } + + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, + dwCreationDisposition, dwFlagsAndAttributes, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + hFile = NULL; + + if (hFile != NULL) + { + WIN32FILE_IOWIN w32fiow; + w32fiow.hf = hFile; + w32fiow.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + if (ret==NULL) + CloseHandle(hFile); + else *((WIN32FILE_IOWIN*)ret) = w32fiow; + } + return ret; +} + + +uLong ZCALLBACK win32_read_file_func (//opaque, stream, buf, size) + voidpf opaque, + voidpf stream, + void* buf, + uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + + return ret; +} + + +uLong ZCALLBACK win32_write_file_func (//opaque, stream, buf, size) + voidpf opaque, + voidpf stream, + const void* buf, + uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile !=NULL) + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + + return ret; +} + +long ZCALLBACK win32_tell_file_func (//opaque, stream) + voidpf opaque, + voidpf stream) +{ + long ret=-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + if (dwSet == INVALID_SET_FILE_POINTER) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=(long)dwSet; + } + return ret; +} + +long ZCALLBACK win32_seek_file_func (//opaque, stream, offset, origin) + voidpf opaque, + voidpf stream, + uLong offset, + int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + + long ret=-1; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile != NULL) + { + DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); + if (dwSet == INVALID_SET_FILE_POINTER) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func (//opaque, stream) + voidpf opaque, + voidpf stream) +{ + int ret=-1; + + if (stream!=NULL) + { + HANDLE hFile; + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + CloseHandle(hFile); + ret=0; + } + free(stream); + } + return ret; +} + +int ZCALLBACK win32_error_file_func (//opaque, stream) + voidpf opaque, + voidpf stream) +{ + int ret=-1; + if (stream!=NULL) + { + ret = ((WIN32FILE_IOWIN*)stream) -> error; + } + return ret; +} + +void fill_win32_filefunc (//pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque=NULL; +} + +#endif diff --git a/Libraries/unzip101e/iowin32.h b/Libraries/unzip101e/iowin32.h new file mode 100644 index 0000000..2877392 --- /dev/null +++ b/Libraries/unzip101e/iowin32.h @@ -0,0 +1,25 @@ +/* iowin32.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + This IO API version uses the Win32 API (for Microsoft Windows) + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifdef WIN32 + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Libraries/unzip101e/unzip.cpp b/Libraries/unzip101e/unzip.cpp new file mode 100644 index 0000000..4edb523 --- /dev/null +++ b/Libraries/unzip101e/unzip.cpp @@ -0,0 +1,1603 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unzlocal_getByte(//pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi) +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getShort (//pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getLong (//pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (//fileName1,fileName2) + const char* fileName1, + const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (//fileName1,fileName2,iCaseSensitivity) + const char* fileName1, + const char* fileName2, + int iCaseSensitivity) +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong unzlocal_SearchCentralDir(//pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (//path, pzlib_filefunc_def) + const char *path, + zlib_filefunc_def* pzlib_filefunc_def) +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (//file,pglobal_info) + unzFile file, + unz_global_info *pglobal_info) +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (//ulDosDate, ptm) + uLong ulDosDate, + tm_unz* ptm) +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (/*file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize)*/ + unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (/*file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize)*/ + unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (//file) + unzFile file) +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (//file) + unzFile file) +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (//file, szFileName, iCaseSensitivity) + unzFile file, + const char *szFileName, + int iCaseSensitivity) +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(//file, file_pos) + unzFile file, + unz_file_pos* file_pos) +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(//file, file_pos) + unzFile file, + unz_file_pos* file_pos) +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (/*s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield)*/ + unz_s* s, + uInt* piSizeVar, + uLong *poffset_local_extrafield, + uInt *psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (//file, method, level, raw, password) + unzFile file, + int* method, + int* level, + int raw, + const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (Bytef*)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (//file) + unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (//file, password) + unzFile file, + const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (//file,method,level,raw) + unzFile file, + int* method, + int* level, + int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (//file, buf, len) + unzFile file, + voidp buf, + unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (//file) + unzFile file) +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (//file) + unzFile file) +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (//file,buf,len) + unzFile file, + voidp buf, + unsigned len) +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (//file) + unzFile file) +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (//file, szComment, uSizeBuf) + unzFile file, + char *szComment, + uLong uSizeBuf) +{ +// int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (//file) + unzFile file) +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (//file, pos) + unzFile file, + uLong pos) +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/Libraries/unzip101e/unzip.h b/Libraries/unzip101e/unzip.h new file mode 100644 index 0000000..1184783 --- /dev/null +++ b/Libraries/unzip101e/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "../zlib123/zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/Libraries/unzip101e/zip.cpp b/Libraries/unzip101e/zip.cpp new file mode 100644 index 0000000..5941e65 --- /dev/null +++ b/Libraries/unzip101e/zip.cpp @@ -0,0 +1,1219 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.01e, February 12th, 2005 + + 27 Dec 2004 Rolf Kalbermatter + Modification to zipOpen2 to support globalComment retrieval. + + Copyright (C) 1998-2005 Gilles Vollant + + Read zip.h for more info +*/ + + +#include +#include +#include +#include + +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] = + " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + uLong pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralheader; /* size of the central header for cur file */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile_info; + +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile_info ci; /* info on the file curretly writing */ + + uLong begin_pos; /* position of the beginning of the zipfile */ + uLong add_position_when_writting_offset; + uLong number_entry; +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif +} zip_internal; + + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(//ldi) + linkedlist_datablock_internal* ldi) +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(//ll) + linkedlist_data* ll) +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(//ll) + linkedlist_data* ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(//ll,buf,len) + linkedlist_data* ll, + const void* buf, + uLong len) +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 or 4 (byte, short or long) +*/ + +local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, uLong x, int nbByte)); +local int ziplocal_putValue (//pzlib_filefunc_def, filestream, x, nbByte) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong x, + int nbByte) +{ + unsigned char buf[4]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); +local void ziplocal_putValue_inmemory (//dest, x, nbByte) + void* dest, + uLong x, + int nbByte) +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong ziplocal_TmzDateToDosDate(//ptm,dosDate) + const tm_zip* ptm, + uLong dosDate) +{ + uLong year = (uLong)ptm->tm_year; + if (year>1980) + year-=1980; + else if (year>80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int ziplocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int ziplocal_getByte(//pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi) +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int ziplocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getShort (//pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int ziplocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getLong (//pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong ziplocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong ziplocal_SearchCentralDir(//pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + +/************************************************************/ +extern zipFile ZEXPORT zipOpen2 (//pathname, append, globalcomment, pzlib_filefunc_def) + const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def) +{ + zip_internal ziinit; + zip_internal* zi; + int err=ZIP_OK; + + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&ziinit.z_filefunc); + else + ziinit.z_filefunc = *pzlib_filefunc_def; + + ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) + (ziinit.z_filefunc.opaque, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writting_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + zi = (zip_internal*)ALLOC(sizeof(zip_internal)); + if (zi==NULL) + { + ZCLOSE(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory */ + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry; + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong size_comment; + + central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); + if (central_pos==0) + err=ZIP_ERRNO; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* zipfile global comment length */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((central_pos0) + { + ziinit.globalcomment = (char*)ALLOC(size_comment+1); + if (ziinit.globalcomment) + { + size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); + ziinit.globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - + (offset_central_dir+size_central_dir); + ziinit.add_position_when_writting_offset = byte_before_the_zipfile; + + { + uLong size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir + byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + uLong read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&ziinit.central_dir,buf_read, + (uLong)read_this); + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + ziinit.begin_pos = byte_before_the_zipfile; + ziinit.number_entry = number_entry_CD; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen (//pathname, append) + const char *pathname, + int append) +{ + return zipOpen2(pathname,append,NULL,NULL); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (/*file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting)*/ + zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting) +{ + zip_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); + } + + zi->ci.flag = 0; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if (level==2) + zi->ci.flag |= 4; + if (level==1) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + + size_extrafield_global + size_comment; + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); + + ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + /* write the local header */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); + + if ((err==ZIP_OK) && (size_filename>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + + if ((err==ZIP_OK) && (size_extrafield_local>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) + !=size_extrafield_local) + err = ZIP_ERRNO; + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, + Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = 1; + } +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip2(/*file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw)*/ + zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw) +{ + return zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip (/*file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level)*/ + zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level) +{ + return zipOpenNewFileInZip2 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0); +} + +local int zipFlushWriteBuffer(//zi) + zip_internal* zi) +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, + zi->ci.buffered_data[i],t); +#endif + } + if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) + !=zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (//file, buf, len) + zipFile file, + const void* buf, + unsigned len) +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.avail_in = len; + zi->ci.crc32 = crc32(zi->ci.crc32,(const Bytef*)buf,len); + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + for (i=0;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (//file, uncompressed_size, crc32) + zipFile file, + uLong uncompressed_size, + uLong crc32) +{ + zip_internal* zi; + uLong compressed_size; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = (uLong)zi->ci.stream.total_in; + } + compressed_size = (uLong)zi->ci.stream.total_out; +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + compressed_size,4); /*compr size*/ + if (zi->ci.stream.data_type == Z_ASCII) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + ziplocal_putValue_inmemory(zi->ci.central_header+24, + uncompressed_size,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (ZSEEK(zi->z_filefunc,zi->filestream, + zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + + if (ZSEEK(zi->z_filefunc,zi->filestream, + cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (//file) + zipFile file) +{ + return zipCloseFileInZipRaw (file,0,0); +} + +extern int ZEXPORT zipClose (//file, global_comment) + zipFile file, + const char* global_comment) +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = (uInt)strlen(global_comment); + + centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + ldi->data,ldi->filled_in_this_block) + !=ldi->filled_in_this_block ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, + (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + global_comment,size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + + if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} diff --git a/Libraries/unzip101e/zip.h b/Libraries/unzip101e/zip.h new file mode 100644 index 0000000..63833f1 --- /dev/null +++ b/Libraries/unzip101e/zip.h @@ -0,0 +1,235 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "../zlib123/zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCtypting)); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCtypting : crc of file to compress (needed for crypting) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); +/* + Close the current file in the zipfile, for fiel opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/Libraries/zlib123/adler32.cpp b/Libraries/zlib123/adler32.cpp new file mode 100644 index 0000000..43357dd --- /dev/null +++ b/Libraries/zlib123/adler32.cpp @@ -0,0 +1,144 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) + +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/Libraries/zlib123/compress.cpp b/Libraries/zlib123/compress.cpp new file mode 100644 index 0000000..5f46781 --- /dev/null +++ b/Libraries/zlib123/compress.cpp @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (//dest, destLen, source, sourceLen, level) + Bytef *dest, + uLongf *destLen, + const Bytef *source, + uLong sourceLen, + int level) +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (//dest, destLen, source, sourceLen) + Bytef *dest, + uLongf *destLen, + const Bytef *source, + uLong sourceLen) +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (//sourceLen) + uLong sourceLen ) +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/Libraries/zlib123/crc32.cpp b/Libraries/zlib123/crc32.cpp new file mode 100644 index 0000000..922c752 --- /dev/null +++ b/Libraries/zlib123/crc32.cpp @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(//crc, buf, len) + unsigned long crc, + const unsigned char FAR *buf, + unsigned len) +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(//crc, buf, len) + unsigned long crc, + const unsigned char FAR *buf, + unsigned len) +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(//crc, buf, len) + unsigned long crc, + const unsigned char FAR *buf, + unsigned len) +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(//mat, vec) + unsigned long *mat, + unsigned long vec) +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(//square, mat) + unsigned long *square, + unsigned long *mat) +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(//crc1, crc2, len2) + uLong crc1, + uLong crc2, + z_off_t len2) +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/Libraries/zlib123/crc32.h b/Libraries/zlib123/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/Libraries/zlib123/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/Libraries/zlib123/deflate.cpp b/Libraries/zlib123/deflate.cpp new file mode 100644 index 0000000..0ae03ea --- /dev/null +++ b/Libraries/zlib123/deflate.cpp @@ -0,0 +1,1737 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(//strm, level, version, stream_size) + z_streamp strm, + int level, + const char *version, + int stream_size) +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(/*strm, level, method, windowBits, memLevel, strategy, + version, stream_size)*/ + z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy, + const char *version, + int stream_size) +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (//strm, dictionary, dictLength) + z_streamp strm, + const Bytef *dictionary, + uInt dictLength) +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (//strm) + z_streamp strm) +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (//strm, head) + z_streamp strm, + gz_headerp head) +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (//strm, bits, value) + z_streamp strm, + int bits, + int value) +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(//strm, level, strategy) + z_streamp strm, + int level, + int strategy) +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(//strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain) +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(//strm, sourceLen) + z_streamp strm, + uLong sourceLen) +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (//s, b) + deflate_state *s, + uInt b) +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(//strm) + z_streamp strm) +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (//strm, flush) + z_streamp strm, + int flush) +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (//strm) + z_streamp strm) +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (//dest, source) + z_streamp dest, + z_streamp source) +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(//strm, buf, size) + z_streamp strm, + Bytef *buf, + unsigned size) +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (//s) + deflate_state *s) +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(//s, cur_match) + deflate_state *s, + IPos cur_match) /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(//s, cur_match) + deflate_state *s, + IPos cur_match) /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(/*s, start, match, length*/ + deflate_state *s, + IPos start, + IPos match, + int length) +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(//s) + deflate_state *s) +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(//s, flush) + deflate_state *s, + int flush) +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(//s, flush) + deflate_state *s, + int flush) +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(//s, flush) + deflate_state *s, + int flush) +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/Libraries/zlib123/deflate.h b/Libraries/zlib123/deflate.h new file mode 100644 index 0000000..222c53e --- /dev/null +++ b/Libraries/zlib123/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/Libraries/zlib123/inffast.cpp b/Libraries/zlib123/inffast.cpp new file mode 100644 index 0000000..a56a6ba --- /dev/null +++ b/Libraries/zlib123/inffast.cpp @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in _this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(//strm, start) +z_streamp strm, +unsigned start) /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code _this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + _this = lcode[hold & lmask]; + dolen: + op = (unsigned)(_this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(_this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, _this.val >= 0x20 && _this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", _this.val)); + PUP(out) = (unsigned char)(_this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(_this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + _this = dcode[hold & dmask]; + dodist: + op = (unsigned)(_this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(_this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(_this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + _this = dcode[_this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + _this = lcode[_this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/Libraries/zlib123/inffast.h b/Libraries/zlib123/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/Libraries/zlib123/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/Libraries/zlib123/inffixed.h b/Libraries/zlib123/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/Libraries/zlib123/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/Libraries/zlib123/inflate.cpp b/Libraries/zlib123/inflate.cpp new file mode 100644 index 0000000..f892c49 --- /dev/null +++ b/Libraries/zlib123/inflate.cpp @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(//strm) +z_streamp strm) +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(//strm, bits, value) +z_streamp strm, +int bits, +int value) +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(//strm, windowBits, version, stream_size) +z_streamp strm, +int windowBits, +const char *version, +int stream_size) +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(//strm, version, stream_size) +z_streamp strm, +const char *version, +int stream_size) +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally _this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead _this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(//state) +struct inflate_state FAR *state) +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do _this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do _this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: _this file should *not* be used by applications."); + puts(" It is part of the implementation of _this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during _this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(//strm, out) +z_streamp strm, +unsigned out) +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In _this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(//strm, flush) +z_streamp strm, +int flush) +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code _this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + _this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(_this.bits) <= bits) break; + PULLBYTE(); + } + if (_this.val < 16) { + NEEDBITS(_this.bits); + DROPBITS(_this.bits); + state->lens[state->have++] = _this.val; + } + else { + if (_this.val == 16) { + NEEDBITS(_this.bits + 2); + DROPBITS(_this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (_this.val == 17) { + NEEDBITS(_this.bits + 3); + DROPBITS(_this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(_this.bits + 7); + DROPBITS(_this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + _this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(_this.bits) <= bits) break; + PULLBYTE(); + } + if (_this.op && (_this.op & 0xf0) == 0) { + last = _this; + for (;;) { + _this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + _this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(_this.bits); + state->length = (unsigned)_this.val; + if ((int)(_this.op) == 0) { + Tracevv((stderr, _this.val >= 0x20 && _this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", _this.val)); + state->mode = LIT; + break; + } + if (_this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (_this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(_this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + _this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(_this.bits) <= bits) break; + PULLBYTE(); + } + if ((_this.op & 0xf0) == 0) { + last = _this; + for (;;) { + _this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + _this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(_this.bits); + if (_this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)_this.val; + state->extra = (unsigned)(_this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(//strm) +z_streamp strm) +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(//strm, dictionary, dictLength) +z_streamp strm, +const Bytef *dictionary, +uInt dictLength) +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(//strm, head) +z_streamp strm, +gz_headerp head) +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(//have, buf, len) +unsigned FAR *have, +unsigned char FAR *buf, +unsigned len) +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(//strm) +z_streamp strm) +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(//strm) +z_streamp strm) +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(//dest, source) +z_streamp dest, +z_streamp source) +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/Libraries/zlib123/inflate.h b/Libraries/zlib123/inflate.h new file mode 100644 index 0000000..fbbc871 --- /dev/null +++ b/Libraries/zlib123/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/Libraries/zlib123/inftrees.cpp b/Libraries/zlib123/inftrees.cpp new file mode 100644 index 0000000..5923d37 --- /dev/null +++ b/Libraries/zlib123/inftrees.cpp @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep _this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(//type, lens, codes, table, bits, work) +codetype type, +unsigned short FAR *lens, +unsigned codes, +code FAR * FAR *table, +unsigned FAR *bits, +unsigned short FAR *work) +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code _this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure _this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in _this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + _this.op = (unsigned char)64; /* invalid code marker */ + _this.bits = (unsigned char)1; + _this.val = (unsigned short)0; + *(*table)++ = _this; /* make a table to force an error */ + *(*table)++ = _this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In _this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for _this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after _this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + _this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + _this.op = (unsigned char)0; + _this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + _this.op = (unsigned char)(extra[work[sym]]); + _this.val = base[work[sym]]; + } + else { + _this.op = (unsigned char)(32 + 64); /* end of block */ + _this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = _this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + _this.op = (unsigned char)64; /* invalid code marker */ + _this.bits = (unsigned char)(len - drop); + _this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + _this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = _this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/Libraries/zlib123/inftrees.h b/Libraries/zlib123/inftrees.h new file mode 100644 index 0000000..dc0fd56 --- /dev/null +++ b/Libraries/zlib123/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/Libraries/zlib123/trees.cpp b/Libraries/zlib123/trees.cpp new file mode 100644 index 0000000..d333342 --- /dev/null +++ b/Libraries/zlib123/trees.cpp @@ -0,0 +1,1222 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)) +/* +local void send_bits(s, value, length) + deflate_state *s; + int value; // value to send + int length; // number of bits +*/ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(//s) + deflate_state *s) +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(//s) + deflate_state *s) +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(//s, tree, k) + deflate_state *s, + ct_data *tree, /* the tree to restore */ + int k) /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(//s, desc) + deflate_state *s, + tree_desc *desc) /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (//tree, max_code, bl_count) + ct_data *tree, /* the tree to decorate */ + int max_code, /* largest code with non zero frequency */ + ushf *bl_count) /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (//s, tree, max_code) + deflate_state *s, + ct_data *tree, /* the tree to be scanned */ + int max_code) /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (//s, tree, max_code) + deflate_state *s, + ct_data *tree, /* the tree to be scanned */ + int max_code) /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(//s) + deflate_state *s) +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(//s, lcodes, dcodes, blcodes) + deflate_state *s, + int lcodes, + int dcodes, + int blcodes) /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(//s, buf, stored_len, eof) + deflate_state *s, + charf *buf, /* input block */ + ulg stored_len, /* length of input block */ + int eof) /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(//s) + deflate_state *s) +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(//s, buf, stored_len, eof) + deflate_state *s, + charf *buf, /* input block, or NULL if too old */ + ulg stored_len, /* length of input block */ + int eof) /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (//s, dist, lc) + deflate_state *s, + unsigned dist, /* distance of matched string */ + unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(//s, ltree, dtree) + deflate_state *s, + ct_data *ltree, /* literal tree */ + ct_data *dtree) /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(//s) + deflate_state *s) +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(//code, len) + unsigned code, /* the value to invert */ + int len) /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(//s) + deflate_state *s) +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(//s) + deflate_state *s) +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(//s, buf, len, header) + deflate_state *s, + charf *buf, /* the input data */ + unsigned len, /* its length */ + int header) /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/Libraries/zlib123/trees.h b/Libraries/zlib123/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/Libraries/zlib123/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/Libraries/zlib123/uncompr.cpp b/Libraries/zlib123/uncompr.cpp new file mode 100644 index 0000000..854a655 --- /dev/null +++ b/Libraries/zlib123/uncompr.cpp @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (//dest, destLen, source, sourceLen) + Bytef *dest, + uLongf *destLen, + const Bytef *source, + uLong sourceLen) +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/Libraries/zlib123/zconf.h b/Libraries/zlib123/zconf.h new file mode 100644 index 0000000..e3b0c96 --- /dev/null +++ b/Libraries/zlib123/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/Libraries/zlib123/zconf.in.h b/Libraries/zlib123/zconf.in.h new file mode 100644 index 0000000..e3b0c96 --- /dev/null +++ b/Libraries/zlib123/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/Libraries/zlib123/zlib.h b/Libraries/zlib123/zlib.h new file mode 100644 index 0000000..62d0e46 --- /dev/null +++ b/Libraries/zlib123/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/Libraries/zlib123/zutil.cpp b/Libraries/zlib123/zutil.cpp new file mode 100644 index 0000000..e092219 --- /dev/null +++ b/Libraries/zlib123/zutil.cpp @@ -0,0 +1,317 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (char *m) +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(//err) + int err) +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (//opaque, items, size) + voidpf opaque, + unsigned items, + unsigned size) +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (//opaque, ptr) + voidpf opaque, + voidpf ptr) +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/Libraries/zlib123/zutil.h b/Libraries/zlib123/zutil.h new file mode 100644 index 0000000..0ba6e02 --- /dev/null +++ b/Libraries/zlib123/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/README.images/screen1.png b/README.images/screen1.png new file mode 100644 index 0000000..1a9c84c Binary files /dev/null and b/README.images/screen1.png differ diff --git a/README.images/screen2.png b/README.images/screen2.png new file mode 100644 index 0000000..2dad4b9 Binary files /dev/null and b/README.images/screen2.png differ diff --git a/README.images/screen3.png b/README.images/screen3.png new file mode 100644 index 0000000..70c51ec Binary files /dev/null and b/README.images/screen3.png differ diff --git a/README.images/screen4.png b/README.images/screen4.png new file mode 100644 index 0000000..d994240 Binary files /dev/null and b/README.images/screen4.png differ diff --git a/README.images/screen5.png b/README.images/screen5.png new file mode 100644 index 0000000..2ed0838 Binary files /dev/null and b/README.images/screen5.png differ diff --git a/README.md b/README.md index 9db7113..c7a9616 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ -# activegs-ios \ No newline at end of file +#Activeg IOS + +Source code for the complete ActiveGS iOS application + +### Build +* Open the project in `ActiveGS_iOS/activegs.xcodeproj` +* In the settings/General tab, change the bundleId to your own +* Fix the team/provisionning profile +* Deploy on your iDevice + +That's it! + +![ScreenShot 1](https://github.com/ogoguel/activegs-ios/README.images/screen1.png) +![ScreenShot 2](https://github.com/ogoguel/activegs-ios/README.images/screen2.png) +![ScreenShot 3](https://github.com/ogoguel/activegs-ios/README.images/screen3.png) +![ScreenShot 4](https://github.com/ogoguel/activegs-ios/README.images/screen4.png) + +### Open/Known issues +* Orientation +* Hardware keyboard support +* iOS7 UI redesign +* Debug Marinetti TCP/IP +* IP Modem support +* Interface for multiple disks configuration +* MFI / Gamepad support + diff --git a/kegs/Console/config_kegs.cpp b/kegs/Console/config_kegs.cpp new file mode 100644 index 0000000..d06903a --- /dev/null +++ b/kegs/Console/config_kegs.cpp @@ -0,0 +1,2603 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Src/defc.h" +#include +#include "../Src/config.h" +#include "../Src/sim65816.h" +#include "../Src/paddles.h" +#include "../Src/video.h" +#include "../Src/adb.h" +#include "../Src/clock.h" +#include "../Src/sound.h" +#include "../Src/driver.h" + +// OG (Not supported Header) +#ifndef _MSC_VER + #include +#else +#ifndef UNDER_CE + #include + #include "../Win/dirent-win32.h" + #define mode_t int +#endif +#define snprintf _snprintf +#endif + +extern int Verbose; +//extern word32 g_vbl_count; +//extern Iwm iwm; + +extern int g_track_bytes_35[]; +extern int g_track_nibs_35[]; +extern int g_c031_disk35; + +//extern int g_cur_a2_stat; +extern byte *g_slow_memory_ptr; +extern byte *g_rom_fc_ff_ptr; +extern byte *g_rom_cards_ptr; +//extern double g_cur_dcycs; +//extern int g_sim65816.g_rom_version; +extern int g_fatal_log; + +//extern word32 g_adb_repeat_vbl; +/* +extern int g_limit_speed; +extern int g_force_depth; +extern int g_raw_serial; +extern int g_serial_out_masking; +extern int g_serial_modem[]; +extern word32 g_mem_size_base; +extern word32 g_mem_size_exp; +extern int g_video_line_update_interval; +extern int g_video_extra_check_inputs; +extern int g_user_halt_bad; +extern int g_joystick_scale_factor_x; +extern int g_joystick_scale_factor_y; +extern int g_joystick_trim_amount_x; +extern int g_joystick_trim_amount_y; +*/ + +extern int g_joystick_type; +extern int g_swap_paddles; +extern int g_invert_paddles; + + +extern int g_screen_index[]; +//extern word32 g_full_refresh_needed; +//extern word32 g_a2_screen_buffer_changed; +//extern int g_a2_new_all_stat[]; +//extern int g_new_a2_stat_cur_line; + +extern int g_key_down; +extern const char* g_kegs_version_str; + +// OG Moved to generic +//int g_config_control_panel = 0; +extern int g_config_control_panel ; +char g_config_kegs_name[1024]; +char g_cfg_cwd_str[CFG_PATH_MAX] = { 0 }; + +int g_config_kegs_auto_update = 1; + +// OG Moved to generic +extern int g_config_kegs_update_needed ; + +const char *g_config_kegs_name_list[] = { + "config.kegs", "kegs_conf", ".config.kegs", 0 +}; + +// OG Moved to generic +//extern int g_highest_smartport_unit ; +int g_reparse_delay = 0; + +// OG Moved to generic +extern int g_user_page2_shadow ; + +byte g_save_text_screen_bytes[0x800]; +// OG Moved to generic +extern int g_save_cur_a2_stat ; +char g_cfg_printf_buf[CFG_PRINTF_BUFSIZE]; +char g_config_kegs_buf[CONF_BUF_LEN]; + +// Moved to generic +extern word32 g_cfg_vbl_count ; + +int g_cfg_curs_x = 0; +int g_cfg_curs_y = 0; +int g_cfg_curs_inv = 0; +int g_cfg_curs_mousetext = 0; + +#define CFG_MAX_OPTS 16 +#define CFG_OPT_MAXSTR 100 + +int g_cfg_opts_vals[CFG_MAX_OPTS]; +char g_cfg_opts_strs[CFG_MAX_OPTS][CFG_OPT_MAXSTR]; +char g_cfg_opt_buf[CFG_OPT_MAXSTR]; + +const char *g_cfg_rom_path = "ROM"; +const char *g_cfg_file_def_name = "Undefined"; +char **g_cfg_file_strptr = 0; +int g_cfg_file_min_size = 1024; +int g_cfg_file_max_size = 2047*1024*1024; + +#define MAX_PARTITION_BLK_SIZE 65536 + +extern Cfg_menu g_cfg_main_menu[]; + +#define KNMP(a) &a, #a, 0 + +Cfg_menu g_cfg_disk_menu[] = { +{ "Disk Configuration", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU }, +{ "s5d1 = ", 0, 0, 0, CFGTYPE_DISK + 0x5000 }, +{ "s5d2 = ", 0, 0, 0, CFGTYPE_DISK + 0x5010 }, +{ "", 0, 0, 0, 0 }, +{ "s6d1 = ", 0, 0, 0, CFGTYPE_DISK + 0x6000 }, +{ "s6d2 = ", 0, 0, 0, CFGTYPE_DISK + 0x6010 }, +{ "", 0, 0, 0, 0 }, +{ "s7d1 = ", 0, 0, 0, CFGTYPE_DISK + 0x7000 }, +{ "s7d2 = ", 0, 0, 0, CFGTYPE_DISK + 0x7010 }, +{ "s7d3 = ", 0, 0, 0, CFGTYPE_DISK + 0x7020 }, +{ "s7d4 = ", 0, 0, 0, CFGTYPE_DISK + 0x7030 }, +{ "s7d5 = ", 0, 0, 0, CFGTYPE_DISK + 0x7040 }, +{ "s7d6 = ", 0, 0, 0, CFGTYPE_DISK + 0x7050 }, +{ "s7d7 = ", 0, 0, 0, CFGTYPE_DISK + 0x7060 }, +{ "s7d8 = ", 0, 0, 0, CFGTYPE_DISK + 0x7070 }, +{ "s7d9 = ", 0, 0, 0, CFGTYPE_DISK + 0x7080 }, +{ "s7d10 = ", 0, 0, 0, CFGTYPE_DISK + 0x7090 }, +{ "s7d11 = ", 0, 0, 0, CFGTYPE_DISK + 0x70a0 }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + +// OG Use define instead of const for joystick_types +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +Cfg_menu g_cfg_joystick_menu[] = { +{ "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU }, +{ "Joystick Emulation," TOSTRING(JOYSTICK_TYPE_KEYPAD)",Keypad Joystick," TOSTRING(JOYSTICK_TYPE_MOUSE)",Mouse Joystick," TOSTRING(JOYSTICK_TYPE_NATIVE_1)",Native Joystick 1," + TOSTRING(JOYSTICK_TYPE_NATIVE_2)",Native Joystick 2," TOSTRING(JOYSTICK_TYPE_NONE)",No Joystick", KNMP(g_joystick_type), CFGTYPE_INT }, +{ "Joystick Scale X,0x100,Standard,0x119,+10%,0x133,+20%," + "0x150,+30%,0xb0,-30%,0xcd,-20%,0xe7,-10%", + KNMP(g_paddles.g_joystick_scale_factor_x), CFGTYPE_INT }, +{ "Joystick Scale Y,0x100,Standard,0x119,+10%,0x133,+20%," + "0x150,+30%,0xb0,-30%,0xcd,-20%,0xe7,-10%", + KNMP(g_paddles.g_joystick_scale_factor_y), CFGTYPE_INT }, +{ "Joystick Trim X", KNMP(g_paddles.g_joystick_trim_amount_x), CFGTYPE_INT }, +{ "Joystick Trim Y", KNMP(g_paddles.g_joystick_trim_amount_y), CFGTYPE_INT }, +{ "Swap Joystick X and Y,0,Normal operation,1,Paddle 1 and Paddle 0 swapped", + KNMP(g_swap_paddles), CFGTYPE_INT }, +{ "Invert Joystick,0,Normal operation,1,Left becomes right and up becomes down", + KNMP(g_invert_paddles), CFGTYPE_INT }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + +Cfg_menu g_cfg_rom_menu[] = { +{ "ROM File Selection", g_cfg_rom_menu, 0, 0, CFGTYPE_MENU }, +{ "ROM File", KNMP(g_cfg_rom_path), CFGTYPE_FILE }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + +Cfg_menu g_cfg_serial_menu[] = { +{ "Serial Port Configuration", g_cfg_serial_menu, 0, 0, CFGTYPE_MENU }, +{ "Serial Ports,0,Only use sockets 6501-6502,1,Use real ports if avail", + KNMP(g_sim65816.g_raw_serial), CFGTYPE_INT }, +{ "Serial Output,0,Send full 8-bit data,1,Mask off high bit", + KNMP(g_sim65816.g_serial_out_masking), CFGTYPE_INT }, +{ "Modem on port 0 (slot 1),0,Simple socket emulation mode,1,Modem with " + "incoming and outgoing emulation", KNMP(g_sim65816.g_serial_modem[0]), + CFGTYPE_INT }, +{ "Modem on port 1 (slot 2),0,Simple socket emulation mode,1,Modem with " + "incoming and outgoing emulation", KNMP(g_sim65816.g_serial_modem[1]), + CFGTYPE_INT }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + +Cfg_menu g_cfg_main_menu[] = { +{ "KEGS Configuration", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ "Disk Configuration", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU }, +{ "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU }, +{ "ROM File Selection", g_cfg_rom_menu, 0, 0, CFGTYPE_MENU }, +{ "Serial Port Configuration", g_cfg_serial_menu, 0, 0, CFGTYPE_MENU }, +{ "Force X-windows display depth", KNMP(g_sim65816.g_force_depth), CFGTYPE_INT }, +{ "Auto-update config.kegs,0,Manual,1,Immediately", + KNMP(g_config_kegs_auto_update), CFGTYPE_INT }, +{ "Speed,0,Unlimited,1,1.0MHz,2,2.8MHz,3,8.0MHz (Zip)", + KNMP(g_sim65816.g_limit_speed), CFGTYPE_INT }, +{ "Expansion Mem Size,0,0MB,0x100000,1MB,0x200000,2MB,0x300000,3MB," + "0x400000,4MB,0x600000,6MB,0x800000,8MB,0xa00000,10MB,0xc00000,12MB," + "0xe00000,14MB", KNMP(g_sim65816.g_mem_size_exp), CFGTYPE_INT }, +{ "3200 Color Enable,0,Auto (Full if fast enough),1,Full (Update every line)," + "8,Off (Update video every 8 lines)", + KNMP(g_sim65816.g_video_line_update_interval), CFGTYPE_INT }, +{ "Keyboard and mouse poll rate,0,60 times per second,1,240 times per second", + KNMP(g_video.g_video_extra_check_inputs), CFGTYPE_INT }, +{ "Code Red Halts,0,Do not stop on bad accesses,1,Enter debugger on bad " + "accesses", KNMP(r_sim65816.g_user_halt_bad), CFGTYPE_INT }, +{ "Enable Text Page 2 Shadow,0,Disabled on ROM 01 (matches real hardware)," + "1,Enabled on ROM 01 and 03", + KNMP(g_user_page2_shadow), CFGTYPE_INT }, +{ "Dump text screen to file", (void *)cfg_text_screen_dump, 0, 0, CFGTYPE_FUNC}, +{ "", 0, 0, 0, 0 }, +{ "Save changes to config.kegs", (void *)config_write_config_kegs_file, 0, 0, + CFGTYPE_FUNC }, +{ "", 0, 0, 0, 0 }, +{ "Exit Config (or press F4)", (void *)cfg_exit, 0, 0, CFGTYPE_FUNC }, +{ 0, 0, 0, 0, 0 }, +}; + + +#define CFG_MAX_DEFVALS 128 +Cfg_defval g_cfg_defvals[CFG_MAX_DEFVALS]; +int g_cfg_defval_index = 0; + +int g_cfg_slotdrive = -1; +int g_cfg_select_partition = -1; +char g_cfg_tmp_path[CFG_PATH_MAX]; +char g_cfg_file_path[CFG_PATH_MAX]; +char g_cfg_file_cachedpath[CFG_PATH_MAX]; +char g_cfg_file_cachedreal[CFG_PATH_MAX]; +char g_cfg_file_curpath[CFG_PATH_MAX]; +char g_cfg_file_shortened[CFG_PATH_MAX]; +char g_cfg_file_match[CFG_PATH_MAX]; + +Cfg_listhdr g_cfg_dirlist = { 0 }; +Cfg_listhdr g_cfg_partitionlist = { 0 }; + +int g_cfg_file_pathfield = 0; + +const char *g_kegs_rom_names[] = { "ROM", "ROM", "ROM.01", "ROM.03", 0 }; + /* First entry is special--it will be overwritten by g_cfg_rom_path */ + +const char *g_kegs_c1rom_names[] = { 0 }; +const char *g_kegs_c2rom_names[] = { 0 }; +const char *g_kegs_c3rom_names[] = { 0 }; +const char *g_kegs_c4rom_names[] = { 0 }; +const char *g_kegs_c5rom_names[] = { 0 }; +const char *g_kegs_c6rom_names[] = { "c600.rom", "controller.rom", "disk.rom", + "DISK.ROM", "diskII.prom", 0 }; +const char *g_kegs_c7rom_names[] = { 0 }; + +const char **g_kegs_rom_card_list[8] = { + 0, g_kegs_c1rom_names, + g_kegs_c2rom_names, g_kegs_c3rom_names, + g_kegs_c4rom_names, g_kegs_c5rom_names, + g_kegs_c6rom_names, g_kegs_c7rom_names }; + + +void +config_init_menus(Cfg_menu *menuptr) +{ + void *voidptr; + const char *name_str; + Cfg_defval *defptr; + char **str_ptr; + char *str; + int type; + int pos; + int val; + + if(menuptr[0].defptr != 0) { + return; + } + menuptr[0].defptr = (void *)1; + pos = 0; + while(pos < 100) { + type = menuptr->cfgtype; + voidptr = menuptr->ptr; + name_str = menuptr->name_str; + if(menuptr->str == 0) { + break; + } + if(name_str != 0) { + defptr = &(g_cfg_defvals[g_cfg_defval_index++]); + if(g_cfg_defval_index >= CFG_MAX_DEFVALS) { + fatal_printf("CFG_MAX_DEFVAL overflow\n"); + my_exit(5); + } + defptr->menuptr = menuptr; + defptr->intval = 0; + defptr->strval = 0; + switch(type) { + case CFGTYPE_INT: + val = *((int *)voidptr); + defptr->intval = val; + menuptr->defptr = &(defptr->intval); + break; + case CFGTYPE_FILE: + str_ptr = (char **)menuptr->ptr; + str = *str_ptr; + // We need to malloc this string since all + // string values must be dynamically alloced + defptr->strval = str; // this can have a copy + *str_ptr = kegs_malloc_str(str); + menuptr->defptr = &(defptr->strval); + break; + default: + fatal_printf("name_str is %p = %s, but type: " + "%d\n", name_str, name_str, type); + my_exit(5); + } + } + if(type == CFGTYPE_MENU) { + config_init_menus((Cfg_menu *)voidptr); + } + pos++; + menuptr++; + } +} + +void +config_init() +{ + int can_create; + + config_init_menus(g_cfg_main_menu); + + // Find the config.kegs file + g_config_kegs_name[0] = 0; + can_create = 1; + setup_kegs_file(&g_config_kegs_name[0], sizeof(g_config_kegs_name), 0, + can_create, &g_config_kegs_name_list[0]); + + config_parse_config_kegs_file(); +} + +void +cfg_exit() +{ + /* printf("In cfg exit\n"); */ + if(g_sim65816.g_rom_version >= 1) { + g_config_control_panel = 0; + } +} + +void +cfg_toggle_config_panel() +{ + g_config_control_panel = !g_config_control_panel; + if(g_sim65816.g_rom_version < 0) { + g_config_control_panel = 1; /* Stay in config mode */ + } +} + +void +cfg_text_screen_dump() +{ + char buf[85]; + const char *filename; + FILE *ofile; + int offset; + int c; + int pos; + int i, j; + + filename = "kegs.screen.dump"; + printf("Writing text screen to the file %s\n", filename); + ofile = fopen(filename, "w"); + if(ofile == 0) { + fatal_printf("Could not write to file %s, (%d)\n", filename, + errno); + return; + } + + for(i = 0; i < 24; i++) { + pos = 0; + for(j = 0; j < 40; j++) { + offset = g_screen_index[i] + j; + if(g_save_cur_a2_stat & ALL_STAT_VID80) { + c = g_save_text_screen_bytes[0x400+offset]; + c = c & 0x7f; + if(c < 0x20) { + c += 0x40; + } + buf[pos++] = c; + } + c = g_save_text_screen_bytes[offset] & 0x7f; + if(c < 0x20) { + c += 0x40; + } + buf[pos++] = c; + } + while((pos > 0) && (buf[pos-1] == ' ')) { + /* try to strip out trailing spaces */ + pos--; + } + buf[pos++] = '\n'; + buf[pos++] = 0; + fputs(buf, ofile); + } + fclose(ofile); +} + +void +config_vbl_update(int doit_3_persec) +{ + if(doit_3_persec) { + if(g_config_kegs_auto_update && g_config_kegs_update_needed) { + config_write_config_kegs_file(); + } + } + return; +} + +void +config_parse_option(char *buf, int pos, int len, int line) +{ + Cfg_menu *menuptr; + Cfg_defval *defptr; + char *nameptr; + char **strptr; + int *iptr; + int num_equals; + int type; + int val; + int c; + int i; + +// warning: modifies buf (turns spaces to nulls) +// parse buf from pos into option, "=" and then "rest" + if(pos >= len) { + /* blank line */ + return; + } + + if(strncmp(&buf[pos], "bram", 4) == 0) { + config_parse_bram(buf, pos+4, len); + return; + } + + // find "name" as first contiguous string + printf("...parse_option: line %d, %p,%p = %s (%s) len:%d\n", line, + &buf[pos], buf, &buf[pos], buf, len); + + nameptr = &buf[pos]; + while(pos < len) { + c = buf[pos]; + if(c == 0 || c == ' ' || c == '\t' || c == '\n') { + break; + } + pos++; + } + buf[pos] = 0; + pos++; + + // Eat up all whitespace and '=' + num_equals = 0; + while(pos < len) { + c = buf[pos]; + if((c == '=') && num_equals == 0) { + pos++; + num_equals++; + } else if(c == ' ' || c == '\t') { + pos++; + } else { + break; + } + } + + /* Look up nameptr to find type */ + type = -1; + defptr = 0; + menuptr = 0; + for(i = 0; i < g_cfg_defval_index; i++) { + defptr = &(g_cfg_defvals[i]); + menuptr = defptr->menuptr; + if(strcmp(menuptr->name_str, nameptr) == 0) { + type = menuptr->cfgtype; + break; + } + } + + switch(type) { + case CFGTYPE_INT: + /* use strtol */ + val = (int)strtol(&buf[pos], 0, 0); + iptr = (int *)menuptr->ptr; + *iptr = val; + break; + case CFGTYPE_FILE: + strptr = (char **)menuptr->ptr; + if(strptr && *strptr) { + free(*strptr); + } + *strptr = kegs_malloc_str(&buf[pos]); + break; + default: + printf("Config file variable %s is unknown type: %d\n", + nameptr, type); + } + +} + +void +config_parse_bram(char *buf, int pos, int len) +{ + int bram_num; + int offset; + int val; + + if((len < (pos+5)) || (buf[pos+1] != '[') || (buf[pos+4] != ']')) { + fatal_printf("While reading config.kegs, found malformed bram " + "statement: %s\n", buf); + return; + } + bram_num = buf[pos] - '0'; + if(bram_num != 1 && bram_num != 3) { + fatal_printf("While reading config.kegs, found bad bram " + "num: %s\n", buf); + return; + } + + bram_num = bram_num >> 1; // turn 3->1 and 1->0 + + offset = strtoul(&(buf[pos+2]), 0, 16); + pos += 5; + while(pos < len) { + while(buf[pos] == ' ' || buf[pos] == '\t' || buf[pos] == 0x0a || + buf[pos] == 0x0d || buf[pos] == '=') { + pos++; + } + val = strtoul(&buf[pos], 0, 16); + clk_bram_set(bram_num, offset, val); + offset++; + pos += 2; + } +} + + +void +x_config_load_roms() +{ + + + struct stat stat_buf; + + int len; + int fd; + int ret; + + + g_sim65816.g_rom_version = -1; + + /* set first entry of g_kegs_rom_names[] to g_cfg_rom_path so that */ + /* it becomes the first place searched. */ + g_kegs_rom_names[0] = g_cfg_rom_path; + setup_kegs_file(&g_cfg_tmp_path[0], CFG_PATH_MAX, -1, 0, + &g_kegs_rom_names[0]); + + if(g_cfg_tmp_path[0] == 0) { + // Just get out, let config interface select ROM + g_config_control_panel = 1; + return; + } + fd = open(&g_cfg_tmp_path[0], O_RDONLY | O_BINARY); + if(fd < 0) { + fatal_printf("Open ROM file %s failed:%d, errno:%d\n", + &g_cfg_tmp_path[0], fd, errno); + g_config_control_panel = 1; + return; + } + + ret = fstat(fd, &stat_buf); + if(ret != 0) { + fatal_printf("fstat returned %d on fd %d, errno: %d\n", + ret, fd, errno); + g_config_control_panel = 1; + return; + } + + len = stat_buf.st_size; + if(len == 128*1024) { + g_sim65816.g_rom_version = 1; + g_sim65816.g_mem_size_base = 256*1024; + memset(&g_rom_fc_ff_ptr[0], 0, 2*65536); + /* Clear banks fc and fd to 0 */ + ret = read(fd, &g_rom_fc_ff_ptr[2*65536], len); + } else if(len == 256*1024) { + g_sim65816.g_rom_version = 3; + g_sim65816.g_mem_size_base = 1024*1024; + ret = read(fd, &g_rom_fc_ff_ptr[0], len); + } else { + fatal_printf("The ROM size should be 128K or 256K, this file " + "is %d bytes\n", len); + g_config_control_panel = 1; + return; + } + + printf("Read: %d bytes of ROM\n", ret); + if(ret != len) { + fatal_printf("errno: %d\n", errno); + g_config_control_panel = 1; + return; + } + close(fd); + +} + +void x_config_load_additional_roms() +{ + int i; + const char **names_ptr; + int fd,len; + int ret; + + for(i = 1; i < 8; i++) { + names_ptr = g_kegs_rom_card_list[i]; + if(names_ptr == 0) { + continue; + } + if(*names_ptr == 0) { + continue; + } + + setup_kegs_file(&g_cfg_tmp_path[0], CFG_PATH_MAX, 1, 0, + names_ptr); + + if(g_cfg_tmp_path[0] != 0) { + fd = open(&(g_cfg_tmp_path[0]), O_RDONLY | O_BINARY); + if(fd < 0) { + fatal_printf("Open card ROM file %s failed: %d " + "err:%d\n", &g_cfg_tmp_path[0], fd, + errno); + continue; + } + + len = 256; + ret = read(fd, &g_rom_cards_ptr[i*0x100], len); + + if(ret != len) { + fatal_printf("While reading card ROM %s, file " + "is too short. (%d) Expected %d bytes, " + "read %d bytes\n", errno, len, ret); + continue; + } + close(fd); + } + } +} + + +void +config_parse_config_kegs_file() +{ + FILE *fconf; + char *buf; + char *ptr; + char *name_ptr; + char *partition_name; + int part_num; + int ejected; + int line; + int pos; + int slot; + int drive; + int size; + int len; + int ret; + int i; + + printf("Parsing config.kegs file\n"); + + clk_bram_zero(); + + g_iwm.g_highest_smartport_unit = -1; + + cfg_get_base_path(&g_cfg_cwd_str[0], g_config_kegs_name, 0); + if(g_cfg_cwd_str[0] != 0) { + ret = chdir(&g_cfg_cwd_str[0]); + if(ret != 0) { + printf("chdir to %s, errno:%d\n", g_cfg_cwd_str, errno); + } + } + + /* In any case, copy the directory path to g_cfg_cwd_str */ + (void)getcwd(&g_cfg_cwd_str[0], CFG_PATH_MAX); + + fconf = fopen(g_config_kegs_name, "r"); + if(fconf == 0) { + fatal_printf("cannot open config.kegs at %s! Stopping!\n", + g_config_kegs_name); + my_exit(3); + } + + line = 0; + while(1) { + buf = &g_config_kegs_buf[0]; + ptr = fgets(buf, CONF_BUF_LEN, fconf); + if(ptr == 0) { + iwm_printf("Done reading disk_conf\n"); + break; + } + + line++; + /* strip off newline(s) */ + len = strlen(buf); + for(i = len - 1; i >= 0; i--) { + if((buf[i] != 0x0d) && (buf[i] != 0x0a)) { + break; + } + len = i; + buf[i] = 0; + } + + iwm_printf("disk_conf[%d]: %s\n", line, buf); + if(len > 0 && buf[0] == '#') { + iwm_printf("Skipping comment\n"); + continue; + } + + /* determine what this is */ + pos = 0; + + while(pos < len && (buf[pos] == ' ' || buf[pos] == '\t') ) { + pos++; + } + if((pos + 4) > len || buf[pos] != 's' || buf[pos+2] != 'd' || + buf[pos+1] > '9' || buf[pos+1] < '0') { + config_parse_option(buf, pos, len, line); + continue; + } + + slot = buf[pos+1] - '0'; + drive = buf[pos+3] - '0'; + + /* skip over slot, drive */ + pos += 4; + if(buf[pos] >= '0' && buf[pos] <= '9') { + drive = drive * 10 + buf[pos] - '0'; + pos++; + } + + /* make s6d1 mean index 0 */ + drive--; + + while(pos < len && (buf[pos] == ' ' || buf[pos] == '\t' || + buf[pos] == '=') ) { + pos++; + } + + ejected = 0; + if(buf[pos] == '#') { + /* disk is ejected, but read all the info anyway */ + ejected = 1; + pos++; + } + + size = 0; + if(buf[pos] == ',') { + /* read optional size parameter */ + pos++; + while(pos < len && buf[pos] >= '0' && buf[pos] <= '9'){ + size = size * 10 + buf[pos] - '0'; + pos++; + } + size = size * 1024; + if(buf[pos] == ',') { + pos++; /* eat trailing ',' */ + } + } + + /* see if it has a partition name */ + partition_name = 0; + part_num = -1; + if(buf[pos] == ':') { + pos++; + /* yup, it's got a partition name! */ + partition_name = &buf[pos]; + while((pos < len) && (buf[pos] != ':')) { + pos++; + } + buf[pos] = 0; /* null terminate partition name */ + pos++; + } + if(buf[pos] == ';') { + pos++; + /* it's got a partition number */ + part_num = 0; + while((pos < len) && (buf[pos] != ':')) { + part_num = (10*part_num) + buf[pos] - '0'; + pos++; + } + pos++; + } + + /* Get filename */ + name_ptr = &(buf[pos]); + if(name_ptr[0] == 0) { + continue; + } + + insert_disk(slot, drive, name_ptr, ejected, size, + partition_name, part_num); + + } + + ret = fclose(fconf); + if(ret != 0) { + fatal_printf("Closing config.kegs ret: %d, errno: %d\n", ret, + errno); + my_exit(4); + } + + iwm_printf("Done parsing disk_conf file\n"); +} + + + +void +config_generate_config_kegs_name(char *outstr, int maxlen, Disk *dsk, + int with_extras) +{ + char *str; + + str = outstr; + + if(with_extras && dsk->fd < 0) { + snprintf(str, maxlen - (str - outstr), "#"); + str = &outstr[strlen(outstr)]; + } + if(with_extras && dsk->force_size > 0) { + snprintf(str, maxlen - (str - outstr), ",%d,", dsk->force_size); + str = &outstr[strlen(outstr)]; + } + if(with_extras && dsk->partition_name != 0) { + snprintf(str, maxlen - (str - outstr), ":%s:", + dsk->partition_name); + str = &outstr[strlen(outstr)]; + } else if(with_extras && dsk->partition_num >= 0) { + snprintf(str, maxlen - (str - outstr), ";%d:", + dsk->partition_num); + str = &outstr[strlen(outstr)]; + } + snprintf(str, maxlen - (str - outstr), "%s", dsk->name_ptr); + + +} + +void +config_write_config_kegs_file() +{ + FILE *fconf; + Disk *dsk; + Cfg_defval *defptr; + Cfg_menu *menuptr; + char *curstr, *defstr; + int defval, curval; + int type; + int slot, drive; + int i; + + printf("Writing config.kegs file to %s\n", g_config_kegs_name); + + fconf = fopen(g_config_kegs_name, "w+"); + if(fconf == 0) { + halt_printf("cannot open %s! Stopping!\n"); + return; + } + + fprintf(fconf, "# KEGS configuration file version %s\n", + g_kegs_version_str); + + for(i = 0; i < MAX_C7_DISKS + 4; i++) { + slot = 7; + drive = i - 4; + if(i < 4) { + slot = (i >> 1) + 5; + drive = i & 1; + } + if(drive == 0) { + fprintf(fconf, "\n"); /* an extra blank line */ + } + + dsk = cfg_get_dsk_from_slot_drive(slot, drive); + if(dsk->name_ptr == 0 && (i > 4)) { + /* No disk, not even ejected--just skip */ + continue; + } + fprintf(fconf, "s%dd%d = ", slot, drive + 1); + if(dsk->name_ptr == 0) { + fprintf(fconf, "\n"); + continue; + } + config_generate_config_kegs_name(&g_cfg_tmp_path[0], + CFG_PATH_MAX, dsk, 1); + fprintf(fconf, "%s\n", &g_cfg_tmp_path[0]); + } + + fprintf(fconf, "\n"); + + /* See if any variables are different than their default */ + for(i = 0; i < g_cfg_defval_index; i++) { + defptr = &(g_cfg_defvals[i]); + menuptr = defptr->menuptr; + defval = defptr->intval; + type = menuptr->cfgtype; + if(type == CFGTYPE_INT) { + curval = *((int *)menuptr->ptr); + if(curval != defval) { + fprintf(fconf, "%s = %d\n", menuptr->name_str, + curval); + } + } + if(type == CFGTYPE_FILE) { + curstr = *((char **)menuptr->ptr); + defstr = *((char **)menuptr->defptr); + if(strcmp(curstr, defstr) != 0) { + fprintf(fconf, "%s = %s\n", menuptr->name_str, + curstr); + } + } + } + + fprintf(fconf, "\n"); + + /* write bram state */ + clk_write_bram(fconf); + + fclose(fconf); + + g_config_kegs_update_needed = 0; +} + + +int +cfg_partition_read_block(int fd, void *buf, int blk, int blk_size) +{ + int ret; + + ret = lseek(fd, blk * blk_size, SEEK_SET); + if(ret != blk * blk_size) { + printf("lseek: %08x, wanted: %08x, errno: %d\n", ret, + blk * blk_size, errno); + return 0; + } + + ret = read(fd, (char *)buf, blk_size); + if(ret != blk_size) { + printf("ret: %08x, wanted %08x, errno: %d\n", ret, blk_size, + errno); + return 0; + } + return ret; +} + +int +cfg_partition_find_by_name_or_num(int fd, const char *partnamestr, int part_num, + Disk *dsk) +{ + Cfg_dirent *direntptr; + int match; + int num_parts; + int i; + + num_parts = cfg_partition_make_list(fd); + + if(num_parts <= 0) { + return -1; + } + + for(i = 0; i < g_cfg_partitionlist.last; i++) { + direntptr = &(g_cfg_partitionlist.direntptr[i]); + match = 0; + if((strncmp(partnamestr, direntptr->name, 32) == 0) && + (part_num < 0)) { + //printf("partition, match1, name:%s %s, part_num:%d\n", + // partnamestr, direntptr->name, part_num); + + match = 1; + } + if((partnamestr == 0) && (direntptr->part_num == part_num)) { + //printf("partition, match2, n:%s, part_num:%d == %d\n", + // direntptr->name, direntptr->part_num, part_num); + match = 1; + } + if(match) { + dsk->image_start = direntptr->image_start; + dsk->image_size = direntptr->size; + //printf("match with image_start: %08x, image_size: " + // "%08x\n", dsk->image_start, dsk->image_size); + + return i; + } + } + + return -1; +} + +int +cfg_partition_make_list(int fd) +{ + Driver_desc *driver_desc_ptr; + Part_map *part_map_ptr; + word32 *blk_bufptr; + word32 start; + word32 len; + word32 data_off; + word32 data_len; + word32 sig; + int size; + int image_start, image_size; + int is_dir; + int block_size; + int map_blks; + int cur_blk; + + block_size = 512; + + cfg_free_alldirents(&g_cfg_partitionlist); + + blk_bufptr = (word32 *)malloc(MAX_PARTITION_BLK_SIZE); + + cfg_partition_read_block(fd, blk_bufptr, 0, block_size); + + driver_desc_ptr = (Driver_desc *)blk_bufptr; + sig = GET_BE_WORD16(driver_desc_ptr->sig); + block_size = GET_BE_WORD16(driver_desc_ptr->blk_size); + if(block_size == 0) { + block_size = 512; + } + if(sig != 0x4552 || block_size < 0x200 || + (block_size > MAX_PARTITION_BLK_SIZE)) { + cfg_printf("Partition error: No driver descriptor map found\n"); + free(blk_bufptr); + return 0; + } + + map_blks = 1; + cur_blk = 0; + size = cfg_get_fd_size(fd); + cfg_file_add_dirent(&g_cfg_partitionlist, "None - Whole image", + is_dir=0, size, 0, -1); + + while(cur_blk < map_blks) { + cur_blk++; + cfg_partition_read_block(fd, blk_bufptr, cur_blk, block_size); + part_map_ptr = (Part_map *)blk_bufptr; + sig = GET_BE_WORD16(part_map_ptr->sig); + if(cur_blk <= 1) { + map_blks = MIN(20, + GET_BE_WORD32(part_map_ptr->map_blk_cnt)); + } + if(sig != 0x504d) { + printf("Partition entry %d bad signature:%04x\n", + cur_blk, sig); + free(blk_bufptr); + return g_cfg_partitionlist.last; + } + + /* found it, check for consistency */ + start = GET_BE_WORD32(part_map_ptr->phys_part_start); + len = GET_BE_WORD32(part_map_ptr->part_blk_cnt); + data_off = GET_BE_WORD32(part_map_ptr->data_start); + data_len = GET_BE_WORD32(part_map_ptr->data_cnt); + if(data_off + data_len > len) { + printf("Poorly formed entry\n"); + continue; + } + + if(data_len < 10 || start < 1) { + printf("Poorly formed entry %d, datalen:%d, " + "start:%08x\n", cur_blk, data_len, start); + continue; + } + + image_size = data_len * block_size; + image_start = (start + data_off) * block_size; + is_dir = 2*(image_size < 800*1024); +#if 0 + printf(" partition add entry %d = %s %d %08x %08x\n", + cur_blk, part_map_ptr->part_name, is_dir, + image_size, image_start); +#endif + + cfg_file_add_dirent(&g_cfg_partitionlist, + part_map_ptr->part_name, is_dir, image_size, + image_start, cur_blk); + } + + free(blk_bufptr); + return g_cfg_partitionlist.last; +} + +int +cfg_maybe_insert_disk(int slot, int drive, const char *namestr) +{ + int num_parts; + int fd; + + fd = open(namestr, O_RDONLY | O_BINARY, 0x1b6); + if(fd < 0) { + fatal_printf("Cannot open disk image: %s\n", namestr); + return 0; + } + + num_parts = cfg_partition_make_list(fd); + close(fd); + + if(num_parts > 0) { + printf("Choose a partition\n"); + g_cfg_select_partition = 1; + } else { + insert_disk(slot, drive, namestr, 0, 0, 0, -1); + return 1; + } + return 0; +} + +int +cfg_stat(char *path, struct stat *sb) +{ + int removed_slash; + int len; + int ret; + + removed_slash = 0; + len = 0; + +#ifdef _WIN32 + /* Windows doesn't like to stat paths ending in a /, so remove it */ + len = strlen(path); + if((len > 1) && (path[len - 1] == '/') ) { + path[len - 1] = 0; /* remove the slash */ + removed_slash = 1; + } +#endif + + ret = stat(path, sb); + +#ifdef _WIN32 + /* put the slash back */ + if(removed_slash) { + path[len - 1] = '/'; + } +#endif + + return ret; +} + +void +cfg_htab_vtab(int x, int y) +{ + if(x > 79) { + x = 0; + } + if(y > 23) { + y = 0; + } + g_cfg_curs_x = x; + g_cfg_curs_y = y; + g_cfg_curs_inv = 0; + g_cfg_curs_mousetext = 0; +} + +void +cfg_home() +{ + int i; + + cfg_htab_vtab(0, 0); + for(i = 0; i < 24; i++) { + cfg_cleol(); + } +} + +void +cfg_cleol() +{ + g_cfg_curs_inv = 0; + g_cfg_curs_mousetext = 0; + cfg_putchar(' '); + while(g_cfg_curs_x != 0) { + cfg_putchar(' '); + } +} + +void +cfg_putchar(int c) +{ + int offset; + int x, y; + + if(c == '\n') { + cfg_cleol(); + return; + } + if(c == '\b') { + g_cfg_curs_inv = !g_cfg_curs_inv; + return; + } + if(c == '\t') { + g_cfg_curs_mousetext = !g_cfg_curs_mousetext; + return; + } + + if (!r_sim65816.is_emulator_initialized()) // OG + return ; + + y = g_cfg_curs_y; + x = g_cfg_curs_x; + + offset = g_screen_index[g_cfg_curs_y]; + if((x & 1) == 0) { + offset += 0x10000; + } + if(g_cfg_curs_inv) { + if(c >= 0x40 && c < 0x60) { + c = c & 0x1f; + } + } else { + c = c | 0x80; + } + if(g_cfg_curs_mousetext) { + c = (c & 0x1f) | 0x40; + } + set_memory_c(0xe00400 + offset + (x >> 1), c, 0); + x++; + if(x >= 80) { + x = 0; + y++; + if(y >= 24) { + y = 0; + } + } + g_cfg_curs_y = y; + g_cfg_curs_x = x; +} + +void +cfg_printf(const char *fmt, ...) +{ + va_list ap; + int c; + int i; + + va_start(ap, fmt); + (void)vsnprintf(g_cfg_printf_buf, CFG_PRINTF_BUFSIZE, fmt, ap); + va_end(ap); + + for(i = 0; i < CFG_PRINTF_BUFSIZE; i++) { + c = g_cfg_printf_buf[i]; + if(c == 0) { + return; + } + cfg_putchar(c); + } +} + +void +cfg_print_num(int num, int max_len) +{ + char buf[64]; + char buf2[64]; + int len; + int cnt; + int c; + int i, j; + + /* Prints right-adjusted "num" in field "max_len" wide */ + snprintf(&buf[0], 64, "%d", num); + len = strlen(buf); + for(i = 0; i < 64; i++) { + buf2[i] = ' '; + } + j = max_len + 1; + buf2[j] = 0; + j--; + cnt = 0; + for(i = len - 1; (i >= 0) && (j >= 1); i--) { + c = buf[i]; + if(c >= '0' && c <= '9') { + if(cnt >= 3) { + buf2[j--] = ','; + cnt = 0; + } + cnt++; + } + buf2[j--] = c; + } + cfg_printf(&buf2[1]); +} + +void +cfg_get_disk_name(char *outstr, int maxlen, int type_ext, int with_extras) +{ + Disk *dsk; + int slot, drive; + + slot = type_ext >> 8; + drive = type_ext & 0xff; + dsk = cfg_get_dsk_from_slot_drive(slot, drive); + + outstr[0] = 0; + if(dsk->name_ptr == 0) { + return; + } + + config_generate_config_kegs_name(outstr, maxlen, dsk, with_extras); +} + +void +cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) +{ + char valbuf[CFG_OPT_MAXSTR]; + char **str_ptr; + const char *menustr; + char *curstr, *defstr; + char *str; + char *outstr; + int *iptr; + int val; + int num_opts; + int opt_num; + int bufpos, outpos; + int curval, defval; + int type; + int type_ext; + int opt_get_str; + int separator; + int len; + int c; + int i; + + g_cfg_opt_buf[0] = 0; + + num_opts = 0; + opt_get_str = 0; + separator = ','; + + menuptr += menu_pos; /* move forward to entry menu_pos */ + + menustr = menuptr->str; + type = menuptr->cfgtype; + type_ext = (type >> 4); + type = type & 0xf; + len = strlen(menustr) + 1; + + bufpos = 0; + outstr = &(g_cfg_opt_buf[0]); + + outstr[bufpos++] = ' '; + outstr[bufpos++] = ' '; + outstr[bufpos++] = '\t'; + outstr[bufpos++] = '\t'; + outstr[bufpos++] = ' '; + outstr[bufpos++] = ' '; + + if(menu_pos == highlight_pos) { + outstr[bufpos++] = '\b'; + } + + opt_get_str = 2; + i = -1; + outpos = bufpos; +#if 0 + printf("cfg menu_pos: %d str len: %d\n", menu_pos, len); +#endif + while(++i < len) { + c = menustr[i]; + if(c == separator) { + if(i == 0) { + continue; + } + c = 0; + } + outstr[outpos++] = c; + outstr[outpos] = 0; + if(outpos >= CFG_OPT_MAXSTR) { + fprintf(stderr, "CFG_OPT_MAXSTR exceeded\n"); + my_exit(1); + } + if(c == 0) { + if(opt_get_str == 2) { + outstr = &(valbuf[0]); + bufpos = outpos - 1; + opt_get_str = 0; + } else if(opt_get_str) { +#if 0 + if(menu_pos == highlight_pos) { + printf("menu_pos %d opt %d = %s=%d\n", + menu_pos, num_opts, + g_cfg_opts_strs[num_opts], + g_cfg_opts_vals[num_opts]); + } +#endif + num_opts++; + outstr = &(valbuf[0]); + opt_get_str = 0; + if(num_opts >= CFG_MAX_OPTS) { + fprintf(stderr, "CFG_MAX_OPTS oflow\n"); + my_exit(1); + } + } else { + val = strtoul(valbuf, 0, 0); + g_cfg_opts_vals[num_opts] = val; + outstr = &(g_cfg_opts_strs[num_opts][0]); + opt_get_str = 1; + } + outpos = 0; + outstr[0] = 0; + } + } + + if(menu_pos == highlight_pos) { + g_cfg_opt_buf[bufpos++] = '\b'; + } + + g_cfg_opt_buf[bufpos] = 0; + + // Figure out if we should get a checkmark + curval = -1; + defval = -1; + curstr = 0; + if(type == CFGTYPE_INT) { + iptr = (int*)menuptr->ptr; // OG Added cast + curval = *iptr; + iptr = (int*)menuptr->defptr; // OG Added cast + defval = *iptr; + if(curval == defval) { + g_cfg_opt_buf[3] = 'D'; /* checkmark */ + g_cfg_opt_buf[4] = '\t'; + } + } + if(type == CFGTYPE_FILE) { + str_ptr = (char **)menuptr->ptr; + curstr = *str_ptr; + str_ptr = (char **)menuptr->defptr; + defstr = *str_ptr; + if(strcmp(curstr,defstr) == 0) { + g_cfg_opt_buf[3] = 'D'; /* checkmark */ + g_cfg_opt_buf[4] = '\t'; + } + } + + // If it's a menu, give it a special menu indicator + if(type == CFGTYPE_MENU) { + g_cfg_opt_buf[1] = '\t'; + g_cfg_opt_buf[2] = 'M'; /* return-like symbol */ + g_cfg_opt_buf[3] = '\t'; + g_cfg_opt_buf[4] = ' '; + } + + // Decide what to display on the "right" side + str = 0; + opt_num = -1; + if(type == CFGTYPE_INT || type == CFGTYPE_FILE) { + g_cfg_opt_buf[bufpos++] = ' '; + g_cfg_opt_buf[bufpos++] = '='; + g_cfg_opt_buf[bufpos++] = ' '; + g_cfg_opt_buf[bufpos] = 0; + for(i = 0; i < num_opts; i++) { + if(curval == g_cfg_opts_vals[i]) { + opt_num = i; + break; + } + } + } + + if(change != 0) { + if(type == CFGTYPE_INT) { + if(num_opts > 0) { + opt_num += change; + if(opt_num >= num_opts) { + opt_num = 0; + } + if(opt_num < 0) { + opt_num = num_opts - 1; + } + curval = g_cfg_opts_vals[opt_num]; + } else { + curval += change; + /* HACK: min_val, max_val testing here */ + } + iptr = (int *)menuptr->ptr; + *iptr = curval; + } + g_config_kegs_update_needed = 1; + } + +#if 0 + if(menu_pos == highlight_pos) { + printf("menu_pos %d opt_num %d\n", menu_pos, opt_num); + } +#endif + + if(opt_num >= 0) { + str = &(g_cfg_opts_strs[opt_num][0]); + } else { + if(type == CFGTYPE_INT) { + str = &(g_cfg_opts_strs[0][0]); + snprintf(str, CFG_OPT_MAXSTR, "%d", curval); // OG + } else if (type == CFGTYPE_DISK) { + str = &(g_cfg_opts_strs[0][0]), + cfg_get_disk_name(str, CFG_OPT_MAXSTR, type_ext, 1); + str = cfg_shorten_filename(str, 68); + } else if (type == CFGTYPE_FILE) { + str = &(g_cfg_opts_strs[0][0]); + snprintf(str, CFG_OPT_MAXSTR, "%s", curstr); // OG + str = cfg_shorten_filename(str, 68); + } else { + str=""; + } + } + +#if 0 + if(menu_pos == highlight_pos) { + printf("menu_pos %d buf_pos %d, str is %s, %02x, %02x, " + "%02x %02x\n", + menu_pos, bufpos, str, g_cfg_opt_buf[bufpos-1], + g_cfg_opt_buf[bufpos-2], + g_cfg_opt_buf[bufpos-3], + g_cfg_opt_buf[bufpos-4]); + } +#endif + + g_cfg_opt_buf[bufpos] = 0; + strncpy(&(g_cfg_opt_buf[bufpos]), str, CFG_OPT_MAXSTR - bufpos - 1); + g_cfg_opt_buf[CFG_OPT_MAXSTR-1] = 0; +} + +void +cfg_get_base_path(char *pathptr, const char *inptr, int go_up) +{ + const char *tmpptr; + char *slashptr; + char *outptr; + int add_dotdot, is_dotdot; + int len; + int c; + + /* Take full filename, copy it to pathptr, and truncate at last slash */ + /* inptr and pathptr can be the same */ + /* if go_up is set, then replace a blank dir with ".." */ + /* but first, see if path is currently just ../ over and over */ + /* if so, just tack .. onto the end and return */ + //printf("cfg_get_base start with %s\n", inptr); + + g_cfg_file_match[0] = 0; + tmpptr = inptr; + is_dotdot = 1; + while(1) { + if(tmpptr[0] == 0) { + break; + } + if(tmpptr[0] == '.' && tmpptr[1] == '.' && tmpptr[2] == '/') { + tmpptr += 3; + } else { + is_dotdot = 0; + break; + } + } + slashptr = 0; + outptr = pathptr; + c = -1; + while(c != 0) { + c = *inptr++; + if(c == '/') { + if(*inptr != 0) { /* if not a trailing slash... */ + slashptr = outptr; + } + } + *outptr++ = c; + } + if(!go_up) { + /* if not go_up, copy chopped part to g_cfg_file_match*/ + /* copy from slashptr+1 to end */ + tmpptr = slashptr+1; + if(slashptr == 0) { + tmpptr = pathptr; + } + strncpy(&g_cfg_file_match[0], tmpptr, CFG_PATH_MAX); + /* remove trailing / from g_cfg_file_match */ + len = strlen(&g_cfg_file_match[0]); + if((len > 1) && (len < (CFG_PATH_MAX - 1)) && + g_cfg_file_match[len - 1] == '/') { + g_cfg_file_match[len - 1] = 0; + } + //printf("set g_cfg_file_match to %s\n", &g_cfg_file_match[0]); + } + if(!is_dotdot && (slashptr != 0)) { + slashptr[0] = '/'; + slashptr[1] = 0; + outptr = slashptr + 2; + } + add_dotdot = 0; + if(pathptr[0] == 0 || is_dotdot) { + /* path was blank, or consisted of just ../ pattern */ + if(go_up) { + add_dotdot = 1; + } + } else if(slashptr == 0) { + /* no slashes found, but path was not blank--make it blank */ + if(pathptr[0] == '/') { + pathptr[1] = 0; + } else { + pathptr[0] = 0; + } + } + + if(add_dotdot) { + --outptr; + outptr[0] = '.'; + outptr[1] = '.'; + outptr[2] = '/'; + outptr[3] = 0; + } + + //printf("cfg_get_base end with %s, is_dotdot:%d, add_dotdot:%d\n", + // pathptr, is_dotdot, add_dotdot); +} + +void +cfg_file_init() +{ + int slot, drive; + int i; + + if(g_cfg_slotdrive < 0xfff) { + cfg_get_disk_name(&g_cfg_tmp_path[0], CFG_PATH_MAX, + g_cfg_slotdrive, 0); + + slot = g_cfg_slotdrive >> 8; + drive = g_cfg_slotdrive & 1; + for(i = 0; i < 6; i++) { + if(g_cfg_tmp_path[0] != 0) { + break; + } + /* try to get a starting path from some mounted drive */ + drive = !drive; + if(i & 1) { + slot++; + if(slot >= 8) { + slot = 5; + } + } + cfg_get_disk_name(&g_cfg_tmp_path[0], CFG_PATH_MAX, + (slot << 8) + drive, 0); + } + } else { + // Just use g_cfg_file_def_name + strncpy(&g_cfg_tmp_path[0], g_cfg_file_def_name, CFG_PATH_MAX); + } + + cfg_get_base_path(&g_cfg_file_curpath[0], &g_cfg_tmp_path[0], 0); + g_cfg_dirlist.invalid = 1; +} + +void +cfg_free_alldirents(Cfg_listhdr *listhdrptr) +{ + int i; + + if(listhdrptr->max > 0) { + // Free the old directory listing + for(i = 0; i < listhdrptr->last; i++) { + free(listhdrptr->direntptr[i].name); + } + free(listhdrptr->direntptr); + } + + listhdrptr->direntptr = 0; + listhdrptr->last = 0; + listhdrptr->max = 0; + listhdrptr->invalid = 0; + + listhdrptr->topent = 0; + listhdrptr->curent = 0; +} + + +void +cfg_file_add_dirent(Cfg_listhdr *listhdrptr, const char *nameptr, int is_dir, + int size, int image_start, int part_num) +{ + Cfg_dirent *direntptr; + char *ptr; + int inc_amt; + int namelen; + + namelen = strlen(nameptr); + if(listhdrptr->last >= listhdrptr->max) { + // realloc + inc_amt = MAX(64, listhdrptr->max); + inc_amt = MIN(inc_amt, 1024); + listhdrptr->max += inc_amt; + listhdrptr->direntptr = (Cfg_dirent*)realloc(listhdrptr->direntptr, + listhdrptr->max * sizeof(Cfg_dirent)); + } + ptr = (char*)malloc(namelen+1+is_dir); // OG Added cast + strncpy(ptr, nameptr, namelen+1); + if(is_dir) { + strcat(ptr, "/"); + } +#if 0 + printf("...file entry %d is %s\n", g_cfg_dirlist.last, ptr); +#endif + direntptr = &(listhdrptr->direntptr[listhdrptr->last]); + direntptr->name = ptr; + direntptr->is_dir = is_dir; + direntptr->size = size; + direntptr->image_start = image_start; + direntptr->part_num = part_num; + listhdrptr->last++; +} + +int +cfg_dirent_sortfn(const void *obj1, const void *obj2) +{ + const Cfg_dirent *direntptr1, *direntptr2; + int ret; + + /* Called by qsort to sort directory listings */ + direntptr1 = (const Cfg_dirent *)obj1; + direntptr2 = (const Cfg_dirent *)obj2; +#if defined(MAC) || defined(_WIN32) + // OG + ret = 0; +// ret = strcasecmp(direntptr1->name, direntptr2->name); +#else + ret = strcmp(direntptr1->name, direntptr2->name); +#endif + return ret; +} + +int +cfg_str_match(const char *str1, const char *str2, int len) +{ + const byte *bptr1, *bptr2; + int c, c2; + int i; + + /* basically, work like strcmp, except if str1 ends first, return 0 */ + + bptr1 = (const byte *)str1; + bptr2 = (const byte *)str2; + for(i = 0; i < len; i++) { + c = *bptr1++; + c2 = *bptr2++; + if(c == 0) { + if(i > 0) { + return 0; + } else { + return c - c2; + } + } + if(c != c2) { + return c - c2; + } + } + + return 0; +} + +void +cfg_file_readdir(const char *pathptr) +{ + struct dirent *direntptr; + struct stat stat_buf; + DIR *dirptr; + mode_t fmt; + char *str; + const char *tmppathptr; + int size; + int ret; + int is_dir, is_gz; + int len; + int i; + + if(!strncmp(pathptr, &g_cfg_file_cachedpath[0], CFG_PATH_MAX) && + (g_cfg_dirlist.last > 0) && (g_cfg_dirlist.invalid==0)){ + return; + } + // No match, must read new directory + + // Free all dirents that were cached previously + cfg_free_alldirents(&g_cfg_dirlist); + + strncpy(&g_cfg_file_cachedpath[0], pathptr, CFG_PATH_MAX); + strncpy(&g_cfg_file_cachedreal[0], pathptr, CFG_PATH_MAX); + + str = &g_cfg_file_cachedreal[0]; + + for(i = 0; i < 200; i++) { + len = strlen(str); + if(len <= 0) { + break; + } else if(len < CFG_PATH_MAX-2) { + if(str[len-1] != '/') { + // append / to make various routines work + str[len] = '/'; + str[len+1] = 0; + } + } + ret = cfg_stat(str, &stat_buf); + is_dir = 0; + if(ret == 0) { + fmt = stat_buf.st_mode & S_IFMT; + if(fmt == S_IFDIR) { + // it's a directory + is_dir = 1; + } + } + if(is_dir) { + break; + } else { + // user is entering more path, use base for display + cfg_get_base_path(str, str, 0); + } + } + + tmppathptr = str; + if(str[0] == 0) { + tmppathptr = "."; + } + cfg_file_add_dirent(&g_cfg_dirlist, "..", 1, 0, -1, -1); + + dirptr = opendir(tmppathptr); + if(dirptr == 0) { + printf("Could not open %s as a directory\n", tmppathptr); + return; + } + while(1) { + direntptr = readdir(dirptr); + if(direntptr == 0) { + break; + } + if(!strcmp(".", direntptr->d_name)) { + continue; + } + if(!strcmp("..", direntptr->d_name)) { + continue; + } + // Else, see if it is a directory or a file + snprintf(&g_cfg_tmp_path[0], CFG_PATH_MAX, "%s%s", + &g_cfg_file_cachedreal[0], direntptr->d_name); + ret = cfg_stat(&g_cfg_tmp_path[0], &stat_buf); + len = strlen(g_cfg_tmp_path); + is_dir = 0; + is_gz = 0; + if((len > 3) && (strcmp(&g_cfg_tmp_path[len - 3], ".gz") == 0)){ + is_gz = 1; + } + if(ret != 0) { + printf("stat %s ret %d, errno:%d\n", &g_cfg_tmp_path[0], + ret, errno); + stat_buf.st_size = 0; + continue; // skip it + } else { + fmt = stat_buf.st_mode & S_IFMT; + size = stat_buf.st_size; + if(fmt == S_IFDIR) { + // it's a directory + is_dir = 1; + } else if((fmt == S_IFREG) && (is_gz == 0)) { + if(g_cfg_slotdrive < 0xfff) { + if(size < 140*1024) { + continue; /* skip it */ + } + } else { + /* see if there are size limits */ + if((size < g_cfg_file_min_size) || + (size > g_cfg_file_max_size)) { + continue; /* skip it */ + } + } + } + } + cfg_file_add_dirent(&g_cfg_dirlist, direntptr->d_name, is_dir, + stat_buf.st_size, -1, -1); + } + + /* then sort the results (Mac's HFS+ is sorted, but other FS won't be)*/ + qsort(&(g_cfg_dirlist.direntptr[0]), g_cfg_dirlist.last, + sizeof(Cfg_dirent), cfg_dirent_sortfn); + + g_cfg_dirlist.curent = g_cfg_dirlist.last - 1; + for(i = g_cfg_dirlist.last - 1; i >= 0; i--) { + ret = cfg_str_match(&g_cfg_file_match[0], + g_cfg_dirlist.direntptr[i].name, CFG_PATH_MAX); + if(ret <= 0) { + /* set cur ent to closest filename to the match name */ + g_cfg_dirlist.curent = i; + } + } +} + +char * +cfg_shorten_filename(const char *in_ptr, int maxlen) +{ + char *out_ptr; + int len; + int c; + int i; + + /* Warning: uses a static string, not reentrant! */ + + out_ptr = &(g_cfg_file_shortened[0]); + len = strlen(in_ptr); + maxlen = MIN(len, maxlen); + for(i = 0; i < maxlen; i++) { + c = in_ptr[i] & 0x7f; + if(c < 0x20) { + c = '*'; + } + out_ptr[i] = c; + } + out_ptr[maxlen] = 0; + if(len > maxlen) { + for(i = 0; i < (maxlen/2); i++) { + c = in_ptr[len-i-1] & 0x7f; + if(c < 0x20) { + c = '*'; + } + out_ptr[maxlen-i-1] = c; + } + out_ptr[(maxlen/2) - 1] = '.'; + out_ptr[maxlen/2] = '.'; + out_ptr[(maxlen/2) + 1] = '.'; + } + + return out_ptr; +} + +void +cfg_fix_topent(Cfg_listhdr *listhdrptr) +{ + int num_to_show; + + num_to_show = listhdrptr->num_to_show; + + /* Force curent and topent to make sense */ + if(listhdrptr->curent >= listhdrptr->last) { + listhdrptr->curent = listhdrptr->last - 1; + } + if(listhdrptr->curent < 0) { + listhdrptr->curent = 0; + } + if(abs(listhdrptr->curent - listhdrptr->topent) >= num_to_show) { + listhdrptr->topent = listhdrptr->curent - (num_to_show/2); + } + if(listhdrptr->topent > listhdrptr->curent) { + listhdrptr->topent = listhdrptr->curent - (num_to_show/2); + } + if(listhdrptr->topent < 0) { + listhdrptr->topent = 0; + } +} + +void +cfg_file_draw() +{ + Cfg_listhdr *listhdrptr; + Cfg_dirent *direntptr; + const char *str, *fmt; + int num_to_show; + int yoffset; + int x, y; + int i; + + cfg_file_readdir(&g_cfg_file_curpath[0]); + + for(y = 0; y < 21; y++) { + cfg_htab_vtab(0, y); + cfg_printf("\tZ\t"); + for(x = 1; x < 79; x++) { + cfg_htab_vtab(x, y); + cfg_putchar(' '); + } + cfg_htab_vtab(79, y); + cfg_printf("\t_\t"); + } + + cfg_htab_vtab(1, 0); + cfg_putchar('\b'); + for(x = 1; x < 79; x++) { + cfg_putchar(' '); + } + if(g_cfg_slotdrive < 0xfff) { + cfg_htab_vtab(30, 0); + cfg_printf("\bSelect image for s%dd%d\b", + (g_cfg_slotdrive >> 8), (g_cfg_slotdrive & 0xff) + 1); + } else { + cfg_htab_vtab(5, 0); + cfg_printf("\bSelect file to use as %-40s\b", + cfg_shorten_filename(g_cfg_file_def_name, 40)); + } + + cfg_htab_vtab(2, 1); + cfg_printf("config.kegs path: %-56s", + cfg_shorten_filename(&g_config_kegs_name[0], 56)); + + cfg_htab_vtab(2, 2); + cfg_printf("Current KEGS directory: %-50s", + cfg_shorten_filename(&g_cfg_cwd_str[0], 50)); + + cfg_htab_vtab(2, 3); + + str = ""; + if(g_cfg_file_pathfield) { + str = "\b \b"; + } + cfg_printf("Path: %s%s", + cfg_shorten_filename(&g_cfg_file_curpath[0], 68), str); + + cfg_htab_vtab(0, 4); + cfg_printf(" \t"); + for(x = 1; x < 79; x++) { + cfg_putchar('\\'); + } + cfg_printf("\t "); + + + /* Force curent and topent to make sense */ + listhdrptr = &g_cfg_dirlist; + num_to_show = CFG_NUM_SHOWENTS; + yoffset = 5; + if(g_cfg_select_partition > 0) { + listhdrptr = &g_cfg_partitionlist; + num_to_show -= 2; + cfg_htab_vtab(2, yoffset); + cfg_printf("Select partition of %-50s\n", + cfg_shorten_filename(&g_cfg_file_path[0], 50), str); + yoffset += 2; + } + + listhdrptr->num_to_show = num_to_show; + cfg_fix_topent(listhdrptr); + for(i = 0; i < num_to_show; i++) { + y = i + yoffset; + if(listhdrptr->last > (i + listhdrptr->topent)) { + direntptr = &(listhdrptr-> + direntptr[i + listhdrptr->topent]); + cfg_htab_vtab(2, y); + if(direntptr->is_dir) { + cfg_printf("\tXY\t "); + } else { + cfg_printf(" "); + } + if(direntptr->part_num >= 0) { + cfg_printf("%3d: ", direntptr->part_num); + } + str = cfg_shorten_filename(direntptr->name, 45); + fmt = "%-45s"; + if(i + listhdrptr->topent == listhdrptr->curent) { + if(g_cfg_file_pathfield == 0) { + fmt = "\b%-45s\b"; + } else { + fmt = "%-44s\b \b"; + } + } + cfg_printf(fmt, str); + if(!direntptr->is_dir) { + cfg_print_num(direntptr->size, 13); + } + } + } + + cfg_htab_vtab(1, 5 + CFG_NUM_SHOWENTS); + cfg_putchar('\t'); + for(x = 1; x < 79; x++) { + cfg_putchar('L'); + } + cfg_putchar('\t'); + +} + +void +cfg_partition_selected() +{ + char *str; + const char *part_str; + char *part_str2; + int pos; + int part_num; + + pos = g_cfg_partitionlist.curent; + str = g_cfg_partitionlist.direntptr[pos].name; + part_num = -2; + part_str = 0; + if(str[0] == 0 || (str[0] >= '0' && str[0] <= '9')) { + part_num = g_cfg_partitionlist.direntptr[pos].part_num; + } else { + part_str = str; + } + part_str2 = 0; + if(part_str != 0) { + part_str2 = (char *)malloc(strlen(part_str)+1); + strcpy(part_str2, part_str); + } + + insert_disk(g_cfg_slotdrive >> 8, g_cfg_slotdrive & 0xff, + &(g_cfg_file_path[0]), 0, 0, part_str2, part_num); + if(part_str2 != 0) { + free(part_str2); + } + g_cfg_slotdrive = -1; + g_cfg_select_partition = -1; +} + +void +cfg_file_update_ptr(char *str) +{ + char *newstr; + int len; + + len = strlen(str) + 1; + newstr = (char*)malloc(len); + memcpy(newstr, str, len); + if(g_cfg_file_strptr) { + if(*g_cfg_file_strptr) { + free(*g_cfg_file_strptr); + } + } + *g_cfg_file_strptr = newstr; + if(g_cfg_file_strptr == &(g_cfg_rom_path)) { + printf("Updated ROM file\n"); + load_roms_init_memory(); + } + g_config_kegs_update_needed = 1; +} + +void +cfg_file_selected() +{ + struct stat stat_buf; + char *str; + int fmt; + int ret; + + if(g_cfg_select_partition > 0) { + cfg_partition_selected(); + return; + } + + if(g_cfg_file_pathfield == 0) { + // in file section area of window + str = g_cfg_dirlist.direntptr[g_cfg_dirlist.curent].name; + if(!strcmp(str, "../")) { + /* go up one directory */ + cfg_get_base_path(&g_cfg_file_curpath[0], + &g_cfg_file_curpath[0], 1); + return; + } + + snprintf(&g_cfg_file_path[0], CFG_PATH_MAX, "%s%s", //OG + &g_cfg_file_cachedreal[0], str); + } else { + // just use cfg_file_curpath directly + strncpy(&g_cfg_file_path[0], &g_cfg_file_curpath[0], + CFG_PATH_MAX); + } + + ret = cfg_stat(&g_cfg_file_path[0], &stat_buf); + fmt = stat_buf.st_mode & S_IFMT; + cfg_printf("Stat'ing %s, st_mode is: %08x\n", &g_cfg_file_path[0], + (int)stat_buf.st_mode); + + if(ret != 0) { + printf("stat %s returned %d, errno: %d\n", &g_cfg_file_path[0], + ret, errno); + } else { + if(fmt == S_IFDIR) { + /* it's a directory */ + strncpy(&g_cfg_file_curpath[0], &g_cfg_file_path[0], + CFG_PATH_MAX); + } else { + /* select it */ + if(g_cfg_slotdrive < 0xfff) { + ret = cfg_maybe_insert_disk(g_cfg_slotdrive>>8, + g_cfg_slotdrive & 0xff, + &g_cfg_file_path[0]); + if(ret > 0) { + g_cfg_slotdrive = -1; + } + } else { + cfg_file_update_ptr(&g_cfg_file_path[0]); + g_cfg_slotdrive = -1; + } + } + } +} + + +void +cfg_file_handle_key(int key) +{ + Cfg_listhdr *listhdrptr; + int len; + + if(g_cfg_file_pathfield) { + if(key >= 0x20 && key < 0x7f) { + len = strlen(&g_cfg_file_curpath[0]); + if(len < CFG_PATH_MAX-4) { + g_cfg_file_curpath[len] = key; + g_cfg_file_curpath[len+1] = 0; + } + return; + } + } + + listhdrptr = &g_cfg_dirlist; + if(g_cfg_select_partition > 0) { + listhdrptr = &g_cfg_partitionlist; + } + if( (g_cfg_file_pathfield == 0) && + ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) ) { + /* jump to file starting with this letter */ + g_cfg_file_match[0] = key; + g_cfg_file_match[1] = 0; + g_cfg_dirlist.invalid = 1; /* re-read directory */ + } + + switch(key) { + case 0x1b: + if(g_cfg_slotdrive < 0xfff) { + eject_disk_by_num(g_cfg_slotdrive >> 8, + g_cfg_slotdrive & 0xff); + } + g_cfg_slotdrive = -1; + g_cfg_select_partition = -1; + g_cfg_dirlist.invalid = 1; + break; + case 0x0a: /* down arrow */ + if(g_cfg_file_pathfield == 0) { + listhdrptr->curent++; + cfg_fix_topent(listhdrptr); + } + break; + case 0x0b: /* up arrow */ + if(g_cfg_file_pathfield == 0) { + listhdrptr->curent--; + cfg_fix_topent(listhdrptr); + } + break; + case 0x0d: /* return */ + printf("handling return press\n"); + cfg_file_selected(); + break; + case 0x09: /* tab */ + g_cfg_file_pathfield = !g_cfg_file_pathfield; + break; + case 0x08: /* left arrow */ + case 0x7f: /* delete key */ + if(g_cfg_file_pathfield) { + // printf("left arrow/delete\n"); + len = strlen(&g_cfg_file_curpath[0]) - 1; + if(len >= 0) { + g_cfg_file_curpath[len] = 0; + } + } + break; + default: + printf("key: %02x\n", key); + } +#if 0 + printf("curent: %d, topent: %d, last: %d\n", + g_cfg_dirlist.curent, g_cfg_dirlist.topent, g_cfg_dirlist.last); +#endif +} + +void +config_control_panel() +{ + void (*fn_ptr)(); + const char *str; + Cfg_menu *menuptr; + void *ptr; + int print_eject_help; + int line; + int type; + int match_found; + int menu_line; + int menu_inc; + int max_line; + int key; + int i, j; + + // First, save important text screen state + g_save_cur_a2_stat = g_video.g_cur_a2_stat; + for(i = 0; i < 0x400; i++) { + g_save_text_screen_bytes[i] = g_slow_memory_ptr[0x400+i]; + g_save_text_screen_bytes[0x400+i] =g_slow_memory_ptr[0x10400+i]; + } + + g_video.g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_VID80 | ALL_STAT_ANNUNC3 | + (0xf << BIT_ALL_STAT_TEXT_COLOR) | ALL_STAT_ALTCHARSET; + g_video.g_a2_new_all_stat[0] = g_video.g_cur_a2_stat; + g_video.g_new_a2_stat_cur_line = 0; + + cfg_printf("In config_control_panel\n"); + + for(i = 0; i < 20; i++) { + // Toss any queued-up keypresses + if(adb_read_c000() & 0x80) { + (void)adb_access_c010(); + } + } + g_adb.g_adb_repeat_vbl = 0; + g_cfg_vbl_count = 0; + // HACK: Force adb keyboard (and probably mouse) to "normal"... + + g_video.g_full_refresh_needed = -1; + g_video.g_a2_screen_buffer_changed = -1; + + cfg_home(); + j = 0; + + menuptr = g_cfg_main_menu; + if(g_sim65816.g_rom_version < 0) { + /* Must select ROM file */ + menuptr = g_cfg_rom_menu; + } + menu_line = 1; + menu_inc = 1; + g_cfg_slotdrive = -1; + g_cfg_select_partition = -1; + + while(g_config_control_panel) { + if(g_fatal_log > 0) { + x_show_alert(0, 0); + } + cfg_home(); + line = 1; + max_line = 1; + match_found = 0; + print_eject_help = 0; + cfg_printf("%s\n\n", menuptr[0].str); + while(line < 24) { + str = menuptr[line].str; + type = menuptr[line].cfgtype; + ptr = menuptr[line].ptr; + if(str == 0) { + break; + } + if((type & 0xf) == CFGTYPE_DISK) { + print_eject_help = 1; + } + cfg_parse_menu(menuptr, line, menu_line, 0); + if(line == menu_line) { + if(type != 0) { + match_found = 1; + } else if(menu_inc) { + menu_line++; + } else { + menu_line--; + } + } + if(line > max_line) { + max_line = line; + } + + cfg_printf("%s\n", g_cfg_opt_buf); + line++; + } + if((menu_line < 1) && !match_found) { + menu_line = 1; + } + if((menu_line >= max_line) && !match_found) { + menu_line = max_line; + } + + if(g_sim65816.g_rom_version < 0) { + cfg_htab_vtab(0, 21); + cfg_printf("\bYOU MUST SELECT A VALID ROM FILE\b\n"); + } + + cfg_htab_vtab(0, 23); + cfg_printf("Move: \tJ\t \tK\t Change: \tH\t \tU\t \tM\t"); + if(print_eject_help) { + cfg_printf(" Eject: "); + if(g_cfg_slotdrive >= 0) { + cfg_printf("\bESC\b"); + } else { + cfg_printf("E"); + } + } +#if 0 + cfg_htab_vtab(0, 22); + cfg_printf("menu_line: %d line: %d, vbl:%d, adb:%d key_dn:%d\n", + menu_line, line, g_cfg_vbl_count, g_adb_repeat_vbl, + g_key_down); +#endif + + if(g_cfg_slotdrive >= 0) { + cfg_file_draw(); + } + + key = -1; + refresh_video(1); + while(g_config_control_panel) { + refresh_video(1); + + video_update(); + key = adb_read_c000(); + if(key & 0x80) { + key = key & 0x7f; + (void)adb_access_c010(); + break; + } else { + key = -1; + } + micro_sleep(1.0/60.0); + g_cfg_vbl_count++; + if(!match_found) { + break; + } + } + + if((key >= 0) && (g_cfg_slotdrive < 0)) { + // Normal menu system + switch(key) { + case 0x0a: /* down arrow */ + menu_line++; + menu_inc = 1; + break; + case 0x0b: /* up arrow */ + menu_line--; + menu_inc = 0; + if(menu_line < 1) { + menu_line = 1; + } + break; + case 0x15: /* right arrow */ + cfg_parse_menu(menuptr, menu_line,menu_line,1); + break; + case 0x08: /* left arrow */ + cfg_parse_menu(menuptr,menu_line,menu_line,-1); + break; + case 0x0d: + type = menuptr[menu_line].cfgtype; + ptr = menuptr[menu_line].ptr; + switch(type & 0xf) { + case CFGTYPE_MENU: + menuptr = (Cfg_menu *)ptr; + menu_line = 1; + break; + case CFGTYPE_DISK: + g_cfg_slotdrive = type >> 4; + cfg_file_init(); + break; + case CFGTYPE_FUNC: + fn_ptr = (void (*)())ptr; + (*fn_ptr)(); + break; + case CFGTYPE_FILE: + g_cfg_slotdrive = 0xfff; + g_cfg_file_def_name = *((char **)ptr); + g_cfg_file_strptr = (char **)ptr; + cfg_file_init(); + } + break; + case 0x1b: + // Jump to last menu entry + menu_line = max_line; + break; + case 'e': + case 'E': + type = menuptr[menu_line].cfgtype; + if((type & 0xf) == CFGTYPE_DISK) { + eject_disk_by_num(type >> 12, + (type >> 4) & 0xff); + } + break; + default: + printf("key: %02x\n", key); + } + } else if(key >= 0) { + cfg_file_handle_key(key); + } + } + + for(i = 0; i < 0x400; i++) { + set_memory_c(0xe00400+i, g_save_text_screen_bytes[i], 0); + set_memory_c(0xe10400+i, g_save_text_screen_bytes[0x400+i], 0); + } + + // And quit + g_config_control_panel = 0; + g_adb.g_adb_repeat_vbl =g_sim65816.g_vbl_count + 60; + g_video.g_cur_a2_stat = g_save_cur_a2_stat; + change_display_mode(g_sim65816.g_cur_dcycs); + g_video.g_full_refresh_needed = -1; + g_video.g_a2_screen_buffer_changed = -1; +} + + +// extern byte g_bram[2][256]; +// extern byte* g_bram_ptr; +void x_clk_setup_bram_version() +{ + if(g_sim65816.g_rom_version < 3) { + g_clock.g_bram_ptr = (&g_clock.g_bram[0][0]); // ROM 01 + } else { + g_clock.g_bram_ptr = (&g_clock.g_bram[1][0]); // ROM 03 + } +} + + + +// OG Stub to be notified of disk insertion +void x_notify_disk_insertion(int _size, int _start, int _isprodos,int _slot, int _drive) +{ +} + +// Stub to be notified on motor status change +void x_notify_motor_status(int _motorOn,int _slot,int _drive, int _curtrack) +{ +} +// Stub to be notified of disk ejection +void x_notify_disk_ejection(int _slot,int _drive) +{ +} + +void x_exit(int _err) +{ + exit(_err); +} + +void x_update_info(const char* total_mhz) +{ + // OG TODO + /* + char* sp_str; + switch(g_sim65816.g_limit_speed) + { + case 1: sp_str = "1.0 Mhz"; break; + case 2: sp_str = "2.8 Mhz"; break; + case 3: sp_str = "8.0 Mhz"; break; + default: sp_str = "Unlimited"; break; + } + + sprintf(status_buf, "dcycs:%9.1f sim MHz:%s " + "Eff MHz:%s, sec:%1.3f vol:%02x pal:%x, Limit:%s", + dcycs/(1000.0*1000.0), sim_mhz_ptr, total_mhz_ptr, + dtime_diff_1sec, g_sound.g_doc_vol, g_video.g_a2vid_palette, + sp_str); + video_update_status_line(0, status_buf); + */ +} + +void x_refresh_panel(int _panel) +{ +} + +#ifdef DRIVER_WINDOWS +void x_play_sound(enum_sound hSound) +{ +} +#endif + +void +x_dialog_create_kegs_conf(const char *str) +{ + const char *path; + char tmp_buf[512]; + int ret; + + ret = x_show_alert(1, str); + if(ret) { + // Create empty file + path = "~/Library/KEGS"; + snprintf(tmp_buf, 500, "mkdir -p %s", path); + system(tmp_buf); + snprintf(tmp_buf, 500, "touch %s/%s", path, str); + system(tmp_buf); + } +} + + +void kegs_driver() +{ + g_driver.x_config_load_roms = x_config_load_roms; +} \ No newline at end of file diff --git a/kegs/Dummy/joystick_dummy.cpp b/kegs/Dummy/joystick_dummy.cpp new file mode 100644 index 0000000..c81ddba --- /dev/null +++ b/kegs/Dummy/joystick_dummy.cpp @@ -0,0 +1,49 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../src/defc.h" +#ifndef _MSC_VER // OG Unknown MSFT header +#include +#endif +#include "../src/paddles.h" +#include "../src/moremem.h" + +/* +extern int g_joystick_native_type1; +extern int g_joystick_native_type2; +extern int g_joystick_native_type; +extern int g_paddle_buttons; +extern int g_paddle_val[]; +*/ +void +joystick_init() +{ + g_joystick_native_type1 = -1; + g_joystick_native_type2 = -1; + g_joystick_native_type = -1; +} + +void +joystick_update(double dcycs) +{ + int i; + + for(i = 0; i < 4; i++) { + g_paddles.g_paddle_val[i] = 32767; + } + g_moremem.g_paddle_buttons = 0xc; +} + +void +joystick_update_buttons() +{ +} + +// OG +void joystick_shut() +{ +} + diff --git a/kegs/Dummy/sounddriver_dummy.cpp b/kegs/Dummy/sounddriver_dummy.cpp new file mode 100644 index 0000000..31d2fa4 --- /dev/null +++ b/kegs/Dummy/sounddriver_dummy.cpp @@ -0,0 +1,51 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Src/defc.h" +#include "../Src/sound.h" + +//extern int g_audio_rate; + +void x_snd_init(word32 *shmaddr) +{ + +} + +void x_snd_shutdown() +{ + +} + + +void x_snd_child_init() +{ + + set_audio_rate(g_sound.g_audio_rate); + +} + + word32* x_sound_allocate(int size) + { + + return NULL; + } + + void x_sound_free(word32* mem) + { + + } + + +int x_snd_send_audio(byte *ptr, int in_size) +{ + + return in_size; +} + + void x_play_sound(enum_sound _hSound) + { + } + \ No newline at end of file diff --git a/kegs/OSX/2mg.icns b/kegs/OSX/2mg.icns new file mode 100644 index 0000000..1e612e0 Binary files /dev/null and b/kegs/OSX/2mg.icns differ diff --git a/kegs/OSX/525.icns b/kegs/OSX/525.icns new file mode 100644 index 0000000..94e5a90 Binary files /dev/null and b/kegs/OSX/525.icns differ diff --git a/kegs/OSX/macdriver_activegs.cpp b/kegs/OSX/macdriver_activegs.cpp new file mode 100644 index 0000000..9dc5564 --- /dev/null +++ b/kegs/OSX/macdriver_activegs.cpp @@ -0,0 +1,303 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#if !defined(DRIVER_OSX) && !defined(DRIVER_IOS) +#error "missing DRIVER_IOS or DRIVER_OSX" +#endif + +#include "../src/defc.h" +#include "../src/protos_macdriver.h" +#include "../src/sim65816.h" +#include +#include "../src/video.h" +#include "../src/graphcounter.h" +#include "../src/async_event.h" +#include "../Src/StdString.h" +#include "../Src/driver.h" + +#ifdef DRIVER_IOS +#include +#include +#else +#include +#include +extern void addConsoleWindow(Kimage*); +#endif + +extern int macUsingCoreGraphics; +extern void addConsoleWindow(Kimage*); + +#ifdef ENABLEQD +extern WindowRef g_main_window; +extern PixMapHandle pixmap_backbuffer; +extern GWorldPtr backbuffer; +#endif + + + +int x_vbl_count = 0; + + +void x_check_system_input_events(void) +{ + /* + while(get_state()==IN_PAUSE && !should_emulator_terminate() ) + micro_sleep(0.1); + */ +} + + +MyString messageLine; +int messageLineVBL=0; + + + +void x_async_refresh(CGContextRef myContext,CGRect myBoundingBox) +{ + +#ifdef ENABLEQD + CEmulatorMac* pEmu = (CEmulatorMac*)CEmulator::theEmulator; + if (!pEmu) return ; +#endif + +#ifndef DRIVER_IOS + x_vbl_count++; +#endif + + addFrameRate(0); + + CHANGE_BORDER(1,0xFF); + + // OG + if (macUsingCoreGraphics) + { + if(r_sim65816.is_emulator_offscreen_available() && g_kimage_offscreen.dev_handle) + { + + /* + void addConsoleWindow(Kimage* _dst); + addConsoleWindow(&g_kimage_offscreen); + */ + + CGContextSaveGState(myContext); + +#ifndef DRIVER_IOS + // CGContextTranslateCTM(myContext,0.0, X_A2_WINDOW_HEIGHT); + CGContextTranslateCTM(myContext,0.0, myBoundingBox.size.height); + CGContextScaleCTM(myContext,1.0,-1.0); +#endif + + + CGImageRef myImage = CGBitmapContextCreateImage((CGContextRef)g_kimage_offscreen.dev_handle); + + + + CGContextDrawImage(myContext, myBoundingBox, myImage);// 6 + +#ifndef VIDEO_SINGLEVLINE + if (r_sim65816.get_video_fx() == VIDEOFX_CRT) + { + + + CGContextSetRGBFillColor(myContext,0,0,0,0.5); + for(int h=0;hwindow_port; + Rect src_rect; + Rect dest_rect; + SetRect(&src_rect,0,0,704,462); + SetRect(&dest_rect,0,0,704,462); + + if (pixmap_backbuffer) + CopyBits( (BitMap *)(*pixmap_backbuffer), + GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect, + srcCopy, NULL); + +#endif + } + + + CHANGE_BORDER(1,0); + + if (r_sim65816.is_emulator_offscreen_available() && g_driver.x_handle_state_on_paint) + g_driver.x_handle_state_on_paint(myBoundingBox.size.width,myBoundingBox.size.height); + +} + + + +void +x_redraw_status_lines() +{ +} + +void +x_push_done() +{ +} + + +int macmain(int argc, char* argv[]) +{ + update_window(); + return kegsmain(0,NULL); +} + +void +x_full_screen(int do_full) +{ +} + +void x_invalidrect(); + + +int +x_show_alert(int is_fatal, const char *str) +{ + return 0; +} + +void x_refresh_video() +{ + + if (!r_sim65816.is_emulator_offscreen_available()) + { + return ; + } + + x_vbl_count = 0; + +#ifdef ENABLE_GRAPH + g_graph.draw_graph(&g_kimage_offscreen, g_sim65816.g_vbl_count); +#endif + + x_invalidrect(); +} + +#ifdef USE_RASTER + + +int x_init_raster(void* _data) +{ + return 1; +} + + +int x_close_raster() +{ + return 1; +} + +// NANO SLEEP XP http://www.dotnet247.com/247reference/msgs/57/289291.aspx + +int x_wait_for_vbl() +{ + return 1; +} + +int x_wait_for_last_refresh(double _w) +{ + + if (_w<0.0) + { + // on est trop lent : ca a pris plus d'une 1/60ieme de seconde pour construire la frame + return 0 ; + } + +#ifdef DRIVER_IOS + extern int x_frame_rate; + if (x_frame_rate==60 && g_video_offscreen_has_been_modified && !x_vbl_count) +#else + if (g_video_offscreen_has_been_modified && !x_vbl_count) +#endif + { + while(!x_vbl_count && !r_sim65816.should_emulator_terminate()) micro_sleep(0.01); + x_vbl_count--; + } + else + { + if(_w>0.0) + { + double s = get_dtime(); + if (_w>0.01) + micro_sleep(_w); + // sur windows le micro_sleep est lÈgËrement en retard! + while( get_dtime() < s+_w); + } + } + + return 0; +} + +#endif diff --git a/kegs/OSX/macdriver_generic.cpp b/kegs/OSX/macdriver_generic.cpp new file mode 100644 index 0000000..92442a6 --- /dev/null +++ b/kegs/OSX/macdriver_generic.cpp @@ -0,0 +1,782 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#if !defined(DRIVER_OSX) && !defined(DRIVER_IOS) +#error +#endif + +#if defined(DRIVER_IOS) +#include +#include +#include + +#else +#include +#include +#include +#include + +/* +#if !defined(ACTIVEGSPLUGIN) && !defined(ACTIVEGSCOCOA) +#define ENABLEQD +#endif + */ +#endif + +#include + +#include "../src/defc.h" +#include "../src/protos_macdriver.h" +#include "../src/video.h" +#include "../src/raster.h" +#include "../src/sound.h" +#include "../src/StdString.h" + + + +int macUsingCoreGraphics=0; + +word32 g_mac_shift_control_state = 0; + +#ifdef ENABLEQD +WindowRef g_main_window; +CGrafPtr mac_window_port; +#endif + + + + + +//extern Kimage g_mainwin_kimage; + + +extern int Verbose; +/* +extern int g_video_act_width; +extern int g_video_act_height; +extern int g_video_act_margin_left; +extern int g_video_act_margin_right; +extern int g_video_act_margin_top; +extern int g_video_act_margin_bottom; +*/ +// extern int g_screen_depth; +// extern int g_force_depth; + + +//extern int g_screen_mdepth; + + +extern int g_send_sound_to_file; + +//extern int g_quit_sim_now; // OG Not need anymore +extern int g_config_control_panel; + + +int g_auto_repeat_on = -1; +int g_x_shift_control_state = 0; + + +extern int Max_color_size; + +extern word32 g_palette_8to1624[256]; +extern word32 g_a2palette_8to1624[256]; + +int g_alt_left_up = 1; +int g_alt_right_up = 1; + +//extern word32 g_full_refresh_needed; + +//extern int g_border_sides_refresh_needed; +//extern int g_border_special_refresh_needed; +//extern int g_status_refresh_needed; + +extern int g_lores_colors[]; + +extern int g_a2vid_palette; + +//extern int g_installed_full_superhires_colormap; + +//extern int g_screen_redraw_skip_amt; + +//extern word32 g_a2_screen_buffer_changed; + +int g_upd_count = 0; + + + + +void +update_window(void) +{ + + // OG Not needed + /* + SetPortWindowPort(g_main_window); + PenNormal(); + */ + + g_video.g_full_refresh_needed = -1; + g_video.g_a2_screen_buffer_changed = -1; + g_video.g_status_refresh_needed = 1; + g_video.g_border_sides_refresh_needed = 1; + g_video.g_border_special_refresh_needed = 1; + + g_upd_count++; + if(g_upd_count > 250) { + g_upd_count = 0; + } + +} + + +void x_update_modifiers(word32 state) +{ +//#ifndef ACTIVEIPHONE + + word32 state_xor; + int is_up; + + state = state & ( + cmdKey | controlKey | + shiftKey | alphaLock | optionKey + ); + state_xor = g_mac_shift_control_state ^ state; +// if (state_xor) printf("modified:%X\n",state); + is_up = 0; + if(state_xor & controlKey) { + is_up = ((state & controlKey) == 0); + adb_physical_key_update(0x36, is_up); + } + if(state_xor & alphaLock) { + is_up = ((state & alphaLock) == 0); + adb_physical_key_update(0x39, is_up); + } + if(state_xor & shiftKey) { + is_up = ((state & shiftKey) == 0); + adb_physical_key_update(0x38, is_up); + } + if(state_xor & cmdKey) { + is_up = ((state & cmdKey) == 0); + adb_physical_key_update(0x37, is_up); + } + if(state_xor & optionKey) { + is_up = ((state & optionKey) == 0); + adb_physical_key_update(0x3a, is_up); + } +//#endif + + g_mac_shift_control_state = state; +} + + +void +x_update_color(int col_num, int red, int green, int blue, word32 rgb) +{ +} + + +void +x_update_physical_colormap() +{ +} + +void x_show_color_array() +{ + int i; + + for(i = 0; i < 256; i++) { + printf("%02x: %08x\n", i, g_palette_8to1624[i]); + } +} + + + +void +x_get_kimage(Kimage *kimage_ptr) +{ +#ifdef ENABLEQD + PixMapHandle pixmap_handle; + GWorldPtr world; + Rect world_rect; + OSStatus err; +#endif +// word32 *wptr; + byte *ptr; +// int row_bytes; + int width; + int height; + int depth, mdepth; + int size; + + + width = kimage_ptr->width_req; + height = kimage_ptr->height; + depth = kimage_ptr->depth; + mdepth = kimage_ptr->mdepth; + + size = 0; + if(depth == s_video.g_screen_depth) + { + + if (!macUsingCoreGraphics) + + { +#ifdef ENABLEQD + SetRect(&world_rect, 0, 0, width, height); + err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0); + pixmap_handle = GetGWorldPixMap(world); + err = LockPixels(pixmap_handle); + ptr = (byte *)GetPixBaseAddr(pixmap_handle); + int row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff); + kimage_ptr->width_act = row_bytes / (mdepth >> 3); + mac_printf("Got depth: %d, bitmap_ptr: %p, width: %d\n", depth, ptr, kimage_ptr->width_act); + mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",(int)(*pixmap_handle)->baseAddr,(*pixmap_handle)->rowBytes,(*pixmap_handle)->pixelType); + word32* wptr = (word32 *)(*pixmap_handle); + mac_printf("wptr: %p=%08x %08x %08x %08x %08x %08x %08x %08x\n",wptr,wptr[0], wptr[1], wptr[2], wptr[3],wptr[4], wptr[5], wptr[6], wptr[7]); + kimage_ptr->dev_handle = pixmap_handle; + kimage_ptr->data_ptr = ptr; +#endif + } + else + { + + + kimage_ptr->width_act = width ; + size = height* kimage_ptr->width_act * mdepth >> 3; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + mac_printf("malloc for data fail, mdepth:%d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + kimage_ptr->dev_handle = (void *)-1; + } + } + else { + + /* allocate buffers for video.c to draw into */ + + + kimage_ptr->width_act = width ; + size = height* kimage_ptr->width_act * mdepth >> 3 ; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + mac_printf("malloc for data fail, mdepth:%d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + kimage_ptr->dev_handle = (void *)-1; + } + + mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr, + kimage_ptr->dev_handle, kimage_ptr->data_ptr, size); + +} + + +#ifdef ENABLEQD +PixMapHandle pixmap_backbuffer=NULL; +GWorldPtr backbuffer=NULL; +#endif + +// OG MAx OSX 10.5 and iOS 3.1 do not support passing null while creating bitmapcontext = must provide its own array +#if ( MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 ) || ( __IPHONE_OS_VERSION_MAX_REQUIRED < 4000 ) +#define CGBITMAPCONTEXT_REQUIRES_DATA +#endif + + + +void x_video_init() +{ + int lores_col; + int i; + + printf("Preparing graphics system\n"); + + +#ifndef ENABLEQD + s_video.g_screen_depth = s_video.g_screen_mdepth = 32; +#else + // Get screen depth + GDHandle g_gdhandle = GetGDevice(); + s_video.g_screen_mdepth = (**((**g_gdhandle).gdPMap)).pixelSize; + + s_video.g_screen_depth = s_video.g_screen_mdepth; + +#endif + + + if(s_video.g_screen_depth > 16) { + /* 32-bit display */ + s_video.g_red_mask = 0xff; + s_video.g_green_mask = 0xff; + s_video.g_blue_mask = 0xff; + + if (macUsingCoreGraphics) + { + s_video.g_red_left_shift = 0; + s_video.g_green_left_shift = 8; + s_video.g_blue_left_shift = 16; + } + else + { + s_video.g_red_left_shift = 16; + s_video.g_green_left_shift = 8; + s_video.g_blue_left_shift = 0; + + } + + s_video.g_red_right_shift = 0; + s_video.g_green_right_shift = 0; + s_video.g_blue_right_shift = 0; + } else if(s_video.g_screen_depth > 8) { + /* 16-bit display */ + s_video.g_red_mask = 0x1f; + s_video.g_green_mask = 0x1f; + s_video.g_blue_mask = 0x1f; + s_video.g_red_left_shift = 10; + s_video.g_green_left_shift = 5; + s_video.g_blue_left_shift = 0; + s_video.g_red_right_shift = 3; + s_video.g_green_right_shift = 3; + s_video.g_blue_right_shift = 3; + } + + + // OG Create backbuffer +#ifdef USE_RASTER + x_init_raster(NULL); +#endif + + init_kimage(&g_kimage_offscreen,0,s_video.g_screen_depth, s_video.g_screen_mdepth); + g_kimage_offscreen.width_act = X_A2_WINDOW_WIDTH; + g_kimage_offscreen.width_req = X_A2_WINDOW_WIDTH; + g_kimage_offscreen.height = X_A2_WINDOW_HEIGHT; + + + if (!macUsingCoreGraphics) + { + +#ifdef ENABLEQD + /* + Rect r; + SetRect(&r, 0, 0, 704, 462); + NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0); + pixmap_backbuffer = GetGWorldPixMap(backbuffer); + */ + x_get_kimage(&g_kimage_offscreen); + + +#endif + } + else + { + + + + int pixelsWide = g_kimage_offscreen.width_act; + int pixelsHigh = g_kimage_offscreen.height; + int bitmapBytesPerRow = (pixelsWide * 4);// 1 + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + char* bitmapData = NULL; +#ifdef CGBITMAPCONTEXT_REQUIRES_DATA + int bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); + void* bitmapDataAllocPtr = NULL; + bitmapData = (char*)memalloc_align(bitmapByteCount, 256, &bitmapDataAllocPtr); + if (bitmapData == NULL) + { + fprintf (stderr, "Memory not allocated!"); + return ; + } + g_kimage_offscreen.dev_handle2 = bitmapDataAllocPtr; +#else + bitmapData=NULL; +#endif + CGContextRef offscreenContext = CGBitmapContextCreate (bitmapData,// 4 + pixelsWide, + pixelsHigh, + 8, // bits per component + bitmapBytesPerRow, + colorSpace, + kCGImageAlphaNoneSkipLast); + if (offscreenContext== NULL) + { + #ifdef CGBITMAPCONTEXT_REQUIRES_DATA + if (bitmapDataAllocPtr) + free (bitmapDataAllocPtr);// 5 + bitmapData=NULL; + bitmapDataAllocPtr=NULL; + #endif + printf("context not created"); + return ; + } + + +#ifndef CGBITMAPCONTEXT_REQUIRES_DATA + bitmapData = (char*)CGBitmapContextGetData(offscreenContext); +#endif + if (!bitmapData) + { + printf("video initialization failed..."); + return ; + } + + + g_kimage_offscreen.data_ptr = (byte*)bitmapData; + g_kimage_offscreen.dev_handle = (void*)offscreenContext; + + + CGContextSetRGBFillColor (offscreenContext, 0, 0, 0, 1); + CGContextFillRect (offscreenContext, CGRectMake (0,0, 704, 462 )); + + CGColorSpaceRelease( colorSpace );// 6 + } + + + video_get_kimages(); + + if(s_video.g_screen_depth != 8) { + // Get g_mainwin_kimage + video_get_kimage(&s_video.g_mainwin_kimage, 0, s_video.g_screen_depth, + s_video.g_screen_mdepth); + } + + for(i = 0; i < 256; i++) { + lores_col = g_lores_colors[i & 0xf]; + video_update_color_raw(i, lores_col); + g_a2palette_8to1624[i] = g_palette_8to1624[i]; + } + + s_video.g_installed_full_superhires_colormap = 1; + + fflush(stdout); + +} + + +void x_video_shut() +{ + + + printf("xdriver_end\n"); + + + if (macUsingCoreGraphics) + { + #ifdef CGBITMAPCONTEXT_REQUIRES_DATA + if (g_kimage_offscreen.dev_handle2) + { + free(g_kimage_offscreen.dev_handle2); + g_kimage_offscreen.dev_handle2 = NULL; + // bitmapDataAllocPtr=NULL; + // bitmapData=NULL; + } + + #endif + g_kimage_offscreen.data_ptr = NULL; + if (g_kimage_offscreen.dev_handle) + { + CGContextRelease((CGContextRef)g_kimage_offscreen.dev_handle); + g_kimage_offscreen.dev_handle = NULL; + // bitmapData = NULL; + } + } + else + { +#ifdef ENABLEQD + pixmap_backbuffer = NULL; + DisposeGWorld(backbuffer); + backbuffer = NULL; +#endif + } + +#ifndef ACTIVEGS + extern int g_fatal_log; +if(g_fatal_log >= 0) +{ + x_show_alert(1, 0); +} +#endif +} + + + + +//extern volatile int x_in_async_refresh; + +void +x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, + int width, int height) +{ + + + // OG TO INVESTIGATE + if (!kimage_ptr->data_ptr) + { + printf("x_push_kimage: k_image_ptr not yet initilialized\n"); + return ; + } + + + + if (!g_kimage_offscreen.data_ptr) + { + printf("err:graphic not initialized yet"); + return; + } + int wd = kimage_ptr->width_act * kimage_ptr->mdepth>>3; + int w = width *4; + + // int bitmapBytesPerRow = (pixelsWide * 4);// 1 + int bitmapBytesPerRow = g_kimage_offscreen.width_act * (g_kimage_offscreen.mdepth >> 3); + + byte* ptrdest = g_kimage_offscreen.data_ptr + bitmapBytesPerRow*desty + destx*4; + byte* srcdest = kimage_ptr->data_ptr + wd*srcy + srcx*4; + for(int i=0;idev_handle == (void*)-1) + { + free(kimage_ptr->data_ptr); + kimage_ptr->data_ptr = NULL; + } + else + { + if (!macUsingCoreGraphics) + { +#ifdef ENABLEQD + UnlockPixels((PixMapHandle)kimage_ptr->dev_handle); + kimage_ptr->dev_handle = NULL; + DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2); + kimage_ptr->dev_handle2 = NULL; +#endif + } + } +} + +// OG Addding ratio +int x_calc_ratio(float&x,float&y) +{ + return 1; +} + + +void x_refresh_buffer() +{ +#ifdef ENABLEQD +Rect src_rect, dest_rect; +CGrafPtr window_port; + +PixMapHandle pixmap_handle = (PixMapHandle)g_kimage_offscreen.dev_handle; +SetRect(&src_rect, 0, 0, g_kimage_offscreen.width_act, g_kimage_offscreen.height); +dest_rect = src_rect; + + SetPortWindowPort(g_main_window); + window_port = GetWindowPort(g_main_window); + + CopyBits( (BitMap *)(*pixmap_handle), + GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect, + srcCopy, NULL); +#endif +} + +void x_recenter_hw_mouse() +{ + +} + +#if 0 +bool x_load_wav(const char* _Path, unsigned char** _outDataBuffer, unsigned int & _outFileSize, OASound & _sound ) +{ + + CFStringRef rawCFString = CFStringCreateWithCString( NULL, _Path, CFStringGetSystemEncoding() ); + CFURLRef urlRef = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, rawCFString, kCFURLPOSIXPathStyle, FALSE ); + + + AudioFileID aSoundID = 0; + bool bSuccess=FALSE; + + // Open file + OSStatus error = AudioFileOpenURL(/*(CFURLRef)aFileURL*/urlRef, kAudioFileReadPermission, 0, &aSoundID); + if (error == noErr) + { // success + + //get Format + AudioFileTypeID format = 0; + UInt32 sizeFormat = sizeof(AudioFileTypeID); + OSStatus result = AudioFileGetProperty(aSoundID, kAudioFilePropertyFileFormat, &sizeFormat, (void*)&format); + if(result != noErr) + { + printf("cannot find file format"); + goto cleanup; + } + + if (format !=kAudioFileWAVEType) + { + printf("sound format not supported"); + goto cleanup; + + } + + //get DataFormat + AudioStreamBasicDescription dataFormat ; + UInt32 sizeDataFormat = sizeof(AudioStreamBasicDescription); + result = AudioFileGetProperty(aSoundID, kAudioFilePropertyDataFormat, &sizeDataFormat, (void*)&dataFormat); + if(result != noErr) + { + printf("cannot find file dataformat"); + goto cleanup; + } + + _sound.frequency = (int)dataFormat.mSampleRate; + _sound.depth = dataFormat.mBitsPerChannel; + _sound.nbchannel = dataFormat.mChannelsPerFrame; + + //get File size + UInt64 outDataSize = 0; + UInt32 thePropSize = sizeof(UInt64); + result = AudioFileGetProperty(aSoundID, kAudioFilePropertyAudioDataByteCount, + &thePropSize, &outDataSize); + if(result != noErr) + { + printf("cannot find file size"); + goto cleanup; + } + + _outFileSize = (UInt32)outDataSize; + + + + // Create buffer + *_outDataBuffer = (UInt8*)malloc(_outFileSize); + + //copy file into buffer + OSStatus l_readResult = noErr; + l_readResult = AudioFileReadBytes(aSoundID, false, 0, (UInt32*)&_outFileSize, *_outDataBuffer); + + if (l_readResult == noErr) + bSuccess = TRUE; //Ouf! + + } + +cleanup: + + if (!bSuccess) + printf(" --- Error %ld loading sound at path: %s",error,_Path); + else + { + // printf(" --- Sound loaded : %s",_Path); + } + + if (aSoundID) + AudioFileClose(aSoundID); + + if (urlRef) + CFRelease(urlRef); + CFRelease(rawCFString); + + return bSuccess; +} +#endif + + +void x_preload_sounds() +{ + + for(int i=0;i= 3); + +} + + + +pascal OSStatus +quit_event_handler(EventHandlerCallRef call_ref, EventRef event, void *ignore) +{ + OSStatus err; + + err = CallNextEventHandler(call_ref, event); + if(err == noErr) { + g_quit_seen = 1; + } + return err; +} + +void +show_simple_alert(const char *str1,const char *str2, const char *str3, int num) +{ + char buf[256]; + + g_fatal_log_strs[0] = kegs_malloc_str(str1); + g_fatal_log_strs[1] = kegs_malloc_str(str2); + g_fatal_log_strs[2] = kegs_malloc_str(str3); + g_fatal_log = 3; + if(num != 0) { + snprintf(buf, 250, ": %d", num); + g_fatal_log_strs[g_fatal_log++] = kegs_malloc_str(buf); + } + x_show_alert(0, 0); +} + + + +void cfg_toggle_config_panel(); + +pascal OSStatus +my_cmd_handler( EventHandlerCallRef handlerRef, EventRef event, void *userdata) +{ + OSStatus osresult; + HICommand command; + word32 command_id; + + osresult = eventNotHandledErr; + + GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, + sizeof(HICommand), NULL, &command); + + command_id = (word32)command.commandID; + switch(command_id) { + case 'Kbep': + SysBeep(10); + osresult = noErr; + break; + case 'abou': + show_simple_alert("KEGSMAC v", (char *)g_kegs_version_str, + ", Copyright 2004 Kent Dickey\n" + "Latest version at http://kegs.sourceforge.net/\n", 0); + osresult = noErr; + break; + case 'KCFG': +#ifdef ACTIVEGS +#else + cfg_toggle_config_panel(); +#endif + osresult = noErr; + break; + case 'quit': + break; + case 'swin': + /* not sure what this is, but Panther sends it */ + break; + default: + printf("commandID %08x unknown\n", command_id); + SysBeep(90); + break; + } + return osresult; +} + + + +pascal OSStatus +my_win_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata) +{ + OSStatus os_result; + UInt32 event_kind; + + os_result = eventNotHandledErr; + + // SysBeep(1); + + event_kind = GetEventKind(event); + // show_alert("win handler", event_kind); + if(event_kind == kEventWindowDrawContent) + { + update_window(); + } if(event_kind == kEventWindowClose) { + + r_sim65816.quit_emulator(); + +#ifndef ACTIVEGS + g_quit_seen = 1; + my_exit(0); +#else + // OG notify emulator that window has closed + g_main_window = 0; +#endif + } else { + //show_event(GetEventClass(event), event_kind, 0); + update_window(); + } + + return os_result; +} + + +pascal OSStatus +dummy_event_handler(EventHandlerCallRef call_ref, EventRef in_event, + void *ignore) +{ + OSStatus err; + EventHandlerRef installed_handler; + EventTypeSpec event_spec = { kEventClassApplication, kEventAppQuit }; + + // From http://developer.apple.com/qa/qa2001/qa1061.html + // Trick to move main event queue to use ReceiveNextEvent in an event + // handler called by RunApplicationEventLoop + + err = InstallApplicationEventHandler(g_quit_handler_UPP, 1, &event_spec, + NULL, &installed_handler); + + x_async_sound_init(); + kegsmain(g_mac_argc, g_mac_argv); + x_async_snd_shutdown(); + + return noErr; +} + +/* +void add_event_key(int _k,int _u) +{ +} + */ + +void +check_input_events() +{ + OSStatus err; + EventTargetRef target; + EventRef event; + UInt32 event_class, event_kind; + byte mac_keycode; + UInt32 keycode; + UInt32 modifiers; + Point mouse_point, mouse_delta_point; + WindowRef window_ref; + int button, button_state; + EventMouseButton mouse_button; + int handled; + int mouse_events; + int is_up; + int in_win; + int ignore; + + if(g_quit_seen) { + exit(0); + } + + if (!g_main_window) + return ; + SetPortWindowPort(g_main_window); + + mouse_events = 0; + target = GetEventDispatcherTarget(); + while(1) { + err = ReceiveNextEvent(0, NULL, kEventDurationNoWait, + true, &event); + + if(err == eventLoopTimedOutErr) { + break; + } + if(err != noErr) { + printf("ReceiveNextEvent err: %d\n", (int)err); + break; + } + + event_class = GetEventClass(event); + event_kind = GetEventKind(event); + handled = 0; + switch(event_class) { + case kEventClassKeyboard: + handled = 1; + keycode = 0; + modifiers = 0; + GetEventParameter(event, kEventParamKeyMacCharCodes, + typeChar, NULL, sizeof(byte), NULL, + &mac_keycode); + GetEventParameter(event, kEventParamKeyCode, + typeUInt32, NULL, sizeof(UInt32), NULL, + &keycode); + GetEventParameter(event, kEventParamKeyModifiers, + typeUInt32, NULL, sizeof(UInt32), NULL, + &modifiers); + + x_update_modifiers((word32)modifiers); + + // Key up/down event + is_up = -1; + switch(event_kind) { + case kEventRawKeyDown: + is_up = 0; + //printf("key down: %02x, %08x\n", + // (int)mac_keycode, (int)keycode); + break; + case kEventRawKeyUp: + is_up = 1; + //printf("key up: %02x, %08x\n", + // (int)mac_keycode, (int)keycode); + break; + case kEventRawKeyModifiersChanged: + is_up = -1; + //printf("key xxx: %08x\n", (int)modifiers); + break; + } + if(is_up >= 0) { + adb_physical_key_update((int)keycode, is_up); + } + break; + case kEventClassMouse: + handled = 2; + mouse_events++; + GetEventParameter(event, kEventParamMouseLocation, + typeQDPoint, NULL, sizeof(Point), NULL, + &mouse_point); + GetWindowRegion(g_main_window, kWindowContentRgn, + g_event_rgnhandle); + in_win = PtInRgn(mouse_point, g_event_rgnhandle); + // in_win = 1 if it was in the contect region of window + err = GetEventParameter(event, kEventParamMouseDelta, + typeQDPoint, NULL, sizeof(Point), NULL, + &mouse_delta_point); + button = 0; + button_state = -1; + switch(event_kind) { + case kEventMouseDown: + button_state = 7; + handled = 3; + break; + case kEventMouseUp: + button_state = 0; + handled = 3; + break; + } + if(button_state >= 0) { + GetEventParameter(event, kEventParamMouseButton, + typeMouseButton, NULL, + sizeof(EventMouseButton), NULL, + &mouse_button); + button = mouse_button; + if(button > 1) { + button = 4 - button; + button = 1 << button; + } + ignore = (button_state != 0) && + (!in_win || g_ignore_next_click); + ignore = ignore || !g_mainwin_active; + if(ignore) { + // Outside of A2 window, ignore clicks + button = 0; + } + if(button_state == 0) { + g_ignore_next_click = 0; + } + } + + GlobalToLocal(&mouse_point); + + if(g_adb.g_warp_pointer) { + if(err == 0) { + g_mac_mouse_x += mouse_delta_point.h; + g_mac_mouse_y += mouse_delta_point.v; + } + mac_warp_mouse(); + } else { + g_mac_mouse_x = mouse_point.h - + g_video_act_margin_left; + g_mac_mouse_y = mouse_point.v - + g_video_act_margin_top; + } + +#if 0 + printf("Mouse %d at: %d,%d button:%d, button_st:%d\n", + mouse_events, g_mac_mouse_x, g_mac_mouse_y, + button, button_state); + printf("Mouse deltas: err:%d, %d,%d\n", (int)err, + mouse_delta_point.h, mouse_delta_point.v); +#endif + + update_mouse(g_mac_mouse_x, g_mac_mouse_y, + button_state, button & 7); + if(g_adb.g_warp_pointer) { + g_mac_mouse_x = A2_WINDOW_WIDTH/2; + g_mac_mouse_y = A2_WINDOW_HEIGHT/2; + update_mouse(g_mac_mouse_x, g_mac_mouse_y,0,-1); + } + + +#if 0 + // regarde si c'est un double click + int nbclick; + GetEventParameter(event, kEventParamClickCount, + typeUInt32, NULL, + sizeof(typeUInt32), NULL, + &nbclick); + if (nbclick==2) + { + extern void add_simulate_space(); + add_simulate_space(); + } +#endif + + + break; + case kEventClassApplication: + switch(event_kind) { + case kEventAppActivated: + handled = 1; + g_mainwin_active = 1; + window_ref = 0; + GetEventParameter(event, kEventParamWindowRef, + typeWindowRef, NULL, sizeof(WindowRef), + NULL, &window_ref); + if(window_ref == g_main_window) { + g_ignore_next_click = 1; + } + break; + case kEventAppDeactivated: + handled = 1; + g_mainwin_active = 0; + g_ignore_next_click = 1; + break; + } + break; + } + // show_event(event_class, event_kind, handled); + if(handled != 1) { + (void)SendEventToEventTarget(event, target); + } + ReleaseEvent(event); + } + + return; +} + +void +temp_run_application_event_loop(void) +{ + OSStatus err; + EventRef dummy_event; + EventHandlerRef install_handler; + EventTypeSpec event_spec = { 'KWIN', 'KWIN' }; + + // Create UPP for dummy_event_handler and for quit_event_handler + err = noErr; + dummy_event = 0; + + g_dummy_event_handler_UPP = NewEventHandlerUPP(dummy_event_handler); + g_quit_handler_UPP = NewEventHandlerUPP(quit_event_handler); + if((g_dummy_event_handler_UPP == 0) || (g_quit_handler_UPP == 0)) { + err = memFullErr; + } + + if(err == noErr) { + err = InstallApplicationEventHandler(g_dummy_event_handler_UPP, + 1, &event_spec, 0, &install_handler); + if(err == noErr) { + err = MacCreateEvent(NULL, 'KWIN', 'KWIN', + GetCurrentEventTime(), kEventAttributeNone, + &dummy_event); + if(err == noErr) { + err = PostEventToQueue(GetMainEventQueue(), + dummy_event, kEventPriorityHigh); + } + if(err == noErr) { + RunApplicationEventLoop(); + } + + (void)RemoveEventHandler(install_handler); + } + } + + if(dummy_event != NULL) { + ReleaseEvent(dummy_event); + } +} + + + +int +#ifdef ACTIVEGS +macmain +#else +main +#endif +(int argc, char* argv[]) +{ + ProcessSerialNumber my_psn; + + IBNibRef nibRef; + EventHandlerUPP handlerUPP; + EventTypeSpec cmd_event[3]; + GDHandle g_gdhandle ; + Rect win_rect; + OSStatus err; + +#ifndef ACTIVEGS + char *argptr; + int slash_cnt; + int i; + + /* Prepare argv0 */ + slash_cnt = 0; + argptr = argv[0]; + for(i = strlen(argptr); i >= 0; i--) { + if(argptr[i] == '/') { + slash_cnt++; + if(slash_cnt == 3) { + strncpy(&(g_argv0_path[0]), argptr, i); + g_argv0_path[i] = 0; + } + } + } + + printf("g_argv0_path is %s\n", g_argv0_path); + + g_mac_argv[0] = argv[0]; + g_mac_argc = 1; + i = 1; + while((i < argc) && (g_mac_argc < MAX_MAC_ARGS)) { + if(!strncmp(argv[i], "-psn", 4)) { + /* skip this argument */ + } else { + g_mac_argv[g_mac_argc++] = argv[i]; + } + i++; + } +#endif + + InitCursor(); + g_event_rgnhandle = NewRgn(); + g_status_font_family = FMGetFontFamilyFromName("\pCourier"); + + SetRect(&win_rect, 0, 0, X_A2_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT + // OG Remove status line from ActiveGS window +#ifndef ACTIVEGS + + MAX_STATUS_LINES*16 + 8 +#endif + ); + OffsetRect(&win_rect, 64, 50); + + + // Create a Nib reference passing the name of the nib file + // CreateNibReference only searches into the application bundle. + err = CreateNibReference(CFSTR("main"), &nibRef); + require_noerr( err, CantGetNibRef ); + // Once the nib reference is created, set the menu bar. + err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar")); + require_noerr( err, CantSetMenuBar ); + + +#ifndef ACTIVEGS + err = CreateNewWindow(kDocumentWindowClass, + kWindowStandardDocumentAttributes | + kWindowStandardHandlerAttribute, + &win_rect, &g_main_window); + + err = SetWindowTitleWithCFString(g_main_window, CFSTR("KEGSMAC")); +#else + err = CreateNewWindow(kDocumentWindowClass, + (kWindowCloseBoxAttribute /*| kWindowFullZoomAttribute */| kWindowCollapseBoxAttribute /*| kWindowResizableAttribute*/) /*kWindowStandardDocumentAttributes*/ | + kWindowStandardHandlerAttribute, + &win_rect, &g_main_window); + extern CFStringRef activeGSversionSTR; + err = SetWindowTitleWithCFString(g_main_window, activeGSversionSTR); +#endif + + //printf("CreateNewWindow ret: %d, g_main_window: %p\n", (int)err, g_main_window); + + + // We don't need the nib reference anymore. + DisposeNibReference(nibRef); + + SysBeep(120); + + handlerUPP = NewEventHandlerUPP( my_cmd_handler ); + + cmd_event[0].eventClass = kEventClassCommand; + cmd_event[0].eventKind = kEventProcessCommand; + InstallWindowEventHandler(g_main_window, handlerUPP, 1, &cmd_event[0], + (void *)g_main_window, NULL); + + handlerUPP = NewEventHandlerUPP(my_win_handler); + cmd_event[0].eventClass = kEventClassWindow; + cmd_event[0].eventKind = kEventWindowDrawContent; + cmd_event[1].eventClass = kEventClassWindow; + cmd_event[1].eventKind = kEventWindowUpdate; + cmd_event[2].eventClass = kEventClassWindow; + cmd_event[2].eventKind = kEventWindowClose; + err = InstallWindowEventHandler(g_main_window, handlerUPP, 3, + &cmd_event[0], (void *)g_main_window, NULL); + require_noerr(err, CantCreateWindow); + + // Get screen depth + g_gdhandle = GetGDevice(); + s_video.g_screen_mdepth = (**((**g_gdhandle).gdPMap)).pixelSize; + + s_video.g_screen_depth = s_video.g_screen_mdepth; + + if(s_video.g_screen_depth > 16) { + /* 32-bit display */ + s_video.g_red_mask = 0xff; + s_video.g_green_mask = 0xff; + s_video.g_blue_mask = 0xff; + + /* + if (macUsingCoreGraphics) + { + g_red_left_shift = 0; + g_green_left_shift = 8; + g_blue_left_shift = 16; + } + else + */ + { + s_video.g_red_left_shift = 16; + s_video.g_green_left_shift = 8; + s_video.g_blue_left_shift = 0; + + } + + s_video.g_red_right_shift = 0; + s_video.g_green_right_shift = 0; + s_video.g_blue_right_shift = 0; + } else if(s_video.g_screen_depth > 8) { + /* 16-bit display */ + s_video.g_red_mask = 0x1f; + s_video.g_green_mask = 0x1f; + s_video.g_blue_mask = 0x1f; + s_video.g_red_left_shift = 10; + s_video.g_green_left_shift = 5; + s_video.g_blue_left_shift = 0; + s_video.g_red_right_shift = 3; + s_video.g_green_right_shift = 3; + s_video.g_blue_right_shift = 3; + } + + // show_alert("About to show window", (int)g_main_window); + update_main_window_size(); + + update_window(); + + + // The window was created hidden so show it. + ShowWindow( g_main_window ); + BringToFront( g_main_window ); + + update_window(); + + // Make us pop to the front a different way + err = GetCurrentProcess(&my_psn); + if(err == noErr) { + (void)SetFrontProcess(&my_psn); + } + + // Call the event loop + temp_run_application_event_loop(); + return 0; + +CantCreateWindow: +CantSetMenuBar: +CantGetNibRef: + show_simple_alert("ending", "", "error code", err); + return err; +} + +void +x_redraw_status_lines() +{ + // OG Disable status line +#ifndef ACTIVEGS + Rect rect; + Pattern white_pattern; + char tmp_buf[256]; + char *buf; + int len; + int line; + int height; + int margin; + + SetPortWindowPort(g_main_window); + PenNormal(); + height = 16; + margin = 0; + TextFont(g_status_font_family); + TextFace(normal); + TextSize(12); + + SetRect(&rect, 0, X_A2_WINDOW_HEIGHT + margin, X_A2_WINDOW_WIDTH, + X_A2_WINDOW_HEIGHT + margin + MAX_STATUS_LINES*height); + GetQDGlobalsWhite(&white_pattern); + FillRect(&rect, &white_pattern); + + for(line = 0; line < MAX_STATUS_LINES; line++) { + buf = g_status_ptrs[line]; + if(buf == 0) { + /* skip it */ + continue; + } + MoveTo(10, X_A2_WINDOW_HEIGHT + height*line + margin + height); + len = MIN(250, strlen(buf)); + strncpy(&tmp_buf[1], buf, len); + tmp_buf[0] = len; + DrawString((const unsigned char*)&tmp_buf[0]); + } +#endif +} + +void +x_full_screen(int do_full) +{ + +#if 0 + WindowRef new_window; + short width, height; + OSErr ret; + + width = 640; + height = 480; + if(do_full && (g_mac_fullscreen_state == 0)) { + g_main_window_saved = g_main_window; + + GetWindowBounds(g_main_window, kWindowContentRgn, + &g_main_window_saved_rect); + ret = BeginFullScreen(&g_mac_fullscreen_state, 0, + &width, &height, &new_window, 0, 0); + printf("Ret beginfullscreen: %d\n", (int)ret); + printf("New width: %d, new height: %d\n", width, height); + if(ret == noErr) { + g_main_window = new_window; + } else { + g_mac_fullscreen_state = 0; + } + } else if(!do_full && (g_mac_fullscreen_state != 0)) { + ret = EndFullScreen(g_mac_fullscreen_state, 0); + printf("ret endfullscreen: %d\n", (int)ret); + g_main_window = g_main_window_saved; + g_mac_fullscreen_state = 0; + //InitCursor(); + SetWindowBounds(g_main_window, kWindowContentRgn, + &g_main_window_saved_rect); + } + + update_main_window_size(); + + ShowWindow(g_main_window); + BringToFront(g_main_window); + update_window(); +#endif +} + + +void +x_push_done() +{ + + CGrafPtr window_port; + + SetPortWindowPort(g_main_window); + window_port = GetWindowPort(g_main_window); + + QDFlushPortBuffer(window_port, 0); + +} + +void +mac_warp_mouse() +{ +#ifndef ACTIVEGS + Rect port_rect; + Point win_origin_pt; + CGPoint cgpoint; + CGDisplayErr cg_err; + + GetPortBounds(GetWindowPort(g_main_window), &port_rect); + SetPt(&win_origin_pt, port_rect.left, port_rect.top); + LocalToGlobal(&win_origin_pt); + + cgpoint = CGPointMake( (float)(win_origin_pt.h + X_A2_WINDOW_WIDTH/2), + (float)(win_origin_pt.v + X_A2_WINDOW_HEIGHT/2)); + cg_err = CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); +#endif +} + +int x_refresh_video() +{ + void x_refresh_buffer(); + x_refresh_buffer(); + return 1; +} + +#ifdef ACTIVEGS +void x_refresh_panel(enum refreshpanelenum _enum) +{ +} +#endif diff --git a/kegs/OSX/macsnd_driver.cpp b/kegs/OSX/macsnd_driver.cpp new file mode 100644 index 0000000..c8c51e7 --- /dev/null +++ b/kegs/OSX/macsnd_driver.cpp @@ -0,0 +1,194 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifndef DRIVER_OSX +#error +#endif + +/************************************************************************/ +/* KEGS: Apple //gs Emulator */ +/* Copyright 2002 by Kent Dickey */ +/* */ +/* This code is covered by the GNU GPL */ +/* */ +/* The KEGS web page is kegs.sourceforge.net */ +/* You may contact the author at: kadickey@alumni.princeton.edu */ +/************************************************************************/ + +const char rcsid_macsnd_driver_c[] = "@(#)$KmKId: macsnd_driver.c,v 1.4 2003-10-17 15:57:40-04 kentd Exp $"; + +#include "defc.h" + +#include + + +#include "sound.h" +#include + +#define MACSND_REBUF_SIZE (64*1024) +#define MACSND_QUANTA 512 +/* MACSND_QUANTA must be >= 128 and a power of 2 */ + +word32 g_macsnd_rebuf[MACSND_REBUF_SIZE]; +volatile word32 *g_macsnd_rebuf_ptr; +volatile word32 *g_macsnd_rebuf_cur; +volatile int g_macsnd_playing = 0; + +extern int Verbose; + +//extern int g_audio_rate; +extern word32 *g_sound_shm_addr; +extern int g_sound_size; + + + +SndChannelPtr g_snd_channel_ptr; +ExtSoundHeader g_snd_hdr; +SndCommand g_snd_cmd; + +void +mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd) +{ + OSStatus err; + int samps; + + // This is an interrupt routine--no printf, etc! + + samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur; + if(samps < 0) { + samps += MACSND_REBUF_SIZE; + } + + samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples + if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) { + samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) - + g_macsnd_rebuf_cur; + } + if(samps > 0) { + g_macsnd_playing = 1; + g_snd_hdr.numFrames = samps; + g_snd_hdr.loopEnd = samps; + g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur; // OG Cast from byte* to ,char* + + g_snd_cmd.cmd = bufferCmd; + g_snd_cmd.param1 = 0; + g_snd_cmd.param2 = (long) &g_snd_hdr; + + g_macsnd_rebuf_cur += samps; + if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) { + g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE; + } + + err = SndDoImmediate(g_snd_channel_ptr, &g_snd_cmd); + + // And set-up callback + g_snd_cmd.cmd = callBackCmd; + g_snd_cmd.param1 = 0; + g_snd_cmd.param2 = 0; + err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE); + } else { + g_macsnd_playing = 0; + } +} + +int x_snd_send_audio(byte *ptr, int in_size) +{ + SndCommand snd_cmd = {0}; + word32 *wptr, *macptr; + word32 *eptr; + int samps; + int i; + + samps = in_size / 4; + wptr = (word32 *)ptr; + macptr = (word32 *)g_macsnd_rebuf_ptr; + eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE]; + for(i = 0; i < samps; i++) { + *macptr++ = *wptr++; + if(macptr >= eptr) { + macptr = &g_macsnd_rebuf[0]; + } + } + + g_macsnd_rebuf_ptr = macptr; + + if(!g_macsnd_playing) { + mac_snd_callback(g_snd_channel_ptr, &snd_cmd); + } + + return in_size; +} + +void x_snd_child_init() +{ + OSStatus err; + + mac_printf("In mac child\n"); + fflush(stdout); + mac_printf("pid: %d\n", getpid()); + fflush(stdout); + + //return; + + //g_snd_channel_ptr = 0; + err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo, + NewSndCallBackUPP(mac_snd_callback)); + mac_printf("SndNewChannel ret: %d\n", (int)err); + fflush(stdout); + + memset(&g_snd_hdr, 0, sizeof(g_snd_hdr)); + g_snd_hdr.sampleSize = 16; + g_snd_hdr.numChannels = 2; + g_sound.g_audio_rate = 44100; + g_snd_hdr.sampleRate = g_sound.g_audio_rate << 16; + g_snd_hdr.numFrames = 0; // will be set in mac_send_audio + g_snd_hdr.encode = extSH; + g_snd_hdr.baseFrequency = 0; + g_snd_hdr.samplePtr = 0; + + set_audio_rate(g_sound.g_audio_rate); + + mac_printf("End of child_sound_init_mac\n"); + fflush(stdout); +} + +void x_snd_init(word32 *shmaddr) +{ + g_macsnd_rebuf_cur = &g_macsnd_rebuf[0]; + g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0]; + mac_printf("macsnd_init called\n"); + //child_sound_loop(-1, -1, shmaddr); +} + +void x_snd_shutdown() +{ +} + + + +word32* x_sound_allocate(int size) +{ + word32 *shmaddr; + shmaddr = (word32*)malloc(size); + memset(shmaddr, 0, size); + return shmaddr; +} + + +void x_sound_free(word32* _mem) +{ + if (_mem) + free(_mem); + +} + +void x_async_sound_init() +{ +} + +void x_async_snd_shutdown() +{ +} diff --git a/kegs/OSX/scc_macdriver.cpp b/kegs/OSX/scc_macdriver.cpp new file mode 100644 index 0000000..39f6993 --- /dev/null +++ b/kegs/OSX/scc_macdriver.cpp @@ -0,0 +1,205 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../src/defc.h" +#include "../src/scc.h" + +#ifndef _WIN32 +# include +#endif + +//extern Scc g_scc.scc_stat[2]; +//extern word32 g_c025_val; + +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) +int +scc_serial_mac_init(int port) +{ + char str_buf[1024]; + Scc *scc_ptr; + int state; + int fd; + + scc_ptr = &(g_scc.scc_stat[port]); + + scc_ptr->state = 0; /* mark as uninitialized */ + + /*sprintf(&str_buf[0], "/dev/tty.USA19QW11P1.1"); */ + sprintf(&str_buf[0], "/dev/tty.USA19H181P1.1"); + /* HACK: fix this... */ + + fd = open(&str_buf[0], O_RDWR | O_NONBLOCK); + + scc_ptr->host_handle = (void *)fd; + scc_ptr->host_handle2 = 0; + + printf("scc_serial_mac_init %d called, fd: %d\n", port, fd); + + if(fd < 0) { + scc_ptr->host_handle = (void *)-1; + return -1; + } + + scc_serial_mac_change_params(port); + + state = 2; /* raw serial */ + scc_ptr->state = state; + + return state; +} + +void +scc_serial_mac_change_params(int port) +{ + struct termios termios_buf; + Scc *scc_ptr; + int fd; + int csz; + int ret; + + scc_ptr = &(g_scc.scc_stat[port]); + + fd = (intptr_t)scc_ptr->host_handle; + printf("scc_serial_mac_change_parms port: %d, fd: %d\n", port, fd); + if(fd <= 0) { + return; + } + + ret = tcgetattr(fd, &termios_buf); + if(ret != 0) { + printf("tcgetattr port%d ret: %d\n", port, ret); + } + +#if 1 + printf("baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n", + (int)termios_buf.c_ispeed, (int)termios_buf.c_iflag, + (int)termios_buf.c_oflag, (int)termios_buf.c_cflag, + (int)termios_buf.c_lflag); +#endif + + memset(&termios_buf, 0, sizeof(struct termios)); + cfmakeraw(&termios_buf); + cfsetspeed(&termios_buf, scc_ptr->baud_rate); + + csz = scc_ptr->char_size; + termios_buf.c_cflag = CREAD | CLOCAL; + termios_buf.c_cflag |= (csz == 5) ? CS5 : + (csz == 6) ? CS6 : + (csz == 7) ? CS7 : + CS8; + switch((scc_ptr->reg[4] >> 2) & 0x3) { + case 2: // 1.5 stop bits + termios_buf.c_cflag |= CSTOPB; /* no 1.5 stop bit setting.*/ + break; + case 3: // 2 stop bits + termios_buf.c_cflag |= CSTOPB; + break; + } + + switch((scc_ptr->reg[4]) & 0x3) { + case 1: // Odd parity + termios_buf.c_cflag |= (PARENB | PARODD); + break; + case 3: // Even parity + termios_buf.c_cflag |= PARENB; + break; + } + + /* always enabled DTR and RTS control */ + termios_buf.c_cflag |= CDTR_IFLOW | CRTS_IFLOW; + + printf("fd: %d, baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n", + fd, (int)termios_buf.c_ispeed, (int)termios_buf.c_iflag, + (int)termios_buf.c_oflag, (int)termios_buf.c_cflag, + (int)termios_buf.c_lflag); + ret = tcsetattr(fd, TCSANOW, &termios_buf); + if(ret != 0) { + printf("tcsetattr ret: %d\n", ret); + } +} + +void +scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs) +{ + byte tmp_buf[256]; + Scc *scc_ptr; + int fd; + int i; + size_t ret; + + scc_ptr = &(g_scc.scc_stat[port]); + + fd = (intptr_t)scc_ptr->host_handle; + if(fd <= 0) { + return; + } + + /* Try reading some bytes */ + space_left = MIN(space_left, 256); + ret = read(fd, tmp_buf, space_left); + + if(ret > 0) { + for(i = 0; i < ret; i++) { + scc_add_to_readbuf(port, tmp_buf[i], dcycs); + } + } + +} + +void +scc_serial_mac_empty_writebuf(int port) +{ + Scc *scc_ptr; + int fd; + int rdptr; + int wrptr; + int done; + size_t ret; + int len; + + scc_ptr = &(g_scc.scc_stat[port]); + + fd = (intptr_t)scc_ptr->host_handle; + if(fd <= 0) { + return; + } + + /* Try writing some bytes */ + done = 0; + while(!done) { + rdptr = scc_ptr->out_rdptr; + wrptr = scc_ptr->out_wrptr; + if(rdptr == wrptr) { + //printf("...rdptr == wrptr\n"); + done = 1; + break; + } + len = wrptr - rdptr; + if(len < 0) { + len = SCC_OUTBUF_SIZE - rdptr; + } + if(len > 32) { + len = 32; + } + if(len <= 0) { + done = 1; + break; + } + ret = write(fd, &(scc_ptr->out_buf[rdptr]), len); + + if(ret <= 0) { + done = 1; + break; + } else { + rdptr = rdptr + ret; + if(rdptr >= SCC_OUTBUF_SIZE) { + rdptr = rdptr - SCC_OUTBUF_SIZE; + } + scc_ptr->out_rdptr = rdptr; + } + } +} +#endif /* MAC */ diff --git a/kegs/Src/16inst_c.h b/kegs/Src/16inst_c.h new file mode 100644 index 0000000..8ea653f --- /dev/null +++ b/kegs/Src/16inst_c.h @@ -0,0 +1,3001 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef ASM +# ifdef INCLUDE_RCSID_S + .stringz "@(#)$KmKId: instable.h,v 1.104 2004-10-05 20:12:08-04 kentd Exp $" +# endif +#endif + +case 0x00: /* brk */ +#ifdef ASM + ldb 1(scratch1),ret0 + ldil l%g_sim65816.g_testing,arg3 + ldil l%g_sim65816.g_num_brk,arg1 + ldw r%g_sim65816.g_testing(arg3),arg3 + INC_KPC_2; + ldw r%g_sim65816.g_num_brk(arg1),arg2 + comib,<> 0,arg3,brk_testing_16 + extru kpc,31,16,arg0 + addi 1,arg2,arg2 + bb,>= psr,23,brk_native_16 + stw arg2,r%g_sim65816.g_num_brk(arg1) + + bl push_16,link + nop + + bl push_8,link + extru psr,31,8,arg0 ;B bit already on in PSR + + ldil l%0xfffe,arg0 + bl get_mem_long_16,link + ldo r%0xfffe(arg0),arg0 + + zdep ret0,31,16,kpc ;set kbank to 0 + +#if 0 + bl set_halt_act,link + ldi 3,arg0 +#endif + + + ldi 0,dbank ;clear dbank in emul mode + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + + +brk_native_16 + stw arg0,STACK_SAVE_COP_ARG0(sp) + bl push_8,link + extru kpc,15,8,arg0 + + bl push_16,link + ldw STACK_SAVE_COP_ARG0(sp),arg0 + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xffe6,arg0 + bl get_mem_long_16,link + ldo r%0xffe6(arg0),arg0 + + zdep ret0,31,16,kpc ;zero kbank in kpc + +#if 0 +#endif + bl set_halt_act,link + ldi 3,arg0 + + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + +brk_testing_16 + DEC_KPC2; + CYCLES_PLUS_2 + b dispatch_done + depi RET_BREAK,3,4,ret0 + +#else + GET_1BYTE_ARG; + if(g_sim65816.g_testing) { + CYCLES_PLUS_2; + FINISH(RET_BREAK, arg); + } + g_sim65816.g_num_brk++; + INC_KPC_2; + if(psr & 0x100) { + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xfffe, kpc, 0); + dbank = 0; + } else { + PUSH8(kpc >> 16); + PUSH16(kpc); + PUSH8(psr & 0xff); + GET_MEMORY16(0xffe6, kpc, 0); + halt_printf("Halting for native break!\n"); + } + kpc = kpc & 0xffff; + psr |= 0x4; + psr &= ~(0x8); +#endif + + break; +case 0x01: /* ORA (Dloc,X) */ +/* called with arg = val to ORA in */ + GET_DLOC_X_IND_RD(); + ORA_INST(); + + break; +case 0x02: /* COP */ +#ifdef ASM + ldil l%g_sim65816.g_num_cop,arg1 + INC_KPC_2; + ldw r%g_sim65816.g_num_cop(arg1),arg2 + extru kpc,31,16,arg0 + addi 1,arg2,arg2 + bb,>= psr,23,cop_native_16 + stw arg2,r%g_sim65816.g_num_cop(arg1) + + bl push_16,link + nop + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xfff4,arg0 + bl get_mem_long_16,link + ldo r%0xfff4(arg0),arg0 + + ldi 0,dbank ;clear dbank in emul mode + zdep ret0,31,16,kpc ;clear kbank + + bl set_halt_act,link + ldi 3,arg0 + + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + +cop_native_16 + stw arg0,STACK_SAVE_COP_ARG0(sp) + bl push_8,link + extru kpc,15,8,arg0 + + bl push_16,link + ldw STACK_SAVE_COP_ARG0(sp),arg0 + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xffe4,arg0 + bl get_mem_long_16,link + ldo r%0xffe4(arg0),arg0 + + zdep ret0,31,16,kpc ;clear kbank + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + + +#else + + GET_1BYTE_ARG + if (arg == 0x93) + { + INC_KPC_2; + int process_marinetti_command(int _command,word32* param, word32& _regx, word32& _regy); + + + int p = xreg*0x10000 + yreg; + word32* ptr = (word32*)&g_memory_ptr[p]; + + int ret = process_marinetti_command(acc,ptr,xreg,yreg); + if (ret) + { + psr |= 1; // SEC + acc = ret; + } + else + { + psr &= ~(0x01); + acc = 0; + } + } + else + if (arg == 0x84) + { + int p = xreg*0x10000 + yreg; + const char* ptr = (const char*)&g_memory_ptr[p]; + printf("%s\n",ptr); + INC_KPC_2; + } + else + { + + g_sim65816.g_num_cop++; + INC_KPC_2; + if(psr & 0x100) + { + halt_printf("Halting for emul COP at %04x\n", kpc); + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xfff4, kpc, 0); + dbank = 0; + } else { + + PUSH8(kpc >> 16); + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xffe4, kpc, 0); + + } + kpc = kpc & 0xffff; + + psr |= 4; + psr &= ~(0x8); +} +#endif + + break; +case 0x03: /* ORA Disp8,S */ + GET_DISP8_S_RD(); + ORA_INST(); + + break; +case 0x04: /* TSB Dloc */ + GET_DLOC_RD(); + TSB_INST(1); + + break; +case 0x05: /* ORA Dloc */ + GET_DLOC_RD(); + ORA_INST(); + + break; +case 0x06: /* ASL Dloc */ + GET_DLOC_RD(); + ASL_INST(1); + + break; +case 0x07: /* ORA [Dloc] */ + GET_DLOC_L_IND_RD(); + ORA_INST(); + + break; +case 0x08: /* PHP */ +#ifdef ASM + dep neg,24,1,psr + ldil l%dispatch,link + INC_KPC_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + ldo r%dispatch(link),link + b push_8 + extru psr,31,8,arg0 +#else + INC_KPC_1; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + PUSH8(psr); +#endif + + break; +case 0x09: /* ORA #imm */ + GET_IMM_MEM(); + ORA_INST(); + + break; +case 0x0a: /* ASL a */ +#ifdef ASM +# ifdef ACC8 + ldi 0xff,scratch1 + sh1add acc,0,scratch3 + INC_KPC_1 + extru scratch3,24,1,neg + and scratch3,scratch1,zero + extru scratch3,23,1,scratch2 + dep zero,31,8,acc + b dispatch + dep scratch2,31,1,psr /* set carry */ +# else + zdepi -1,31,16,scratch1 + sh1add acc,0,scratch3 + INC_KPC_1 + extru scratch3,16,1,neg + and scratch3,scratch1,zero + extru scratch3,15,1,scratch2 + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; + tmp1 = acc + acc; +# ifdef ACC8 + SET_CARRY8(tmp1); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + SET_CARRY16(tmp1); + acc = tmp1 & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x0b: /* PHD */ +#ifdef ASM + ldil l%dispatch,link + extru direct,31,16,arg0 + INC_KPC_1 + b push_16_unsafe + ldo r%dispatch(link),link +#else + INC_KPC_1; + PUSH16_UNSAFE(direct); +#endif + + break; +case 0x0c: /* TSB abs */ + GET_ABS_RD(); + TSB_INST(0); + + break; +case 0x0d: /* ORA abs */ + GET_ABS_RD(); + ORA_INST(); + + break; +case 0x0e: /* ASL abs */ + GET_ABS_RD(); + ASL_INST(0); + + break; +case 0x0f: /* ORA long */ + GET_LONG_RD(); + ORA_INST(); + + + break; +case 0x10: /* BPL disp8 */ +#ifdef ASM + COND_BR1 + comib,<> 0,neg,inst10_2_16 + COND_BR2 + +inst10_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(neg == 0); +#endif + + break; +case 0x11: /* ORA (Dloc),y */ + GET_DLOC_IND_Y_RD(); + ORA_INST(); + + break; +case 0x12: /* ORA (Dloc) */ + GET_DLOC_IND_RD(); + ORA_INST(); + + break; +case 0x13: /* ORA (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + ORA_INST(); + + break; +case 0x14: /* TRB Dloc */ + GET_DLOC_RD(); + TRB_INST(1); + + break; +case 0x15: /* ORA Dloc,x */ + GET_DLOC_X_RD(); + ORA_INST(); + + break; +case 0x16: /* ASL Dloc,X */ + GET_DLOC_X_RD(); + ASL_INST(1); + + break; +case 0x17: /* ORA [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + ORA_INST(); + + break; +case 0x18: /* CLC */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,31,1,psr /* clear carry */ +#else + psr = psr & (~1); + INC_KPC_1; +#endif + + break; +case 0x19: /* ORA abs,y */ + GET_ABS_Y_RD(); + ORA_INST(); + + + break; +case 0x1a: /* INC a */ +#ifdef ASM +# ifdef ACC8 + ldi 0xff,scratch2 + addi 1,acc,scratch1 + extru scratch1,24,1,neg + INC_KPC_1 + extru scratch1,31,8,zero + b dispatch + dep zero,31,8,acc +# else + zdepi -1,31,16,scratch2 + addi 1,acc,scratch1 + extru scratch1,16,1,neg + INC_KPC_1 + extru scratch1,31,16,zero + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + acc = (acc & 0xff00) | ((acc + 1) & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + acc = (acc + 1) & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x1b: /* TCS */ +#ifdef ASM + copy acc,stack + extru,= psr,23,1,0 /* in emulation mode, stack page 1 */ + depi 1,23,24,stack + INC_KPC_1 + b dispatch + nop +#else + stack = acc; + INC_KPC_1; + if(psr & 0x100) { + stack = (stack & 0xff) + 0x100; + } +#endif + + break; +case 0x1c: /* TRB Abs */ + GET_ABS_RD(); + TRB_INST(0); + + break; +case 0x1d: /* ORA Abs,X */ + GET_ABS_X_RD(); + ORA_INST(); + + break; +case 0x1e: /* ASL Abs,X */ + GET_ABS_X_RD_WR(); + ASL_INST(0); + + break; +case 0x1f: /* ORA Long,X */ + GET_LONG_X_RD(); + ORA_INST(); + + + break; +case 0x20: /* JSR abs */ +#ifdef ASM + addi 2,kpc,arg0 + ldb 1(scratch1),scratch2 + CYCLES_PLUS_2 + ldb 2(scratch1),scratch1 + ldil l%dispatch,link + extru arg0,31,16,arg0 + ldo r%dispatch(link),link + dep scratch2,31,8,kpc + b push_16 + dep scratch1,23,8,kpc +#else + GET_2BYTE_ARG; + INC_KPC_2; + PUSH16(kpc); + kpc = (kpc & 0xff0000) + arg; + CYCLES_PLUS_2; +#endif + + break; +case 0x21: /* AND (Dloc,X) */ +/* called with arg = val to AND in */ + GET_DLOC_X_IND_RD(); + AND_INST(); + + break; +case 0x22: /* JSL Long */ +#ifdef ASM + INC_KPC_3 + ldb 3(scratch1),scratch2 + copy kpc,arg0 + ldb 1(scratch1),kpc + ldb 2(scratch1),scratch1 + CYCLES_PLUS_3 + dep scratch2,15,8,kpc + stw scratch2,STACK_SAVE_INSTR_TMP1(sp) + bl push_24_unsafe,link + dep scratch1,23,8,kpc + + b dispatch + nop +#else + GET_3BYTE_ARG; + tmp1 = arg; + CYCLES_PLUS_3; + INC_KPC_3; + PUSH24_UNSAFE(kpc); + kpc = tmp1 & 0xffffff; +#endif + + break; +case 0x23: /* AND Disp8,S */ +/* called with arg = val to AND in */ + GET_DISP8_S_RD(); + AND_INST(); + + break; +case 0x24: /* BIT Dloc */ + GET_DLOC_RD(); + BIT_INST(); + + break; +case 0x25: /* AND Dloc */ +/* called with arg = val to AND in */ + GET_DLOC_RD(); + AND_INST(); + + break; +case 0x26: /* ROL Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + ROL_INST(1); + + break; +case 0x27: /* AND [Dloc] */ + GET_DLOC_L_IND_RD(); + AND_INST(); + + break; +case 0x28: /* PLP */ +#ifdef ASM + bl pull_8,link + ldi 0,zero + + extru psr,27,2,scratch2 /* save old x & m */ + dep ret0,31,8,psr + CYCLES_PLUS_1 + INC_KPC_1 + extru,<> ret0,30,1,0 + ldi 1,zero + copy scratch2,arg0 + b update_system_state + extru ret0,24,1,neg +#else + PULL8(tmp1); + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_1; + psr = (psr & ~0xff) | (tmp1 & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + + break; +case 0x29: /* AND #imm */ + GET_IMM_MEM(); + AND_INST(); + + break; +case 0x2a: /* ROL a */ +#ifdef ASM +# ifdef ACC8 + extru psr,31,1,scratch2 + ldi 0xff,scratch1 + sh1add acc,scratch2,scratch3 + INC_KPC_1 + extru scratch3,24,1,neg + and scratch3,scratch1,zero + extru scratch3,23,1,scratch2 + dep zero,31,8,acc + b dispatch + dep scratch2,31,1,psr /* set carry */ +# else + extru psr,31,1,scratch2 + INC_KPC_1 + sh1add acc,scratch2,scratch3 + zdepi -1,31,16,scratch1 + extru scratch3,16,1,neg + and scratch3,scratch1,zero + extru scratch3,15,1,scratch2 + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) << 1) + (psr & 1); + SET_CARRY8(tmp1); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc << 1) + (psr & 1); + SET_CARRY16(tmp1); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x2b: /* PLD */ +#ifdef ASM + INC_KPC_1 + bl pull_16_unsafe,link + CYCLES_PLUS_1 + extru ret0,31,16,direct + extru ret0,16,1,neg + b dispatch + copy direct,zero +#else + INC_KPC_1; + PULL16_UNSAFE(direct); + CYCLES_PLUS_1; + SET_NEG_ZERO16(direct); +#endif + + break; +case 0x2c: /* BIT abs */ + GET_ABS_RD(); + BIT_INST(); + + break; +case 0x2d: /* AND abs */ + GET_ABS_RD(); + AND_INST(); + + break; +case 0x2e: /* ROL abs */ + GET_ABS_RD(); + ROL_INST(0); + + break; +case 0x2f: /* AND long */ + GET_LONG_RD(); + AND_INST(); + + + break; +case 0x30: /* BMI disp8 */ +#ifdef ASM + COND_BR1 + comib,= 0,neg,inst30_2_16 + COND_BR2 + +inst30_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(neg); +#endif + + break; +case 0x31: /* AND (Dloc),y */ + GET_DLOC_IND_Y_RD(); + AND_INST(); + + break; +case 0x32: /* AND (Dloc) */ + GET_DLOC_IND_RD(); + AND_INST(); + + break; +case 0x33: /* AND (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + AND_INST(); + + break; +case 0x34: /* BIT Dloc,x */ + GET_DLOC_X_RD(); + BIT_INST(); + + break; +case 0x35: /* AND Dloc,x */ + GET_DLOC_X_RD(); + AND_INST(); + + break; +case 0x36: /* ROL Dloc,X */ + GET_DLOC_X_RD(); + ROL_INST(1); + + break; +case 0x37: /* AND [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + AND_INST(); + + break; +case 0x38: /* SEC */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,31,1,psr /* set carry */ +#else + psr = psr | 1; + INC_KPC_1; +#endif + + break; +case 0x39: /* AND abs,y */ + GET_ABS_Y_RD(); + AND_INST(); + + break; +case 0x3a: /* DEC a */ +#ifdef ASM +# ifdef ACC8 + addi -1,acc,scratch1 + extru scratch1,24,1,neg + INC_KPC_1 + extru scratch1,31,8,zero + b dispatch + dep zero,31,8,acc +# else + addi -1,acc,scratch1 + extru scratch1,16,1,neg + INC_KPC_1 + extru scratch1,31,16,zero + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + acc = (acc & 0xff00) | ((acc - 1) & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + acc = (acc - 1) & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x3b: /* TSC */ +/* set N,Z according to 16 bit acc */ +#ifdef ASM + copy stack,acc + extru stack,16,1,neg + INC_KPC_1 + b dispatch + extru acc,31,16,zero +#else + INC_KPC_1; + acc = stack; + SET_NEG_ZERO16(acc); +#endif + + break; +case 0x3c: /* BIT Abs,x */ + GET_ABS_X_RD(); + BIT_INST(); + + break; +case 0x3d: /* AND Abs,X */ + GET_ABS_X_RD(); + AND_INST(); + + break; +case 0x3e: /* ROL Abs,X */ + GET_ABS_X_RD_WR(); + ROL_INST(0); + + break; +case 0x3f: /* AND Long,X */ + GET_LONG_X_RD(); + AND_INST(); + + + break; +case 0x40: /* RTI */ +#ifdef ASM + bb,>= psr,23,rti_native_16 + CYCLES_PLUS_1 +/* emulation */ + bl pull_24,link + ldi 0,zero + + extru psr,27,2,scratch2 + extru ret0,23,16,scratch3 + copy scratch2,arg0 + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + + extru ret0,24,1,neg + b update_system_state + dep scratch3,31,16,kpc + +rti_native_16 + bl pull_8,link + ldi 0,zero + + copy ret0,scratch1 + extru ret0,24,1,neg + dep ret0,31,8,scratch1 + bl pull_24,link + stw scratch1,STACK_SAVE_INSTR_TMP1(sp) + + extru psr,27,2,scratch2 + ldw STACK_SAVE_INSTR_TMP1(sp),psr + extru ret0,31,24,kpc + extru,<> psr,30,1,0 + ldi 1,zero + + b update_system_state_and_change_kbank + copy scratch2,arg0 +#else + CYCLES_PLUS_1 + if(psr & 0x100) { + PULL24(tmp1); + kpc = (kpc & 0xff0000) + ((tmp1 >> 8) & 0xffff); + tmp2 = psr; + psr = (psr & ~0xff) + (tmp1 & 0xff); + neg = (psr >> 7) & 1; + zero = !(psr & 2); + UPDATE_PSR(psr, tmp2); + } else { + PULL8(tmp1); + tmp2 = psr; + psr = (tmp1 & 0xff); + neg = (psr >> 7) & 1; + zero = !(psr & 2); + PULL24(kpc); + UPDATE_PSR(psr, tmp2); + } +#endif + + + break; +case 0x41: /* EOR (Dloc,X) */ +/* called with arg = val to EOR in */ + GET_DLOC_X_IND_RD(); + EOR_INST(); + + break; +case 0x42: /* WDM */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_5 + CYCLES_PLUS_2 + INC_KPC_2 + b dispatch_done + depi RET_WDM,3,4,ret0 +#else + GET_1BYTE_ARG; + INC_KPC_2; + CYCLES_PLUS_5; + CYCLES_PLUS_2; + FINISH(RET_WDM, arg & 0xff); +#endif + + break; +case 0x43: /* EOR Disp8,S */ +/* called with arg = val to EOR in */ + GET_DISP8_S_RD(); + EOR_INST(); + + break; +case 0x44: /* MVP */ +#ifdef ASM + ldb 2(scratch1),scratch2 /* src bank */ + bb,< psr,23,inst44_notnat_16 + ldb 1(scratch1),dbank /* dest bank */ + bb,< psr,27,inst44_notnat_16 + stw scratch2,STACK_SRC_BANK(sp) + +inst44_loop_16 + CYCLES_PLUS_1 + ldw STACK_SRC_BANK(sp),scratch2 + copy xreg,arg0 + + bl get_mem_long_8,link + dep scratch2,15,8,arg0 +/* got byte */ + copy ret0,arg1 + copy yreg,arg0 + bl set_mem_long_8,link + dep dbank,15,8,arg0 +/* wrote byte, dec acc */ + CYCLES_PLUS_2 + fldds 0(fcycles_stop_ptr),fcycles_stop + addi -1,xreg,xreg + zdepi -1,31,16,scratch2 + addi -1,yreg,yreg + addi -1,acc,acc + fcmp,<,dbl fcycles,fcycles_stop + and xreg,scratch2,xreg + extrs acc,31,16,scratch1 + and yreg,scratch2,yreg + + comib,= -1,scratch1,inst44_done_16 + and acc,scratch2,acc + + ftest + b inst44_out_of_time_16 + + CYCLES_PLUS_2 + b inst44_loop_16 + nop + +/* get here if done */ +inst44_done_16 + INC_KPC_3 + b dispatch + nop + +inst44_notnat_16 + copy dbank,ret0 + dep scratch2,23,8,ret0 + CYCLES_PLUS_3 + depi RET_MVP,3,4,ret0 + b dispatch_done + CYCLES_PLUS_2 + +inst44_out_of_time_16 +/* cycle have gone positive, just get out, do not update kpc */ + b,n dispatch +#else + GET_2BYTE_ARG; + /* arg & 0xff = dest bank, arg & 0xff00 = src bank */ + + if(psr & 0x110) { + // OG MVP should work even with no native mode - keep the warning though + printf("MVP but not native m or x!\n"); + /* + halt_printf("MVP but not native m or x!\n"); + break; + */ + } + CYCLES_MINUS_2 + dbank = arg & 0xff; + tmp1 = (arg >> 8) & 0xff; + while(1) { + CYCLES_PLUS_3; + GET_MEMORY8((tmp1 << 16) + xreg, arg); + SET_MEMORY8((dbank << 16) + yreg, arg); + CYCLES_PLUS_2; + xreg = (xreg - 1) & 0xffff; + yreg = (yreg - 1) & 0xffff; + acc = (acc - 1) & 0xffff; + if(acc == 0xffff) { + INC_KPC_3; + break; + } + if(fcycles >= g_sim65816.g_fcycles_stop) { + break; + } + } +#endif + + + break; +case 0x45: /* EOR Dloc */ +/* called with arg = val to EOR in */ + GET_DLOC_RD(); + EOR_INST(); + + break; +case 0x46: /* LSR Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + LSR_INST(1); + + break; +case 0x47: /* EOR [Dloc] */ + GET_DLOC_L_IND_RD(); + EOR_INST(); + + break; +case 0x48: /* PHA */ +#ifdef ASM +# ifdef ACC8 + INC_KPC_1 + ldil l%dispatch,link + extru acc,31,8,arg0 + b push_8 + ldo r%dispatch(link),link +# else + INC_KPC_1 + ldil l%dispatch,link + extru acc,31,16,arg0 + b push_16 + ldo r%dispatch(link),link +# endif +#else + INC_KPC_1; +# ifdef ACC8 + PUSH8(acc); +# else + PUSH16(acc); +# endif +#endif + + break; +case 0x49: /* EOR #imm */ + GET_IMM_MEM(); + EOR_INST(); + + break; +case 0x4a: /* LSR a */ +#ifdef ASM +# ifdef ACC8 + extru acc,31,1,scratch2 + INC_KPC_1 + extru acc,30,7,zero + ldi 0,neg + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,8,acc +# else + extru acc,31,1,scratch2 + INC_KPC_1 + extru acc,30,15,zero + ldi 0,neg + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) >> 1); + SET_CARRY8(acc << 8); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc >> 1); + SET_CARRY8((acc << 8)); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x4b: /* PHK */ +#ifdef ASM + ldil l%dispatch,link + extru kpc,15,8,arg0 + INC_KPC_1 + b push_8 + ldo r%dispatch(link),link +#else + PUSH8(kpc >> 16); + INC_KPC_1; +#endif + + break; +case 0x4c: /* JMP abs */ +#ifdef ASM + ldb 1(scratch1),scratch2 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + dep scratch2,31,8,kpc + b dispatch + dep scratch1,23,8,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + kpc = (kpc & 0xff0000) + arg; +#endif + + + break; +case 0x4d: /* EOR abs */ + GET_ABS_RD(); + EOR_INST(); + + break; +case 0x4e: /* LSR abs */ + GET_ABS_RD(); + LSR_INST(0); + + break; +case 0x4f: /* EOR long */ + GET_LONG_RD(); + EOR_INST(); + + + break; +case 0x50: /* BVC disp8 */ +#ifdef ASM + COND_BR1 + bb,< psr,25,inst50_2_16 + COND_BR2 + +inst50_2_16 + COND_BR_UNTAKEN + +#else + BRANCH_DISP8((psr & 0x40) == 0); +#endif + + break; +case 0x51: /* EOR (Dloc),y */ + GET_DLOC_IND_Y_RD(); + EOR_INST(); + + break; +case 0x52: /* EOR (Dloc) */ + GET_DLOC_IND_RD(); + EOR_INST(); + + break; +case 0x53: /* EOR (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + EOR_INST(); + + break; +case 0x54: /* MVN */ +#ifdef ASM + ldb 2(scratch1),scratch2 /* src bank */ + bb,< psr,23,inst54_notnat_16 + ldb 1(scratch1),dbank /* dest bank */ + bb,< psr,27,inst54_notnat_16 + stw scratch2,STACK_SRC_BANK(sp) + +/* even in 8bit acc mode, use 16-bit accumulator! */ + +inst54_loop_16 + CYCLES_PLUS_1 + ldw STACK_SRC_BANK(sp),scratch2 + copy xreg,arg0 + + bl get_mem_long_8,link + dep scratch2,15,8,arg0 +/* got byte */ + copy ret0,arg1 + copy yreg,arg0 + bl set_mem_long_8,link + dep dbank,15,8,arg0 +/* wrote byte, dec acc */ + CYCLES_PLUS_2 + fldds 0(fcycles_stop_ptr),fcycles_stop + addi 1,xreg,xreg + zdepi -1,31,16,scratch2 + addi 1,yreg,yreg + addi -1,acc,acc + fcmp,<,dbl fcycles,fcycles_stop + and xreg,scratch2,xreg + extrs acc,31,16,scratch1 + and yreg,scratch2,yreg + + comib,= -1,scratch1,inst54_done_16 + and acc,scratch2,acc + ftest + b,n inst54_out_of_time_16 + + CYCLES_PLUS_2 + b inst54_loop_16 + nop + +/* get here if done */ +inst54_done_16 + INC_KPC_3 + b dispatch + nop + +inst54_out_of_time_16 +/* cycle have gone positive, just get out, don't update kpc */ + b,n dispatch + +inst54_notnat_16 + copy dbank,ret0 + dep scratch2,23,8,ret0 + CYCLES_PLUS_3 + depi RET_MVN,3,4,ret0 + b dispatch_done + CYCLES_PLUS_3 +#else + GET_2BYTE_ARG; + /* arg & 0xff = dest bank, arg & 0xff00 = src bank */ + if(psr & 0x110) { + // OG MVP should work even with no native mode - keep the warning though + printf("MVP but not native m or x!\n"); + /* + halt_printf("MVN but not native m or x!\n"); + break; + */ + } + CYCLES_MINUS_2; + dbank = arg & 0xff; + tmp1 = (arg >> 8) & 0xff; + while(1) { + CYCLES_PLUS_3; + GET_MEMORY8((tmp1 << 16) + xreg, arg); + SET_MEMORY8((dbank << 16) + yreg, arg); + CYCLES_PLUS_2; + xreg = (xreg + 1) & 0xffff; + yreg = (yreg + 1) & 0xffff; + acc = (acc - 1) & 0xffff; + if(acc == 0xffff) { + INC_KPC_3; + break; + } + if(fcycles >= g_sim65816.g_fcycles_stop) { + break; + } + } +#endif + + break; +case 0x55: /* EOR Dloc,x */ + GET_DLOC_X_RD(); + EOR_INST(); + + break; +case 0x56: /* LSR Dloc,X */ + GET_DLOC_X_RD(); + LSR_INST(1); + + break; +case 0x57: /* EOR [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + EOR_INST(); + + break; +case 0x58: /* CLI */ +#ifdef ASM + INC_KPC_1 + b check_irqs_pending /* check for ints pending! */ + depi 0,29,1,psr /* clear int disable */ +#else + psr = psr & (~4); + INC_KPC_1; + if(((psr & 0x4) == 0) && g_moremem.g_irq_pending) { + FINISH(RET_IRQ, 0); + } +#endif + + break; +case 0x59: /* EOR abs,y */ + GET_ABS_Y_RD(); + EOR_INST(); + + break; +case 0x5a: /* PHY */ +#ifdef ASM + INC_KPC_1 + ldil l%dispatch,link + bb,>= psr,27,phy_16_16 + ldo r%dispatch(link),link + + b push_8 + copy yreg,arg0 + +phy_16_16 + b push_16 + copy yreg,arg0 +#else + INC_KPC_1; + if(psr & 0x10) { + PUSH8(yreg); + } else { + PUSH16(yreg); + } +#endif + + break; +case 0x5b: /* TCD */ +#ifdef ASM + extru acc,31,16,direct + INC_KPC_1 + copy acc,zero + b dispatch + extru acc,16,1,neg +#else + INC_KPC_1; + direct = acc; + SET_NEG_ZERO16(acc); +#endif + + break; +case 0x5c: /* JMP Long */ +#ifdef ASM + ldb 1(scratch1),kpc + ldb 2(scratch1),scratch2 + CYCLES_PLUS_1 + ldb 3(scratch1),arg0 /* new bank */ + dep scratch2,23,8,kpc + b dispatch + dep arg0,15,8,kpc +#else + GET_3BYTE_ARG; + CYCLES_PLUS_1; + kpc = arg; +#endif + + break; +case 0x5d: /* EOR Abs,X */ + GET_ABS_X_RD(); + EOR_INST(); + + break; +case 0x5e: /* LSR Abs,X */ + GET_ABS_X_RD_WR(); + LSR_INST(0); + + break; +case 0x5f: /* EOR Long,X */ + GET_LONG_X_RD(); + EOR_INST(); + + + break; +case 0x60: /* RTS */ +#ifdef ASM + bl pull_16,link + CYCLES_PLUS_2 +/* ret0 is new kpc-1 */ + addi 1,ret0,ret0 + b dispatch + dep ret0,31,16,kpc +#else + CYCLES_PLUS_2 + PULL16(tmp1); + kpc = (kpc & 0xff0000) + ((tmp1 + 1) & 0xffff); +#endif + + + break; +case 0x61: /* ADC (Dloc,X) */ +/* called with arg = val to ADC in */ + GET_DLOC_X_IND_RD(); + ADC_INST(); + + break; +case 0x62: /* PER */ +#ifdef ASM + ldb 1(scratch1),ret0 + INC_KPC_3 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_2 + ldil l%dispatch,link + dep scratch1,23,8,ret0 + ldo r%dispatch(link),link + add kpc,ret0,arg0 + b push_16_unsafe + extru arg0,31,16,arg0 +#else + GET_2BYTE_ARG; + CYCLES_PLUS_2; + INC_KPC_3; + PUSH16_UNSAFE(kpc + arg); +#endif + + break; +case 0x63: /* ADC Disp8,S */ +/* called with arg = val to ADC in */ + GET_DISP8_S_RD(); + ADC_INST(); + + break; +case 0x64: /* STZ Dloc */ + GET_DLOC_ADDR(); + STZ_INST(1); + + break; +case 0x65: /* ADC Dloc */ +/* called with arg = val to ADC in */ + GET_DLOC_RD(); + ADC_INST(); + + break; +case 0x66: /* ROR Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + ROR_INST(1); + + break; +case 0x67: /* ADC [Dloc] */ + GET_DLOC_L_IND_RD(); + ADC_INST(); + + break; +case 0x68: /* PLA */ +#ifdef ASM +# ifdef ACC8 + INC_KPC_1 + bl pull_8,link + CYCLES_PLUS_1 + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + dep ret0,31,8,acc +# else + INC_KPC_1 + bl pull_16,link + CYCLES_PLUS_1 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + extru ret0,31,16,acc +# endif +#else + INC_KPC_1; + CYCLES_PLUS_1; +# ifdef ACC8 + PULL8(tmp1); + acc = (acc & 0xff00) + tmp1; + SET_NEG_ZERO8(tmp1); +# else + PULL16(tmp1); + acc = tmp1; + SET_NEG_ZERO16(tmp1); +# endif +#endif + + + break; +case 0x69: /* ADC #imm */ + GET_IMM_MEM(); + ADC_INST(); + + break; +case 0x6a: /* ROR a */ +#ifdef ASM +# ifdef ACC8 + extru psr,31,1,neg + INC_KPC_1 + extru acc,30,7,zero + dep neg,24,1,zero + dep acc,31,1,psr /* set carry */ + b dispatch + dep zero,31,8,acc +# else + extru psr,31,1,neg + INC_KPC_1 + extru acc,30,15,zero + dep neg,16,1,zero + dep acc,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) >> 1) + ((psr & 1) << 7); + SET_CARRY8((acc << 8)); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc >> 1) + ((psr & 1) << 15); + SET_CARRY16((acc << 16)); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x6b: /* RTL */ +#ifdef ASM + bl pull_24,link + CYCLES_PLUS_1 +/* ret0 is new kpc-1 */ + copy ret0,kpc + addi 1,ret0,scratch1 + b dispatch + dep scratch1,31,16,kpc + +#else + CYCLES_PLUS_1; + PULL24(tmp1); + kpc = (tmp1 & 0xff0000) + ((tmp1 + 1) & 0xffff); +#endif + + break; +case 0x6c: /* JMP (abs) */ +#ifdef ASM + ldb 1(scratch1),arg0 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + bl get_mem_long_16,link + dep scratch1,23,8,arg0 +/* ret0 is addr to jump to */ + b dispatch + dep ret0,31,16,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + GET_MEMORY16(arg, tmp1, 1); + kpc = (kpc & 0xff0000) + tmp1; +#endif + + break; +case 0x6d: /* ADC abs */ + GET_ABS_RD(); + ADC_INST(); + + break; +case 0x6e: /* ROR abs */ + GET_ABS_RD(); + ROR_INST(0); + + break; +case 0x6f: /* ADC long */ + GET_LONG_RD(); + ADC_INST(); + + + break; +case 0x70: /* BVS disp8 */ +#ifdef ASM + COND_BR1 + bb,>= psr,25,inst70_2_16 + COND_BR2 + +inst70_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x40)); +#endif + + break; +case 0x71: /* ADC (Dloc),y */ + GET_DLOC_IND_Y_RD(); + ADC_INST(); + + break; +case 0x72: /* ADC (Dloc) */ + GET_DLOC_IND_RD(); + ADC_INST(); + + break; +case 0x73: /* ADC (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + ADC_INST(); + + break; +case 0x74: /* STZ Dloc,x */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_X_WR(); + STZ_INST(1); +#else + GET_1BYTE_ARG; + GET_DLOC_X_WR(); + STZ_INST(1); +#endif + + break; +case 0x75: /* ADC Dloc,x */ + GET_DLOC_X_RD(); + ADC_INST(); + + break; +case 0x76: /* ROR Dloc,X */ + GET_DLOC_X_RD(); + ROR_INST(1); + + break; +case 0x77: /* ADC [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + ADC_INST(); + + break; +case 0x78: /* SEI */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,29,1,psr /* set int disable */ +#else + psr = psr | 4; + INC_KPC_1; +#endif + + break; +case 0x79: /* ADC abs,y */ + GET_ABS_Y_RD(); + ADC_INST(); + + break; +case 0x7a: /* PLY */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,inst7a_16bit_16 + nop + + bl pull_8,link + CYCLES_PLUS_1 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,yreg + +inst7a_16bit_16 + bl pull_16,link + CYCLES_PLUS_1 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,yreg + +#else + INC_KPC_1; + CYCLES_PLUS_1 + if(psr & 0x10) { + PULL8(yreg); + SET_NEG_ZERO8(yreg); + } else { + PULL16(yreg); + SET_NEG_ZERO16(yreg); + } +#endif + + break; +case 0x7b: /* TDC */ +#ifdef ASM + extru direct,31,16,zero + copy direct,acc + INC_KPC_1 + b dispatch + extru direct,16,1,neg +#else + INC_KPC_1; + acc = direct; + SET_NEG_ZERO16(direct); +#endif + + break; +case 0x7c: /* JMP (Abs,x) */ +/* always access kbank, xreg cannot wrap into next bank */ +#ifdef ASM + ldb 1(scratch1),ret0 + copy kpc,scratch2 + ldb 2(scratch1),scratch1 + dep xreg,31,16,scratch2 + CYCLES_PLUS_2 + dep scratch1,23,8,ret0 + add ret0,scratch2,arg0 + bl get_mem_long_16,link + extru arg0,31,24,arg0 + b dispatch + dep ret0,31,16,kpc +#else + GET_2BYTE_ARG; + arg = (kpc & 0xff0000) + ((xreg + arg) & 0xffff); + CYCLES_PLUS_2; + GET_MEMORY16(arg, tmp1, 1); + kpc = (kpc & 0xff0000) + tmp1; +#endif + + break; +case 0x7d: /* ADC Abs,X */ + GET_ABS_X_RD(); + ADC_INST(); + + break; +case 0x7e: /* ROR Abs,X */ + GET_ABS_X_RD_WR(); + ROR_INST(0); + + break; +case 0x7f: /* ADC Long,X */ + GET_LONG_X_RD(); + ADC_INST(); + + + break; +case 0x80: /* BRA */ +#ifdef ASM + COND_BR1 + COND_BR2 +#else + BRANCH_DISP8(1); +#endif + + + break; +case 0x81: /* STA (Dloc,X) */ + GET_DLOC_X_IND_ADDR(); + STA_INST(0); + + break; +case 0x82: /* BRL disp16 */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + addi 3,kpc,scratch2 + dep scratch1,23,8,ret0 + add ret0,scratch2,scratch2 + b dispatch + dep scratch2,31,16,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + kpc = (kpc & 0xff0000) + ((kpc + 3 + arg) & 0xffff); +#endif + + break; +case 0x83: /* STA Disp8,S */ + GET_DISP8_S_ADDR(); + STA_INST(1); + + break; +case 0x84: /* STY Dloc */ + GET_DLOC_ADDR(); + STY_INST(1); + + + break; +case 0x85: /* STA Dloc */ + GET_DLOC_ADDR(); + STA_INST(1); + + break; +case 0x86: /* STX Dloc */ + GET_DLOC_ADDR(); + STX_INST(1); + + + break; +case 0x87: /* STA [Dloc] */ + GET_DLOC_L_IND_ADDR(); + STA_INST(0); + + break; +case 0x88: /* DEY */ +#ifdef ASM + INC_KPC_1 + bb,< psr,27,inst88_8bit_16 + addi -1,yreg,yreg +/* 16 bit */ + extru yreg,31,16,zero + extru yreg,16,1,neg + b dispatch + copy zero,yreg + +inst88_8bit_16 + extru yreg,31,8,zero + extru yreg,24,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(yreg - 1, yreg); +#endif + + break; +case 0x89: /* BIT #imm */ +#ifdef ASM + GET_IMM_MEM(); +# ifdef ACC8 +/* Immediate BIT does not set condition flags */ + and acc,ret0,zero + b dispatch + extru zero,31,8,zero +# else + and acc,ret0,zero + b dispatch + extru zero,31,16,zero +# endif +#else + GET_IMM_MEM(); +# ifdef ACC8 + zero = (acc & arg) & 0xff; +# else + zero = (acc & arg) & 0xffff; +# endif +#endif + + break; +case 0x8a: /* TXA */ +#ifdef ASM +# ifdef ACC8 + extru xreg,31,8,zero + INC_KPC_1 + extru xreg,24,1,neg + b dispatch + dep zero,31,8,acc +# else + extru xreg,31,16,zero + INC_KPC_1 + extru xreg,16,1,neg + b dispatch + zdep zero,31,16,acc +# endif +#else + INC_KPC_1; + arg = xreg; + LDA_INST(); +#endif + + break; +case 0x8b: /* PHB */ +#ifdef ASM + ldil l%dispatch,link + extru dbank,31,8,arg0 + INC_KPC_1 + b push_8 + ldo r%dispatch(link),link +#else + INC_KPC_1; + PUSH8(dbank); +#endif + + break; +case 0x8c: /* STY abs */ + GET_ABS_ADDR(); + STY_INST(0); + + break; +case 0x8d: /* STA abs */ + GET_ABS_ADDR(); + STA_INST(0); + + break; +case 0x8e: /* STX abs */ + GET_ABS_ADDR(); + STX_INST(0); + + + break; +case 0x8f: /* STA long */ + GET_LONG_ADDR(); + STA_INST(0); + + + break; +case 0x90: /* BCC disp8 */ +#ifdef ASM + COND_BR1 + bb,< psr,31,inst90_2_16 + COND_BR2 + +inst90_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x01) == 0); +#endif + + + break; +case 0x91: /* STA (Dloc),y */ + GET_DLOC_IND_Y_ADDR_FOR_WR(); + STA_INST(0); + + break; +case 0x92: /* STA (Dloc) */ + GET_DLOC_IND_ADDR(); + STA_INST(0); + + break; +case 0x93: /* STA (Disp8,s),y */ + GET_DISP8_S_IND_Y_ADDR(); + STA_INST(0); + + break; +case 0x94: /* STY Dloc,x */ + GET_DLOC_X_ADDR(); + STY_INST(1); + + break; +case 0x95: /* STA Dloc,x */ + GET_DLOC_X_ADDR(); + STA_INST(1); + + break; +case 0x96: /* STX Dloc,Y */ + GET_DLOC_Y_ADDR(); + STX_INST(1); + + break; +case 0x97: /* STA [Dloc],Y */ + GET_DLOC_L_IND_Y_ADDR(); + STA_INST(0); + + break; +case 0x98: /* TYA */ +#ifdef ASM +# ifdef ACC8 + extru yreg,31,8,zero + INC_KPC_1 + extru yreg,24,1,neg + b dispatch + dep zero,31,8,acc +# else + extru yreg,31,16,zero + INC_KPC_1 + extru yreg,16,1,neg + b dispatch + zdep zero,31,16,acc +# endif +#else + INC_KPC_1; + arg = yreg; + LDA_INST(); +#endif + + break; +case 0x99: /* STA abs,y */ + GET_ABS_INDEX_ADDR_FOR_WR(yreg) + STA_INST(0); + + break; +case 0x9a: /* TXS */ +#ifdef ASM + copy xreg,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + INC_KPC_1 + b dispatch + nop +#else + stack = xreg; + if(psr & 0x100) { + stack = 0x100 | (stack & 0xff); + } + INC_KPC_1; +#endif + + + break; +case 0x9b: /* TXY */ +#ifdef ASM + extru xreg,24,1,neg + INC_KPC_1 + extru,<> psr,27,1,0 ;skip next if 8bit + extru xreg,16,1,neg + copy xreg,yreg + b dispatch + copy xreg,zero +#else + SET_INDEX_REG(xreg, yreg); + INC_KPC_1; +#endif + + + break; +case 0x9c: /* STZ Abs */ + GET_ABS_ADDR(); + STZ_INST(0); + + break; +case 0x9d: /* STA Abs,X */ + GET_ABS_INDEX_ADDR_FOR_WR(xreg); + STA_INST(0); + + break; +case 0x9e: /* STZ Abs,X */ + GET_ABS_INDEX_ADDR_FOR_WR(xreg); + STZ_INST(0); + + break; +case 0x9f: /* STA Long,X */ + GET_LONG_X_ADDR_FOR_WR(); + STA_INST(0); + + + break; +case 0xa0: /* LDY #imm */ +#ifdef ASM + INC_KPC_2 + bb,>= psr,27,insta0_16bit_16 + ldb 1(scratch1),zero + + extru zero,24,1,neg + b dispatch + copy zero,yreg +insta0_16bit_16 + ldb 2(scratch1),scratch1 + INC_KPC_1 + CYCLES_PLUS_1 + extru scratch1,24,1,neg + dep scratch1,23,8,zero + b dispatch + copy zero,yreg +#else + INC_KPC_2; + if((psr & 0x10) == 0) { + GET_2BYTE_ARG; + CYCLES_PLUS_1 + INC_KPC_1; + } else { + GET_1BYTE_ARG; + } + SET_INDEX_REG(arg, yreg); +#endif + + + break; +case 0xa1: /* LDA (Dloc,X) */ +/* called with arg = val to LDA in */ + GET_DLOC_X_IND_RD(); + LDA_INST(); + + break; +case 0xa2: /* LDX #imm */ +#ifdef ASM + ldb 1(scratch1),zero + bb,>= psr,27,insta2_16bit_16 + INC_KPC_2; + + extru zero,24,1,neg + b dispatch + copy zero,xreg +insta2_16bit_16 + ldb 2(scratch1),scratch1 + INC_KPC_1 + CYCLES_PLUS_1 + extru scratch1,24,1,neg + dep scratch1,23,8,zero + b dispatch + copy zero,xreg +#else + INC_KPC_2; + if((psr & 0x10) == 0) { + GET_2BYTE_ARG; + CYCLES_PLUS_1 + INC_KPC_1; + } else { + GET_1BYTE_ARG; + } + SET_INDEX_REG(arg, xreg); +#endif + + break; +case 0xa3: /* LDA Disp8,S */ +/* called with arg = val to LDA in */ + GET_DISP8_S_RD(); + LDA_INST(); + + break; +case 0xa4: /* LDY Dloc */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_WR() + b get_yreg_from_mem + nop +#else + C_LDY_DLOC(); +#endif + + break; +case 0xa5: /* LDA Dloc */ +/* called with arg = val to LDA in */ + GET_DLOC_RD(); + LDA_INST(); + + break; +case 0xa6: /* LDX Dloc */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_WR() + b get_xreg_from_mem + nop +#else + C_LDX_DLOC(); +#endif + + break; +case 0xa7: /* LDA [Dloc] */ + GET_DLOC_L_IND_RD(); + LDA_INST(); + + break; +case 0xa8: /* TAY */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,insta8_16bit_16 + extru acc,31,8,zero + + extru acc,24,1,neg + b dispatch + copy zero,yreg + +insta8_16bit_16 + extru acc,31,16,zero + extru acc,16,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(acc, yreg); +#endif + + break; +case 0xa9: /* LDA #imm */ + GET_IMM_MEM(); + LDA_INST(); + + break; +case 0xaa: /* TAX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instaa_16bit_16 + extru acc,31,8,zero + + extru acc,24,1,neg + b dispatch + copy zero,xreg + +instaa_16bit_16 + extru acc,31,16,zero + extru acc,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(acc, xreg); +#endif + + break; +case 0xab: /* PLB */ +#ifdef ASM + INC_KPC_1 + bl pull_8,link + CYCLES_PLUS_1 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,dbank +#else + INC_KPC_1; + CYCLES_PLUS_1 + PULL8(dbank); + SET_NEG_ZERO8(dbank); +#endif + + break; +case 0xac: /* LDY abs */ +#ifdef ASM + GET_ABS_ADDR() + b get_yreg_from_mem + nop +#else + C_LDY_ABS(); +#endif + + + break; +case 0xad: /* LDA abs */ + GET_ABS_RD(); + LDA_INST(); + + break; +case 0xae: /* LDX abs */ +#ifdef ASM + GET_ABS_ADDR() + b get_xreg_from_mem + nop +#else + C_LDX_ABS(); +#endif + + break; +case 0xaf: /* LDA long */ + GET_LONG_RD(); + LDA_INST(); + + + break; +case 0xb0: /* BCS disp8 */ +#ifdef ASM + COND_BR1 + bb,>= psr,31,instb0_2_16 + COND_BR2 + +instb0_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x01)); +#endif + + break; +case 0xb1: /* LDA (Dloc),y */ + GET_DLOC_IND_Y_RD(); + LDA_INST(); + + break; +case 0xb2: /* LDA (Dloc) */ + GET_DLOC_IND_RD(); + LDA_INST(); + + break; +case 0xb3: /* LDA (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + LDA_INST(); + + break; +case 0xb4: /* LDY Dloc,x */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_X_WR(); + b get_yreg_from_mem + nop +#else + C_LDY_DLOC_X(); +#endif + + break; +case 0xb5: /* LDA Dloc,x */ + GET_DLOC_X_RD(); + LDA_INST(); + + break; +case 0xb6: /* LDX Dloc,y */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_Y_WR(); + b get_xreg_from_mem + nop +#else + C_LDX_DLOC_Y(); +#endif + + break; +case 0xb7: /* LDA [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + LDA_INST(); + + break; +case 0xb8: /* CLV */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,25,1,psr /* clear overflow */ +#else + psr = psr & ~0x40; + INC_KPC_1; +#endif + + break; +case 0xb9: /* LDA abs,y */ + GET_ABS_Y_RD(); + LDA_INST(); + + break; +case 0xba: /* TSX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instba_16bit_16 + extru stack,31,8,zero + + extru stack,24,1,neg + b dispatch + copy zero,xreg +instba_16bit_16 + copy stack,zero + extru stack,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(stack, xreg); +#endif + + break; +case 0xbb: /* TYX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instbb_16bit_16 + copy yreg,xreg + +/* 8 bit */ + extru yreg,24,1,neg + b dispatch + copy yreg,zero +instbb_16bit_16 + extru yreg,16,1,neg + b dispatch + copy yreg,zero +#else + INC_KPC_1; + SET_INDEX_REG(yreg, xreg); +#endif + + break; +case 0xbc: /* LDY Abs,X */ +#ifdef ASM + GET_ABS_INDEX_ADDR_FOR_RD(xreg) + b get_yreg_from_mem + nop +#else + C_LDY_ABS_X(); +#endif + + break; +case 0xbd: /* LDA Abs,X */ + GET_ABS_X_RD(); + LDA_INST(); + + break; +case 0xbe: /* LDX Abs,y */ +#ifdef ASM + GET_ABS_INDEX_ADDR_FOR_RD(yreg) + b get_xreg_from_mem + nop +#else + C_LDX_ABS_Y(); +#endif + + break; +case 0xbf: /* LDA Long,X */ + GET_LONG_X_RD(); + LDA_INST(); + + + break; +case 0xc0: /* CPY #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + bb,>= psr,27,instc0_16bit_16 + INC_KPC_2; + CMP_INDEX_REG_MEAT8(yreg) +instc0_16bit_16 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + INC_KPC_1 + dep scratch1,23,8,ret0 + CMP_INDEX_REG_MEAT16(yreg) +#else + C_CPY_IMM(); +#endif + + + break; +case 0xc1: /* CMP (Dloc,X) */ +/* called with arg = val to CMP in */ + GET_DLOC_X_IND_RD(); + CMP_INST(); + + break; +case 0xc2: /* REP #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_2; + dep neg,24,1,psr + CYCLES_PLUS_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + andcm psr,ret0,ret0 + ldi 0,zero + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + b update_system_state + extru ret0,24,1,neg +#else + GET_1BYTE_ARG; + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_2; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + psr = psr & ~(arg & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + + break; +case 0xc3: /* CMP Disp8,S */ +/* called with arg = val to CMP in */ + GET_DISP8_S_RD(); + CMP_INST(); + + break; +case 0xc4: /* CPY Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + CMP_INDEX_REG_LOAD(instc4_16bit_16, yreg) +#else + C_CPY_DLOC(); +#endif + + + break; +case 0xc5: /* CMP Dloc */ + GET_DLOC_RD(); + CMP_INST(); + + break; +case 0xc6: /* DEC Dloc */ + GET_DLOC_RD(); + DEC_INST(1); + + break; +case 0xc7: /* CMP [Dloc] */ + GET_DLOC_L_IND_RD(); + CMP_INST(); + + break; +case 0xc8: /* INY */ +#ifdef ASM + INC_KPC_1 + addi 1,yreg,yreg + bb,>= psr,27,instc8_16bit_16 + extru yreg,31,8,zero + + extru yreg,24,1,neg + b dispatch + copy zero,yreg + +instc8_16bit_16 + extru yreg,31,16,zero + extru yreg,16,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(yreg + 1, yreg); +#endif + + break; +case 0xc9: /* CMP #imm */ + GET_IMM_MEM(); + CMP_INST(); + + break; +case 0xca: /* DEX */ +#ifdef ASM + INC_KPC_1 + addi -1,xreg,xreg + bb,>= psr,27,instca_16bit_16 + extru xreg,31,8,zero + + extru xreg,24,1,neg + b dispatch + copy zero,xreg + +instca_16bit_16 + extru xreg,31,16,zero + extru xreg,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(xreg - 1, xreg); +#endif + + break; +case 0xcb: /* WAI */ +#ifdef ASM + ldil l%g_sim65816.g_wait_pending,scratch1 + CYCLES_FINISH + ldi 1,scratch2 + b dispatch + stw scratch2,r%g_sim65816.g_wait_pending(scratch1) +#else + g_sim65816.g_wait_pending = 1; + CYCLES_FINISH +#endif + + break; +case 0xcc: /* CPY abs */ +#ifdef ASM + GET_ABS_ADDR() + CMP_INDEX_REG_LOAD(instcc_16bit_16, yreg) +#else + C_CPY_ABS(); +#endif + + + + + break; +case 0xcd: /* CMP abs */ + GET_ABS_RD(); + CMP_INST(); + + break; +case 0xce: /* DEC abs */ + GET_ABS_RD(); + DEC_INST(0); + + + break; +case 0xcf: /* CMP long */ + GET_LONG_RD(); + CMP_INST(); + + + break; +case 0xd0: /* BNE disp8 */ +#ifdef ASM + COND_BR1 + comib,= 0,zero,instd0_2_16 + COND_BR2 + +instd0_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(zero != 0); +#endif + + break; +case 0xd1: /* CMP (Dloc),y */ + GET_DLOC_IND_Y_RD(); + CMP_INST(); + + break; +case 0xd2: /* CMP (Dloc) */ + GET_DLOC_IND_RD(); + CMP_INST(); + + break; +case 0xd3: /* CMP (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + CMP_INST(); + + break; +case 0xd4: /* PEI Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + bl get_mem_long_16,link + CYCLES_PLUS_1 + +/* push ret0 */ + extru ret0,31,16,arg0 + ldil l%dispatch,link + b push_16_unsafe + ldo r%dispatch(link),link +#else + GET_DLOC_ADDR() + GET_MEMORY16(arg, arg, 1); + CYCLES_PLUS_1; + PUSH16_UNSAFE(arg); +#endif + + break; +case 0xd5: /* CMP Dloc,x */ + GET_DLOC_X_RD(); + CMP_INST(); + + break; +case 0xd6: /* DEC Dloc,x */ + GET_DLOC_X_RD(); + DEC_INST(1); + + break; +case 0xd7: /* CMP [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + CMP_INST(); + + break; +case 0xd8: /* CLD */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,28,1,psr /* clear decimal */ +#else + psr = psr & (~0x8); + INC_KPC_1; +#endif + + break; +case 0xd9: /* CMP abs,y */ + GET_ABS_Y_RD(); + CMP_INST(); + + break; +case 0xda: /* PHX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instda_16bit_16 + ldil l%dispatch,link + + extru xreg,31,8,arg0 + b push_8 + ldo r%dispatch(link),link + +instda_16bit_16 + extru xreg,31,16,arg0 + b push_16 + ldo r%dispatch(link),link +#else + INC_KPC_1; + if(psr & 0x10) { + PUSH8(xreg); + } else { + PUSH16(xreg); + } +#endif + + break; +case 0xdb: /* STP */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_1 + b dispatch_done + depi RET_STP,3,4,ret0 +#else + CYCLES_FINISH + FINISH(RET_STP, 0); +#endif + + break; +case 0xdc: /* JML (Abs) */ +#ifdef ASM + ldb 1(scratch1),arg0 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + bl get_mem_long_24,link + dep scratch1,23,8,arg0 + + b dispatch + copy ret0,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + GET_MEMORY24(arg, kpc, 1); +#endif + + break; +case 0xdd: /* CMP Abs,X */ + GET_ABS_X_RD(); + CMP_INST(); + + break; +case 0xde: /* DEC Abs,X */ + GET_ABS_X_RD_WR(); + DEC_INST(0); + + break; +case 0xdf: /* CMP Long,X */ + GET_LONG_X_RD(); + CMP_INST(); + + + break; +case 0xe0: /* CPX #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + bb,>= psr,27,inste0_16bit_16 + INC_KPC_2; + CMP_INDEX_REG_MEAT8(xreg) +inste0_16bit_16 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + INC_KPC_1 + dep scratch1,23,8,ret0 + CMP_INDEX_REG_MEAT16(xreg) +#else + C_CPX_IMM(); +#endif + + + break; +case 0xe1: /* SBC (Dloc,X) */ +/* called with arg = val to SBC in */ + GET_DLOC_X_IND_RD(); + SBC_INST(); + + break; +case 0xe2: /* SEP #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_2; + dep neg,24,1,psr + CYCLES_PLUS_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + or psr,ret0,ret0 + ldi 0,zero + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + b update_system_state + extru ret0,24,1,neg +#else + GET_1BYTE_ARG; + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_2; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + psr = psr | (arg & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + + break; +case 0xe3: /* SBC Disp8,S */ +/* called with arg = val to SBC in */ + GET_DISP8_S_RD(); + SBC_INST(); + + break; +case 0xe4: /* CPX Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + CMP_INDEX_REG_LOAD(inste4_16bit_16, xreg) +#else + C_CPX_DLOC(); +#endif + + + break; +case 0xe5: /* SBC Dloc */ +/* called with arg = val to SBC in */ + GET_DLOC_RD(); + SBC_INST(); + + break; +case 0xe6: /* INC Dloc */ + GET_DLOC_RD(); + INC_INST(1); + + break; +case 0xe7: /* SBC [Dloc] */ + GET_DLOC_L_IND_RD(); + SBC_INST(); + + break; +case 0xe8: /* INX */ +#ifdef ASM + INC_KPC_1 + addi 1,xreg,xreg + bb,>= psr,27,inste8_16bit_16 + extru xreg,31,8,zero + + extru xreg,24,1,neg + b dispatch + copy zero,xreg + +inste8_16bit_16 + extru xreg,31,16,zero + extru xreg,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(xreg + 1, xreg); +#endif + + break; +case 0xe9: /* SBC #imm */ + GET_IMM_MEM(); + SBC_INST(); + + break; +case 0xea: /* NOP */ +#ifdef ASM + INC_KPC_1 + b dispatch + nop +#else + INC_KPC_1; +#endif + + break; +case 0xeb: /* XBA */ +#ifdef ASM + extru acc,16,1,neg /* Z and N reflect status of low 8 */ + CYCLES_PLUS_1 /* bits of final acc value! */ + copy acc,scratch1 /* regardlessof ACC 8 or 16 bit */ + extru acc,23,8,acc + INC_KPC_1 + copy acc,zero + b dispatch + dep scratch1,23,8,acc +#else + tmp1 = acc & 0xff; + CYCLES_PLUS_1 + acc = (tmp1 << 8) + (acc >> 8); + INC_KPC_1; + SET_NEG_ZERO8(acc & 0xff); +#endif + + break; +case 0xec: /* CPX abs */ +#ifdef ASM + GET_ABS_ADDR() + CMP_INDEX_REG_LOAD(instec_16bit_16, xreg) +#else + C_CPX_ABS(); +#endif + + + + + break; +case 0xed: /* SBC abs */ + GET_ABS_RD(); + SBC_INST(); + + break; +case 0xee: /* INC abs */ + GET_ABS_RD(); + INC_INST(0); + + + break; +case 0xef: /* SBC long */ + GET_LONG_RD(); + SBC_INST(); + + + break; +case 0xf0: /* BEQ disp8 */ +#ifdef ASM + COND_BR1 + comib,<> 0,zero,instf0_2_16 + COND_BR2 + +instf0_2_16 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(zero == 0); +#endif + + break; +case 0xf1: /* SBC (Dloc),y */ + GET_DLOC_IND_Y_RD(); + SBC_INST(); + + break; +case 0xf2: /* SBC (Dloc) */ + GET_DLOC_IND_RD(); + SBC_INST(); + + break; +case 0xf3: /* SBC (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + SBC_INST(); + + break; +case 0xf4: /* PEA Abs */ +#ifdef ASM + ldb 1(scratch1),arg0 + ldil l%dispatch,link + ldb 2(scratch1),scratch1 + INC_KPC_3 + CYCLES_PLUS_1 + ldo r%dispatch(link),link + b push_16_unsafe + dep scratch1,23,8,arg0 +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + INC_KPC_3; + PUSH16_UNSAFE(arg); +#endif + + break; +case 0xf5: /* SBC Dloc,x */ + GET_DLOC_X_RD(); + SBC_INST(); + + break; +case 0xf6: /* INC Dloc,x */ + GET_DLOC_X_RD(); + INC_INST(1); + + break; +case 0xf7: /* SBC [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + SBC_INST(); + + break; +case 0xf8: /* SED */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,28,1,psr /* set decimal */ +#else + INC_KPC_1; + psr |= 0x8; +#endif + + break; +case 0xf9: /* SBC abs,y */ + GET_ABS_Y_RD(); + SBC_INST(); + + break; +case 0xfa: /* PLX */ +#ifdef ASM + bb,< psr,27,instfa_8bit_16 + CYCLES_PLUS_1 + + INC_KPC_1 + bl pull_16,link + nop + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,xreg + +instfa_8bit_16 + INC_KPC_1 + bl pull_8,link + nop + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + CYCLES_PLUS_1; + if(psr & 0x10) { + PULL8(xreg); + SET_NEG_ZERO8(xreg); + } else { + PULL16(xreg); + SET_NEG_ZERO16(xreg); + } +#endif + + break; +case 0xfb: /* XCE */ +#ifdef ASM + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_1 + extru psr,23,1,scratch1 /* e bit */ + dep psr,23,1,psr /* copy carry to e bit */ + b update_system_state + dep scratch1,31,1,psr /* copy e bit to carry */ +#else + tmp2 = psr; + INC_KPC_1; + psr = (tmp2 & 0xfe) | ((tmp2 & 1) << 8) | ((tmp2 >> 8) & 1); + UPDATE_PSR(psr, tmp2); +#endif + + break; +case 0xfc: /* JSR (Abs,X) */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru kpc,15,8,scratch2 + ldb 2(scratch1),scratch1 + dep scratch2,15,16,ret0 + INC_KPC_2; + dep scratch1,23,8,ret0 + add xreg,ret0,arg0 + bl get_mem_long_16,link + extru arg0,31,24,arg0 + + CYCLES_PLUS_2 + extru kpc,31,16,arg0 + ldil l%dispatch,link + dep ret0,31,16,kpc + b push_16_unsafe + ldo r%dispatch(link),link +#else + GET_2BYTE_ARG; + INC_KPC_2; + tmp1 = kpc; + arg = (kpc & 0xff0000) + ((arg + xreg) & 0xffff); + GET_MEMORY16(arg, tmp2, 1); + kpc = (kpc & 0xff0000) + tmp2; + CYCLES_PLUS_2 + PUSH16_UNSAFE(tmp1); +#endif + + break; +case 0xfd: /* SBC Abs,X */ + GET_ABS_X_RD(); + SBC_INST(); + + break; +case 0xfe: /* INC Abs,X */ + GET_ABS_X_RD_WR(); + INC_INST(0); + + break; +case 0xff: /* SBC Long,X */ + GET_LONG_X_RD(); + SBC_INST(); + diff --git a/kegs/Src/8inst_c.h b/kegs/Src/8inst_c.h new file mode 100644 index 0000000..9045e02 --- /dev/null +++ b/kegs/Src/8inst_c.h @@ -0,0 +1,3163 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef ASM +# ifdef INCLUDE_RCSID_S + .stringz "@(#)$KmKId: instable.h,v 1.104 2004-10-05 20:12:08-04 kentd Exp $" +# endif +#endif + +#ifdef _DEBUG +#define ENTER_DEBUGGER() set_halt(HALT_WANTTOBRK) +#else +#define ENTER_DEBUGGER() +#endif + +#define IF_OPCODE_SUPPORTED(_INC) \ + if (g_sim65816.g_6502_emulation && kpc < 0x00C000) \ + { \ + printf("unsupported instruction '%0x' @%0x : replacing by %d NOP\n",opcode,kpc,_INC); \ + ENTER_DEBUGGER(); \ + kpc = (kpc & 0xff0000) + ((kpc + _INC) & 0xffff); \ + } \ + else + +case 0x00: /* brk */ +#ifdef ASM + ldb 1(scratch1),ret0 + ldil l%g_sim65816.g_testing,arg3 + ldil l%g_sim65816.g_num_brk,arg1 + ldw r%g_sim65816.g_testing(arg3),arg3 + INC_KPC_2; + ldw r%g_sim65816.g_num_brk(arg1),arg2 + comib,<> 0,arg3,brk_testing_8 + extru kpc,31,16,arg0 + addi 1,arg2,arg2 + bb,>= psr,23,brk_native_8 + stw arg2,r%g_sim65816.g_num_brk(arg1) + + bl push_16,link + nop + + bl push_8,link + extru psr,31,8,arg0 ;B bit already on in PSR + + ldil l%0xfffe,arg0 + bl get_mem_long_16,link + ldo r%0xfffe(arg0),arg0 + + zdep ret0,31,16,kpc ;set kbank to 0 + +#if 0 + bl set_halt_act,link + ldi 3,arg0 +#endif + + + ldi 0,dbank ;clear dbank in emul mode + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + + +brk_native_8 + stw arg0,STACK_SAVE_COP_ARG0(sp) + bl push_8,link + extru kpc,15,8,arg0 + + bl push_16,link + ldw STACK_SAVE_COP_ARG0(sp),arg0 + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xffe6,arg0 + bl get_mem_long_16,link + ldo r%0xffe6(arg0),arg0 + + zdep ret0,31,16,kpc ;zero kbank in kpc + +#if 0 +#endif + bl set_halt_act,link + ldi 3,arg0 + + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + +brk_testing_8 + DEC_KPC2; + CYCLES_PLUS_2 + b dispatch_done + depi RET_BREAK,3,4,ret0 + +#else + GET_1BYTE_ARG; + if(g_sim65816.g_testing) { + CYCLES_PLUS_2; + FINISH(RET_BREAK, arg); + } + g_sim65816.g_num_brk++; + INC_KPC_2; + if(psr & 0x100) { + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xfffe, kpc, 0); + dbank = 0; + } else { + PUSH8(kpc >> 16); + PUSH16(kpc); + PUSH8(psr & 0xff); + GET_MEMORY16(0xffe6, kpc, 0); + halt_printf("Halting for native break!\n"); + } + kpc = kpc & 0xffff; + psr |= 0x4; + psr &= ~(0x8); +#endif + + break; +case 0x01: /* ORA (Dloc,X) */ +/* called with arg = val to ORA in */ + GET_DLOC_X_IND_RD(); + ORA_INST(); + + break; +case 0x02: /* COP */ +#ifdef ASM + ldil l%g_sim65816.g_num_cop,arg1 + INC_KPC_2; + ldw r%g_sim65816.g_num_cop(arg1),arg2 + extru kpc,31,16,arg0 + addi 1,arg2,arg2 + bb,>= psr,23,cop_native_8 + stw arg2,r%g_sim65816.g_num_cop(arg1) + + bl push_16,link + nop + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xfff4,arg0 + bl get_mem_long_16,link + ldo r%0xfff4(arg0),arg0 + + ldi 0,dbank ;clear dbank in emul mode + zdep ret0,31,16,kpc ;clear kbank + + bl set_halt_act,link + ldi 3,arg0 + + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + +cop_native_8 + stw arg0,STACK_SAVE_COP_ARG0(sp) + bl push_8,link + extru kpc,15,8,arg0 + + bl push_16,link + ldw STACK_SAVE_COP_ARG0(sp),arg0 + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xffe4,arg0 + bl get_mem_long_16,link + ldo r%0xffe4(arg0),arg0 + + zdep ret0,31,16,kpc ;clear kbank + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + + +#else + IF_OPCODE_SUPPORTED(1) + { + g_sim65816.g_num_cop++; + INC_KPC_2; + if(psr & 0x100) { + halt_printf("Halting for emul COP at %04x\n", kpc); + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xfff4, kpc, 0); + dbank = 0; + } else { + PUSH8(kpc >> 16); + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xffe4, kpc, 0); + } + kpc = kpc & 0xffff; + psr |= 4; + psr &= ~(0x8); + } +#endif + + break; +case 0x03: /* ORA Disp8,S */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + ORA_INST(); + } + break; +case 0x04: /* TSB Dloc */ + GET_DLOC_RD(); + TSB_INST(1); + + break; +case 0x05: /* ORA Dloc */ + GET_DLOC_RD(); + ORA_INST(); + + break; +case 0x06: /* ASL Dloc */ + GET_DLOC_RD(); + ASL_INST(1); + + break; +case 0x07: /* ORA [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + ORA_INST(); + } + break; +case 0x08: /* PHP */ +#ifdef ASM + dep neg,24,1,psr + ldil l%dispatch,link + INC_KPC_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + ldo r%dispatch(link),link + b push_8 + extru psr,31,8,arg0 +#else + INC_KPC_1; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + PUSH8(psr); +#endif + + break; +case 0x09: /* ORA #imm */ + GET_IMM_MEM(); + ORA_INST(); + + break; +case 0x0a: /* ASL a */ +#ifdef ASM +# ifdef ACC8 + ldi 0xff,scratch1 + sh1add acc,0,scratch3 + INC_KPC_1 + extru scratch3,24,1,neg + and scratch3,scratch1,zero + extru scratch3,23,1,scratch2 + dep zero,31,8,acc + b dispatch + dep scratch2,31,1,psr /* set carry */ +# else + zdepi -1,31,16,scratch1 + sh1add acc,0,scratch3 + INC_KPC_1 + extru scratch3,16,1,neg + and scratch3,scratch1,zero + extru scratch3,15,1,scratch2 + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; + tmp1 = acc + acc; +# ifdef ACC8 + SET_CARRY8(tmp1); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + SET_CARRY16(tmp1); + acc = tmp1 & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x0b: /* PHD */ +#ifdef ASM + ldil l%dispatch,link + extru direct,31,16,arg0 + INC_KPC_1 + b push_16_unsafe + ldo r%dispatch(link),link +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + PUSH16_UNSAFE(direct); + } +#endif + + break; +case 0x0c: /* TSB abs */ + GET_ABS_RD(); + TSB_INST(0); + + break; +case 0x0d: /* ORA abs */ + GET_ABS_RD(); + ORA_INST(); + + break; +case 0x0e: /* ASL abs */ + GET_ABS_RD(); + ASL_INST(0); + + break; +case 0x0f: /* ORA long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + ORA_INST(); + } + + break; +case 0x10: /* BPL disp8 */ +#ifdef ASM + COND_BR1 + comib,<> 0,neg,inst10_2_8 + COND_BR2 + +inst10_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(neg == 0); +#endif + + break; +case 0x11: /* ORA (Dloc),y */ + GET_DLOC_IND_Y_RD(); + ORA_INST(); + + break; +case 0x12: /* ORA (Dloc) */ + GET_DLOC_IND_RD(); + ORA_INST(); + + break; +case 0x13: /* ORA (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + ORA_INST(); + } + break; +case 0x14: /* TRB Dloc */ + GET_DLOC_RD(); + TRB_INST(1); + + break; +case 0x15: /* ORA Dloc,x */ + GET_DLOC_X_RD(); + ORA_INST(); + + break; +case 0x16: /* ASL Dloc,X */ + GET_DLOC_X_RD(); + ASL_INST(1); + + break; +case 0x17: /* ORA [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + ORA_INST(); + } + break; +case 0x18: /* CLC */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,31,1,psr /* clear carry */ +#else + psr = psr & (~1); + INC_KPC_1; +#endif + + break; +case 0x19: /* ORA abs,y */ + GET_ABS_Y_RD(); + ORA_INST(); + + + break; +case 0x1a: /* INC a */ +#ifdef ASM +# ifdef ACC8 + ldi 0xff,scratch2 + addi 1,acc,scratch1 + extru scratch1,24,1,neg + INC_KPC_1 + extru scratch1,31,8,zero + b dispatch + dep zero,31,8,acc +# else + zdepi -1,31,16,scratch2 + addi 1,acc,scratch1 + extru scratch1,16,1,neg + INC_KPC_1 + extru scratch1,31,16,zero + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + acc = (acc & 0xff00) | ((acc + 1) & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + acc = (acc + 1) & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x1b: /* TCS */ +#ifdef ASM + copy acc,stack + extru,= psr,23,1,0 /* in emulation mode, stack page 1 */ + depi 1,23,24,stack + INC_KPC_1 + b dispatch + nop +#else + IF_OPCODE_SUPPORTED(1) + { + stack = acc; + INC_KPC_1; + if(psr & 0x100) + { + stack = (stack & 0xff) + 0x100; + } + } +#endif + + break; +case 0x1c: /* TRB Abs */ + GET_ABS_RD(); + TRB_INST(0); + + break; +case 0x1d: /* ORA Abs,X */ + GET_ABS_X_RD(); + ORA_INST(); + + break; +case 0x1e: /* ASL Abs,X */ + GET_ABS_X_RD_WR(); + ASL_INST(0); + + break; +case 0x1f: /* ORA Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + ORA_INST(); + } + + break; +case 0x20: /* JSR abs */ +#ifdef ASM + addi 2,kpc,arg0 + ldb 1(scratch1),scratch2 + CYCLES_PLUS_2 + ldb 2(scratch1),scratch1 + ldil l%dispatch,link + extru arg0,31,16,arg0 + ldo r%dispatch(link),link + dep scratch2,31,8,kpc + b push_16 + dep scratch1,23,8,kpc +#else + GET_2BYTE_ARG; + INC_KPC_2; + PUSH16(kpc); + kpc = (kpc & 0xff0000) + arg; + CYCLES_PLUS_2; +#endif + + break; +case 0x21: /* AND (Dloc,X) */ +/* called with arg = val to AND in */ + GET_DLOC_X_IND_RD(); + AND_INST(); + + break; +case 0x22: /* JSL Long */ +#ifdef ASM + INC_KPC_3 + ldb 3(scratch1),scratch2 + copy kpc,arg0 + ldb 1(scratch1),kpc + ldb 2(scratch1),scratch1 + CYCLES_PLUS_3 + dep scratch2,15,8,kpc + stw scratch2,STACK_SAVE_INSTR_TMP1(sp) + bl push_24_unsafe,link + dep scratch1,23,8,kpc + + b dispatch + nop +#else + IF_OPCODE_SUPPORTED(2) + { + GET_3BYTE_ARG; + tmp1 = arg; + CYCLES_PLUS_3; + INC_KPC_3; + PUSH24_UNSAFE(kpc); + kpc = tmp1 & 0xffffff; + } +#endif + + break; +case 0x23: /* AND Disp8,S */ +/* called with arg = val to AND in */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + AND_INST(); + } + break; +case 0x24: /* BIT Dloc */ + GET_DLOC_RD(); + BIT_INST(); + + break; +case 0x25: /* AND Dloc */ +/* called with arg = val to AND in */ + GET_DLOC_RD(); + AND_INST(); + + break; +case 0x26: /* ROL Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + ROL_INST(1); + + break; +case 0x27: /* AND [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + AND_INST(); + } + break; +case 0x28: /* PLP */ +#ifdef ASM + bl pull_8,link + ldi 0,zero + + extru psr,27,2,scratch2 /* save old x & m */ + dep ret0,31,8,psr + CYCLES_PLUS_1 + INC_KPC_1 + extru,<> ret0,30,1,0 + ldi 1,zero + copy scratch2,arg0 + b update_system_state + extru ret0,24,1,neg +#else + PULL8(tmp1); + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_1; + psr = (psr & ~0xff) | (tmp1 & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + + break; +case 0x29: /* AND #imm */ + GET_IMM_MEM(); + AND_INST(); + + break; +case 0x2a: /* ROL a */ +#ifdef ASM +# ifdef ACC8 + extru psr,31,1,scratch2 + ldi 0xff,scratch1 + sh1add acc,scratch2,scratch3 + INC_KPC_1 + extru scratch3,24,1,neg + and scratch3,scratch1,zero + extru scratch3,23,1,scratch2 + dep zero,31,8,acc + b dispatch + dep scratch2,31,1,psr /* set carry */ +# else + extru psr,31,1,scratch2 + INC_KPC_1 + sh1add acc,scratch2,scratch3 + zdepi -1,31,16,scratch1 + extru scratch3,16,1,neg + and scratch3,scratch1,zero + extru scratch3,15,1,scratch2 + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) << 1) + (psr & 1); + SET_CARRY8(tmp1); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc << 1) + (psr & 1); + SET_CARRY16(tmp1); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x2b: /* PLD */ +#ifdef ASM + INC_KPC_1 + bl pull_16_unsafe,link + CYCLES_PLUS_1 + extru ret0,31,16,direct + extru ret0,16,1,neg + b dispatch + copy direct,zero +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + PULL16_UNSAFE(direct); + CYCLES_PLUS_1; + SET_NEG_ZERO16(direct); + } +#endif + + break; +case 0x2c: /* BIT abs */ + GET_ABS_RD(); + BIT_INST(); + + break; +case 0x2d: /* AND abs */ + GET_ABS_RD(); + AND_INST(); + + break; +case 0x2e: /* ROL abs */ + GET_ABS_RD(); + ROL_INST(0); + + break; +case 0x2f: /* AND long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + AND_INST(); + } + + break; +case 0x30: /* BMI disp8 */ +#ifdef ASM + COND_BR1 + comib,= 0,neg,inst30_2_8 + COND_BR2 + +inst30_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(neg); +#endif + + break; +case 0x31: /* AND (Dloc),y */ + GET_DLOC_IND_Y_RD(); + AND_INST(); + + break; +case 0x32: /* AND (Dloc) */ + GET_DLOC_IND_RD(); + AND_INST(); + + break; +case 0x33: /* AND (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + AND_INST(); + } + break; +case 0x34: /* BIT Dloc,x */ + GET_DLOC_X_RD(); + BIT_INST(); + + break; +case 0x35: /* AND Dloc,x */ + GET_DLOC_X_RD(); + AND_INST(); + + break; +case 0x36: /* ROL Dloc,X */ + GET_DLOC_X_RD(); + ROL_INST(1); + + break; +case 0x37: /* AND [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + AND_INST(); + } + break; +case 0x38: /* SEC */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,31,1,psr /* set carry */ +#else + psr = psr | 1; + INC_KPC_1; +#endif + + break; +case 0x39: /* AND abs,y */ + GET_ABS_Y_RD(); + AND_INST(); + + break; +case 0x3a: /* DEC a */ +#ifdef ASM +# ifdef ACC8 + addi -1,acc,scratch1 + extru scratch1,24,1,neg + INC_KPC_1 + extru scratch1,31,8,zero + b dispatch + dep zero,31,8,acc +# else + addi -1,acc,scratch1 + extru scratch1,16,1,neg + INC_KPC_1 + extru scratch1,31,16,zero + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + acc = (acc & 0xff00) | ((acc - 1) & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + acc = (acc - 1) & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x3b: /* TSC */ +/* set N,Z according to 16 bit acc */ +#ifdef ASM + copy stack,acc + extru stack,16,1,neg + INC_KPC_1 + b dispatch + extru acc,31,16,zero +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + acc = stack; + SET_NEG_ZERO16(acc); + } +#endif + + break; +case 0x3c: /* BIT Abs,x */ + GET_ABS_X_RD(); + BIT_INST(); + + break; +case 0x3d: /* AND Abs,X */ + GET_ABS_X_RD(); + AND_INST(); + + break; +case 0x3e: /* ROL Abs,X */ + GET_ABS_X_RD_WR(); + ROL_INST(0); + + break; +case 0x3f: /* AND Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + AND_INST(); + } + + break; +case 0x40: /* RTI */ +#ifdef ASM + bb,>= psr,23,rti_native_8 + CYCLES_PLUS_1 +/* emulation */ + bl pull_24,link + ldi 0,zero + + extru psr,27,2,scratch2 + extru ret0,23,16,scratch3 + copy scratch2,arg0 + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + + extru ret0,24,1,neg + b update_system_state + dep scratch3,31,16,kpc + +rti_native_8 + bl pull_8,link + ldi 0,zero + + copy ret0,scratch1 + extru ret0,24,1,neg + dep ret0,31,8,scratch1 + bl pull_24,link + stw scratch1,STACK_SAVE_INSTR_TMP1(sp) + + extru psr,27,2,scratch2 + ldw STACK_SAVE_INSTR_TMP1(sp),psr + extru ret0,31,24,kpc + extru,<> psr,30,1,0 + ldi 1,zero + + b update_system_state_and_change_kbank + copy scratch2,arg0 +#else + CYCLES_PLUS_1 + if(psr & 0x100) { + PULL24(tmp1); + kpc = (kpc & 0xff0000) + ((tmp1 >> 8) & 0xffff); + tmp2 = psr; + psr = (psr & ~0xff) + (tmp1 & 0xff); + neg = (psr >> 7) & 1; + zero = !(psr & 2); + UPDATE_PSR(psr, tmp2); + } else { + PULL8(tmp1); + tmp2 = psr; + psr = (tmp1 & 0xff); + neg = (psr >> 7) & 1; + zero = !(psr & 2); + PULL24(kpc); + UPDATE_PSR(psr, tmp2); + } +#endif + + + break; +case 0x41: /* EOR (Dloc,X) */ +/* called with arg = val to EOR in */ + GET_DLOC_X_IND_RD(); + EOR_INST(); + + break; +case 0x42: /* WDM */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_5 + CYCLES_PLUS_2 + INC_KPC_2 + b dispatch_done + depi RET_WDM,3,4,ret0 +#else + IF_OPCODE_SUPPORTED(2) // 0x42 + { + GET_1BYTE_ARG; + INC_KPC_2; + CYCLES_PLUS_5; + CYCLES_PLUS_2; + FINISH(RET_WDM, arg & 0xff); + } +#endif + + break; +case 0x43: /* EOR Disp8,S */ +/* called with arg = val to EOR in */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + EOR_INST(); + } + break; +case 0x44: /* MVP */ +#ifdef ASM + ldb 2(scratch1),scratch2 /* src bank */ + bb,< psr,23,inst44_notnat_8 + ldb 1(scratch1),dbank /* dest bank */ + bb,< psr,27,inst44_notnat_8 + stw scratch2,STACK_SRC_BANK(sp) + +inst44_loop_8 + CYCLES_PLUS_1 + ldw STACK_SRC_BANK(sp),scratch2 + copy xreg,arg0 + + bl get_mem_long_8,link + dep scratch2,15,8,arg0 +/* got byte */ + copy ret0,arg1 + copy yreg,arg0 + bl set_mem_long_8,link + dep dbank,15,8,arg0 +/* wrote byte, dec acc */ + CYCLES_PLUS_2 + fldds 0(fcycles_stop_ptr),fcycles_stop + addi -1,xreg,xreg + zdepi -1,31,16,scratch2 + addi -1,yreg,yreg + addi -1,acc,acc + fcmp,<,dbl fcycles,fcycles_stop + and xreg,scratch2,xreg + extrs acc,31,16,scratch1 + and yreg,scratch2,yreg + + comib,= -1,scratch1,inst44_done_8 + and acc,scratch2,acc + + ftest + b inst44_out_of_time_8 + + CYCLES_PLUS_2 + b inst44_loop_8 + nop + +/* get here if done */ +inst44_done_8 + INC_KPC_3 + b dispatch + nop + +inst44_notnat_8 + copy dbank,ret0 + dep scratch2,23,8,ret0 + CYCLES_PLUS_3 + depi RET_MVP,3,4,ret0 + b dispatch_done + CYCLES_PLUS_2 + +inst44_out_of_time_8 +/* cycle have gone positive, just get out, do not update kpc */ + b,n dispatch +#else + IF_OPCODE_SUPPORTED(2) // 0x44 + { + GET_2BYTE_ARG; + /* arg & 0xff = dest bank, arg & 0xff00 = src bank */ + if(psr & 0x110) { + // OG MVP should work even with no native mode - keep the warning though + printf("MVP but not native m or x!\n"); + /* + halt_printf("MVP but not native m or x!\n"); + break; + */ + } + CYCLES_MINUS_2 + dbank = arg & 0xff; + tmp1 = (arg >> 8) & 0xff; + while(1) { + CYCLES_PLUS_3; + GET_MEMORY8((tmp1 << 16) + xreg, arg); + SET_MEMORY8((dbank << 16) + yreg, arg); + CYCLES_PLUS_2; + xreg = (xreg - 1) & 0xffff; + yreg = (yreg - 1) & 0xffff; + acc = (acc - 1) & 0xffff; + if(acc == 0xffff) { + INC_KPC_3; + break; + } + if(fcycles >= g_sim65816.g_fcycles_stop) { + break; + } + } + } +#endif + + + break; +case 0x45: /* EOR Dloc */ +/* called with arg = val to EOR in */ + GET_DLOC_RD(); + EOR_INST(); + + break; +case 0x46: /* LSR Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + LSR_INST(1); + + break; +case 0x47: /* EOR [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + EOR_INST(); + } + break; +case 0x48: /* PHA */ +#ifdef ASM +# ifdef ACC8 + INC_KPC_1 + ldil l%dispatch,link + extru acc,31,8,arg0 + b push_8 + ldo r%dispatch(link),link +# else + INC_KPC_1 + ldil l%dispatch,link + extru acc,31,16,arg0 + b push_16 + ldo r%dispatch(link),link +# endif +#else + INC_KPC_1; +# ifdef ACC8 + PUSH8(acc); +# else + PUSH16(acc); +# endif +#endif + + break; +case 0x49: /* EOR #imm */ + GET_IMM_MEM(); + EOR_INST(); + + break; +case 0x4a: /* LSR a */ +#ifdef ASM +# ifdef ACC8 + extru acc,31,1,scratch2 + INC_KPC_1 + extru acc,30,7,zero + ldi 0,neg + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,8,acc +# else + extru acc,31,1,scratch2 + INC_KPC_1 + extru acc,30,15,zero + ldi 0,neg + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) >> 1); + SET_CARRY8(acc << 8); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc >> 1); + SET_CARRY8((acc << 8)); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x4b: /* PHK */ +#ifdef ASM + ldil l%dispatch,link + extru kpc,15,8,arg0 + INC_KPC_1 + b push_8 + ldo r%dispatch(link),link +#else + IF_OPCODE_SUPPORTED(1) + { + PUSH8(kpc >> 16); + INC_KPC_1; + } +#endif + + break; +case 0x4c: /* JMP abs */ +#ifdef ASM + ldb 1(scratch1),scratch2 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + dep scratch2,31,8,kpc + b dispatch + dep scratch1,23,8,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + kpc = (kpc & 0xff0000) + arg; +#endif + + + break; +case 0x4d: /* EOR abs */ + GET_ABS_RD(); + EOR_INST(); + + break; +case 0x4e: /* LSR abs */ + GET_ABS_RD(); + LSR_INST(0); + + break; +case 0x4f: /* EOR long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + EOR_INST(); + } + + break; +case 0x50: /* BVC disp8 */ +#ifdef ASM + COND_BR1 + bb,< psr,25,inst50_2_8 + COND_BR2 + +inst50_2_8 + COND_BR_UNTAKEN + +#else + BRANCH_DISP8((psr & 0x40) == 0); +#endif + + break; +case 0x51: /* EOR (Dloc),y */ + GET_DLOC_IND_Y_RD(); + EOR_INST(); + + break; +case 0x52: /* EOR (Dloc) */ + GET_DLOC_IND_RD(); + EOR_INST(); + + break; +case 0x53: /* EOR (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + EOR_INST(); + } + break; +case 0x54: /* MVN */ +#ifdef ASM + ldb 2(scratch1),scratch2 /* src bank */ + bb,< psr,23,inst54_notnat_8 + ldb 1(scratch1),dbank /* dest bank */ + bb,< psr,27,inst54_notnat_8 + stw scratch2,STACK_SRC_BANK(sp) + +/* even in 8bit acc mode, use 16-bit accumulator! */ + +inst54_loop_8 + CYCLES_PLUS_1 + ldw STACK_SRC_BANK(sp),scratch2 + copy xreg,arg0 + + bl get_mem_long_8,link + dep scratch2,15,8,arg0 +/* got byte */ + copy ret0,arg1 + copy yreg,arg0 + bl set_mem_long_8,link + dep dbank,15,8,arg0 +/* wrote byte, dec acc */ + CYCLES_PLUS_2 + fldds 0(fcycles_stop_ptr),fcycles_stop + addi 1,xreg,xreg + zdepi -1,31,16,scratch2 + addi 1,yreg,yreg + addi -1,acc,acc + fcmp,<,dbl fcycles,fcycles_stop + and xreg,scratch2,xreg + extrs acc,31,16,scratch1 + and yreg,scratch2,yreg + + comib,= -1,scratch1,inst54_done_8 + and acc,scratch2,acc + ftest + b,n inst54_out_of_time_8 + + CYCLES_PLUS_2 + b inst54_loop_8 + nop + +/* get here if done */ +inst54_done_8 + INC_KPC_3 + b dispatch + nop + +inst54_out_of_time_8 +/* cycle have gone positive, just get out, don't update kpc */ + b,n dispatch + +inst54_notnat_8 + copy dbank,ret0 + dep scratch2,23,8,ret0 + CYCLES_PLUS_3 + depi RET_MVN,3,4,ret0 + b dispatch_done + CYCLES_PLUS_3 +#else + IF_OPCODE_SUPPORTED(2) // 0x54 + { + + GET_2BYTE_ARG; + /* arg & 0xff = dest bank, arg & 0xff00 = src bank */ + if(psr & 0x110) { + // OG MVN should work even with no native mode - keep the warning though + printf("MVN but not native m or x!\n"); + } + CYCLES_MINUS_2; + dbank = arg & 0xff; + tmp1 = (arg >> 8) & 0xff; + while(1) { + CYCLES_PLUS_3; + GET_MEMORY8((tmp1 << 16) + xreg, arg); + SET_MEMORY8((dbank << 16) + yreg, arg); + CYCLES_PLUS_2; + xreg = (xreg + 1) & 0xffff; + yreg = (yreg + 1) & 0xffff; + acc = (acc - 1) & 0xffff; + if(acc == 0xffff) { + INC_KPC_3; + break; + } + if(fcycles >= g_sim65816.g_fcycles_stop) { + break; + } + } + } +#endif + + break; +case 0x55: /* EOR Dloc,x */ + GET_DLOC_X_RD(); + EOR_INST(); + + break; +case 0x56: /* LSR Dloc,X */ + GET_DLOC_X_RD(); + LSR_INST(1); + + break; +case 0x57: /* EOR [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + EOR_INST(); + } + break; +case 0x58: /* CLI */ +#ifdef ASM + INC_KPC_1 + b check_irqs_pending /* check for ints pending! */ + depi 0,29,1,psr /* clear int disable */ +#else + psr = psr & (~4); + INC_KPC_1; + if(((psr & 0x4) == 0) && g_moremem.g_irq_pending) { + FINISH(RET_IRQ, 0); + } +#endif + + break; +case 0x59: /* EOR abs,y */ + GET_ABS_Y_RD(); + EOR_INST(); + + break; +case 0x5a: /* PHY */ +#ifdef ASM + INC_KPC_1 + ldil l%dispatch,link + bb,>= psr,27,phy_16_8 + ldo r%dispatch(link),link + + b push_8 + copy yreg,arg0 + +phy_16_8 + b push_16 + copy yreg,arg0 +#else + INC_KPC_1; + if(psr & 0x10) { + PUSH8(yreg); + } else { + PUSH16(yreg); + } +#endif + + break; +case 0x5b: /* TCD */ +#ifdef ASM + extru acc,31,16,direct + INC_KPC_1 + copy acc,zero + b dispatch + extru acc,16,1,neg +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + direct = acc; + SET_NEG_ZERO16(acc); + } +#endif + + break; +case 0x5c: /* JMP Long */ +#ifdef ASM + ldb 1(scratch1),kpc + ldb 2(scratch1),scratch2 + CYCLES_PLUS_1 + ldb 3(scratch1),arg0 /* new bank */ + dep scratch2,23,8,kpc + b dispatch + dep arg0,15,8,kpc +#else + IF_OPCODE_SUPPORTED(2) // 0x5C + { + GET_3BYTE_ARG; + CYCLES_PLUS_1; + kpc = arg; + } +#endif + + break; +case 0x5d: /* EOR Abs,X */ + GET_ABS_X_RD(); + EOR_INST(); + + break; +case 0x5e: /* LSR Abs,X */ + GET_ABS_X_RD_WR(); + LSR_INST(0); + + break; +case 0x5f: /* EOR Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + EOR_INST(); + } + + break; +case 0x60: /* RTS */ +#ifdef ASM + bl pull_16,link + CYCLES_PLUS_2 +/* ret0 is new kpc-1 */ + addi 1,ret0,ret0 + b dispatch + dep ret0,31,16,kpc +#else + CYCLES_PLUS_2 + PULL16(tmp1); + kpc = (kpc & 0xff0000) + ((tmp1 + 1) & 0xffff); +#endif + + + break; +case 0x61: /* ADC (Dloc,X) */ +/* called with arg = val to ADC in */ + GET_DLOC_X_IND_RD(); + ADC_INST(); + + break; +case 0x62: /* PER */ +#ifdef ASM + ldb 1(scratch1),ret0 + INC_KPC_3 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_2 + ldil l%dispatch,link + dep scratch1,23,8,ret0 + ldo r%dispatch(link),link + add kpc,ret0,arg0 + b push_16_unsafe + extru arg0,31,16,arg0 +#else + IF_OPCODE_SUPPORTED(2) // 0x62 + { + GET_2BYTE_ARG; + CYCLES_PLUS_2; + INC_KPC_3; + PUSH16_UNSAFE(kpc + arg); + } +#endif + + break; +case 0x63: /* ADC Disp8,S */ +/* called with arg = val to ADC in */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + ADC_INST(); + } + break; +case 0x64: /* STZ Dloc */ + GET_DLOC_ADDR(); + STZ_INST(1); + + break; +case 0x65: /* ADC Dloc */ +/* called with arg = val to ADC in */ + GET_DLOC_RD(); + ADC_INST(); + + break; +case 0x66: /* ROR Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + ROR_INST(1); + + break; +case 0x67: /* ADC [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + ADC_INST(); + } + break; +case 0x68: /* PLA */ +#ifdef ASM +# ifdef ACC8 + INC_KPC_1 + bl pull_8,link + CYCLES_PLUS_1 + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + dep ret0,31,8,acc +# else + INC_KPC_1 + bl pull_16,link + CYCLES_PLUS_1 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + extru ret0,31,16,acc +# endif +#else + INC_KPC_1; + CYCLES_PLUS_1; +# ifdef ACC8 + PULL8(tmp1); + acc = (acc & 0xff00) + tmp1; + SET_NEG_ZERO8(tmp1); +# else + PULL16(tmp1); + acc = tmp1; + SET_NEG_ZERO16(tmp1); +# endif +#endif + + + break; +case 0x69: /* ADC #imm */ + GET_IMM_MEM(); + ADC_INST(); + + break; +case 0x6a: /* ROR a */ +#ifdef ASM +# ifdef ACC8 + extru psr,31,1,neg + INC_KPC_1 + extru acc,30,7,zero + dep neg,24,1,zero + dep acc,31,1,psr /* set carry */ + b dispatch + dep zero,31,8,acc +# else + extru psr,31,1,neg + INC_KPC_1 + extru acc,30,15,zero + dep neg,16,1,zero + dep acc,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) >> 1) + ((psr & 1) << 7); + SET_CARRY8((acc << 8)); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc >> 1) + ((psr & 1) << 15); + SET_CARRY16((acc << 16)); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + + break; +case 0x6b: /* RTL */ +#ifdef ASM + bl pull_24,link + CYCLES_PLUS_1 +/* ret0 is new kpc-1 */ + copy ret0,kpc + addi 1,ret0,scratch1 + b dispatch + dep scratch1,31,16,kpc + +#else + IF_OPCODE_SUPPORTED(1) + { + CYCLES_PLUS_1; + PULL24(tmp1); + kpc = (tmp1 & 0xff0000) + ((tmp1 + 1) & 0xffff); + } +#endif + + break; +case 0x6c: /* JMP (abs) */ +#ifdef ASM + ldb 1(scratch1),arg0 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + bl get_mem_long_16,link + dep scratch1,23,8,arg0 +/* ret0 is addr to jump to */ + b dispatch + dep ret0,31,16,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + GET_MEMORY16(arg, tmp1, 1); + kpc = (kpc & 0xff0000) + tmp1; +#endif + + break; +case 0x6d: /* ADC abs */ + GET_ABS_RD(); + ADC_INST(); + + break; +case 0x6e: /* ROR abs */ + GET_ABS_RD(); + ROR_INST(0); + + break; +case 0x6f: /* ADC long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + ADC_INST(); + } + + break; +case 0x70: /* BVS disp8 */ +#ifdef ASM + COND_BR1 + bb,>= psr,25,inst70_2_8 + COND_BR2 + +inst70_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x40)); +#endif + + break; +case 0x71: /* ADC (Dloc),y */ + GET_DLOC_IND_Y_RD(); + ADC_INST(); + + break; +case 0x72: /* ADC (Dloc) */ + GET_DLOC_IND_RD(); + ADC_INST(); + + break; +case 0x73: /* ADC (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + ADC_INST(); + } + break; +case 0x74: /* STZ Dloc,x */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_X_WR(); + STZ_INST(1); +#else + GET_1BYTE_ARG; + GET_DLOC_X_WR(); + STZ_INST(1); +#endif + + break; +case 0x75: /* ADC Dloc,x */ + GET_DLOC_X_RD(); + ADC_INST(); + + break; +case 0x76: /* ROR Dloc,X */ + GET_DLOC_X_RD(); + ROR_INST(1); + + break; +case 0x77: /* ADC [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + ADC_INST(); + } + break; +case 0x78: /* SEI */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,29,1,psr /* set int disable */ +#else + psr = psr | 4; + INC_KPC_1; +#endif + + break; +case 0x79: /* ADC abs,y */ + GET_ABS_Y_RD(); + ADC_INST(); + + break; +case 0x7a: /* PLY */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,inst7a_16bit_8 + nop + + bl pull_8,link + CYCLES_PLUS_1 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,yreg + +inst7a_16bit_8 + bl pull_16,link + CYCLES_PLUS_1 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,yreg + +#else + INC_KPC_1; + CYCLES_PLUS_1 + if(psr & 0x10) { + PULL8(yreg); + SET_NEG_ZERO8(yreg); + } else { + PULL16(yreg); + SET_NEG_ZERO16(yreg); + } +#endif + + break; +case 0x7b: /* TDC */ +#ifdef ASM + extru direct,31,16,zero + copy direct,acc + INC_KPC_1 + b dispatch + extru direct,16,1,neg +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + acc = direct; + SET_NEG_ZERO16(direct); + } +#endif + + break; +case 0x7c: /* JMP (Abs,x) */ +/* always access kbank, xreg cannot wrap into next bank */ +#ifdef ASM + ldb 1(scratch1),ret0 + copy kpc,scratch2 + ldb 2(scratch1),scratch1 + dep xreg,31,16,scratch2 + CYCLES_PLUS_2 + dep scratch1,23,8,ret0 + add ret0,scratch2,arg0 + bl get_mem_long_16,link + extru arg0,31,24,arg0 + b dispatch + dep ret0,31,16,kpc +#else + GET_2BYTE_ARG; + arg = (kpc & 0xff0000) + ((xreg + arg) & 0xffff); + CYCLES_PLUS_2; + GET_MEMORY16(arg, tmp1, 1); + kpc = (kpc & 0xff0000) + tmp1; +#endif + + break; +case 0x7d: /* ADC Abs,X */ + GET_ABS_X_RD(); + ADC_INST(); + + break; +case 0x7e: /* ROR Abs,X */ + GET_ABS_X_RD_WR(); + ROR_INST(0); + + break; +case 0x7f: /* ADC Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + ADC_INST(); + } + + break; +case 0x80: /* BRA */ +#ifdef ASM + COND_BR1 + COND_BR2 +#else + BRANCH_DISP8(1); +#endif + + + break; +case 0x81: /* STA (Dloc,X) */ + GET_DLOC_X_IND_ADDR(); + STA_INST(0); + + break; +case 0x82: /* BRL disp16 */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + addi 3,kpc,scratch2 + dep scratch1,23,8,ret0 + add ret0,scratch2,scratch2 + b dispatch + dep scratch2,31,16,kpc +#else + IF_OPCODE_SUPPORTED(2) + { + GET_2BYTE_ARG; + CYCLES_PLUS_1; + kpc = (kpc & 0xff0000) + ((kpc + 3 + arg) & 0xffff); + } +#endif + + break; +case 0x83: /* STA Disp8,S */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_ADDR(); + STA_INST(1); + } + break; +case 0x84: /* STY Dloc */ + GET_DLOC_ADDR(); + STY_INST(1); + + + break; +case 0x85: /* STA Dloc */ + GET_DLOC_ADDR(); + STA_INST(1); + + break; +case 0x86: /* STX Dloc */ + GET_DLOC_ADDR(); + STX_INST(1); + + + break; +case 0x87: /* STA [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_ADDR(); + STA_INST(0); + } + break; +case 0x88: /* DEY */ +#ifdef ASM + INC_KPC_1 + bb,< psr,27,inst88_8bit_8 + addi -1,yreg,yreg +/* 16 bit */ + extru yreg,31,16,zero + extru yreg,16,1,neg + b dispatch + copy zero,yreg + +inst88_8bit_8 + extru yreg,31,8,zero + extru yreg,24,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(yreg - 1, yreg); +#endif + + break; +case 0x89: /* BIT #imm */ +#ifdef ASM + GET_IMM_MEM(); +# ifdef ACC8 +/* Immediate BIT does not set condition flags */ + and acc,ret0,zero + b dispatch + extru zero,31,8,zero +# else + and acc,ret0,zero + b dispatch + extru zero,31,16,zero +# endif +#else + GET_IMM_MEM(); +# ifdef ACC8 + zero = (acc & arg) & 0xff; +# else + zero = (acc & arg) & 0xffff; +# endif +#endif + + break; +case 0x8a: /* TXA */ +#ifdef ASM +# ifdef ACC8 + extru xreg,31,8,zero + INC_KPC_1 + extru xreg,24,1,neg + b dispatch + dep zero,31,8,acc +# else + extru xreg,31,16,zero + INC_KPC_1 + extru xreg,16,1,neg + b dispatch + zdep zero,31,16,acc +# endif +#else + INC_KPC_1; + arg = xreg; + LDA_INST(); +#endif + + break; +case 0x8b: /* PHB */ +#ifdef ASM + ldil l%dispatch,link + extru dbank,31,8,arg0 + INC_KPC_1 + b push_8 + ldo r%dispatch(link),link +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + PUSH8(dbank); + } +#endif + + break; +case 0x8c: /* STY abs */ + GET_ABS_ADDR(); + STY_INST(0); + + break; +case 0x8d: /* STA abs */ + GET_ABS_ADDR(); + STA_INST(0); + + break; +case 0x8e: /* STX abs */ + GET_ABS_ADDR(); + STX_INST(0); + + + break; +case 0x8f: /* STA long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_ADDR(); + STA_INST(0); + } + + break; +case 0x90: /* BCC disp8 */ +#ifdef ASM + COND_BR1 + bb,< psr,31,inst90_2_8 + COND_BR2 + +inst90_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x01) == 0); +#endif + + + break; +case 0x91: /* STA (Dloc),y */ + GET_DLOC_IND_Y_ADDR_FOR_WR(); + STA_INST(0); + + break; +case 0x92: /* STA (Dloc) */ + GET_DLOC_IND_ADDR(); + STA_INST(0); + + break; +case 0x93: /* STA (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_ADDR(); + STA_INST(0); + } + break; +case 0x94: /* STY Dloc,x */ + GET_DLOC_X_ADDR(); + STY_INST(1); + + break; +case 0x95: /* STA Dloc,x */ + GET_DLOC_X_ADDR(); + STA_INST(1); + + break; +case 0x96: /* STX Dloc,Y */ + GET_DLOC_Y_ADDR(); + STX_INST(1); + + break; +case 0x97: /* STA [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_ADDR(); + STA_INST(0); + } + break; +case 0x98: /* TYA */ +#ifdef ASM +# ifdef ACC8 + extru yreg,31,8,zero + INC_KPC_1 + extru yreg,24,1,neg + b dispatch + dep zero,31,8,acc +# else + extru yreg,31,16,zero + INC_KPC_1 + extru yreg,16,1,neg + b dispatch + zdep zero,31,16,acc +# endif +#else + INC_KPC_1; + arg = yreg; + LDA_INST(); +#endif + + break; +case 0x99: /* STA abs,y */ + GET_ABS_INDEX_ADDR_FOR_WR(yreg) + STA_INST(0); + + break; +case 0x9a: /* TXS */ +#ifdef ASM + copy xreg,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + INC_KPC_1 + b dispatch + nop +#else + stack = xreg; + if(psr & 0x100) { + stack = 0x100 | (stack & 0xff); + } + INC_KPC_1; +#endif + + + break; +case 0x9b: /* TXY */ +#ifdef ASM + extru xreg,24,1,neg + INC_KPC_1 + extru,<> psr,27,1,0 ;skip next if 8bit + extru xreg,16,1,neg + copy xreg,yreg + b dispatch + copy xreg,zero +#else + IF_OPCODE_SUPPORTED(1) + { + SET_INDEX_REG(xreg, yreg); + INC_KPC_1; + } +#endif + + + break; +case 0x9c: /* STZ Abs */ + GET_ABS_ADDR(); + STZ_INST(0); + + break; +case 0x9d: /* STA Abs,X */ + GET_ABS_INDEX_ADDR_FOR_WR(xreg); + STA_INST(0); + + break; +case 0x9e: /* STZ Abs,X */ + GET_ABS_INDEX_ADDR_FOR_WR(xreg); + STZ_INST(0); + + break; +case 0x9f: /* STA Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_ADDR_FOR_WR(); + STA_INST(0); + } + + break; +case 0xa0: /* LDY #imm */ +#ifdef ASM + INC_KPC_2 + bb,>= psr,27,insta0_16bit_8 + ldb 1(scratch1),zero + + extru zero,24,1,neg + b dispatch + copy zero,yreg +insta0_16bit_8 + ldb 2(scratch1),scratch1 + INC_KPC_1 + CYCLES_PLUS_1 + extru scratch1,24,1,neg + dep scratch1,23,8,zero + b dispatch + copy zero,yreg +#else + INC_KPC_2; + if((psr & 0x10) == 0) { + GET_2BYTE_ARG; + CYCLES_PLUS_1 + INC_KPC_1; + } else { + GET_1BYTE_ARG; + } + SET_INDEX_REG(arg, yreg); +#endif + + + break; +case 0xa1: /* LDA (Dloc,X) */ +/* called with arg = val to LDA in */ + GET_DLOC_X_IND_RD(); + LDA_INST(); + + break; +case 0xa2: /* LDX #imm */ +#ifdef ASM + ldb 1(scratch1),zero + bb,>= psr,27,insta2_16bit_8 + INC_KPC_2; + + extru zero,24,1,neg + b dispatch + copy zero,xreg +insta2_16bit_8 + ldb 2(scratch1),scratch1 + INC_KPC_1 + CYCLES_PLUS_1 + extru scratch1,24,1,neg + dep scratch1,23,8,zero + b dispatch + copy zero,xreg +#else + INC_KPC_2; + if((psr & 0x10) == 0) { + GET_2BYTE_ARG; + CYCLES_PLUS_1 + INC_KPC_1; + } else { + GET_1BYTE_ARG; + } + SET_INDEX_REG(arg, xreg); +#endif + + break; +case 0xa3: /* LDA Disp8,S */ +/* called with arg = val to LDA in */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + LDA_INST(); + } + break; +case 0xa4: /* LDY Dloc */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_WR() + b get_yreg_from_mem + nop +#else + C_LDY_DLOC(); +#endif + + break; +case 0xa5: /* LDA Dloc */ +/* called with arg = val to LDA in */ + GET_DLOC_RD(); + LDA_INST(); + + break; +case 0xa6: /* LDX Dloc */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_WR() + b get_xreg_from_mem + nop +#else + C_LDX_DLOC(); +#endif + + break; +case 0xa7: /* LDA [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + LDA_INST(); + } + break; +case 0xa8: /* TAY */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,insta8_16bit_8 + extru acc,31,8,zero + + extru acc,24,1,neg + b dispatch + copy zero,yreg + +insta8_16bit_8 + extru acc,31,16,zero + extru acc,16,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(acc, yreg); +#endif + + break; +case 0xa9: /* LDA #imm */ + GET_IMM_MEM(); + LDA_INST(); + + break; +case 0xaa: /* TAX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instaa_16bit_8 + extru acc,31,8,zero + + extru acc,24,1,neg + b dispatch + copy zero,xreg + +instaa_16bit_8 + extru acc,31,16,zero + extru acc,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(acc, xreg); +#endif + + break; +case 0xab: /* PLB */ +#ifdef ASM + INC_KPC_1 + bl pull_8,link + CYCLES_PLUS_1 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,dbank +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + CYCLES_PLUS_1 + PULL8(dbank); + SET_NEG_ZERO8(dbank); + } +#endif + + break; +case 0xac: /* LDY abs */ +#ifdef ASM + GET_ABS_ADDR() + b get_yreg_from_mem + nop +#else + C_LDY_ABS(); +#endif + + + break; +case 0xad: /* LDA abs */ + GET_ABS_RD(); + LDA_INST(); + + break; +case 0xae: /* LDX abs */ +#ifdef ASM + GET_ABS_ADDR() + b get_xreg_from_mem + nop +#else + C_LDX_ABS(); +#endif + + break; +case 0xaf: /* LDA long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + LDA_INST(); + } + + break; +case 0xb0: /* BCS disp8 */ +#ifdef ASM + COND_BR1 + bb,>= psr,31,instb0_2_8 + COND_BR2 + +instb0_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x01)); +#endif + + break; +case 0xb1: /* LDA (Dloc),y */ + GET_DLOC_IND_Y_RD(); + LDA_INST(); + + break; +case 0xb2: /* LDA (Dloc) */ + GET_DLOC_IND_RD(); + LDA_INST(); + + break; +case 0xb3: /* LDA (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + LDA_INST(); + } + break; +case 0xb4: /* LDY Dloc,x */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_X_WR(); + b get_yreg_from_mem + nop +#else + C_LDY_DLOC_X(); +#endif + + break; +case 0xb5: /* LDA Dloc,x */ + GET_DLOC_X_RD(); + LDA_INST(); + + break; +case 0xb6: /* LDX Dloc,y */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_Y_WR(); + b get_xreg_from_mem + nop +#else + C_LDX_DLOC_Y(); +#endif + + break; +case 0xb7: /* LDA [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + LDA_INST(); + } + break; +case 0xb8: /* CLV */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,25,1,psr /* clear overflow */ +#else + psr = psr & ~0x40; + INC_KPC_1; +#endif + + break; +case 0xb9: /* LDA abs,y */ + GET_ABS_Y_RD(); + LDA_INST(); + + break; +case 0xba: /* TSX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instba_16bit_8 + extru stack,31,8,zero + + extru stack,24,1,neg + b dispatch + copy zero,xreg +instba_16bit_8 + copy stack,zero + extru stack,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(stack, xreg); +#endif + + break; +case 0xbb: /* TYX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instbb_16bit_8 + copy yreg,xreg + +/* 8 bit */ + extru yreg,24,1,neg + b dispatch + copy yreg,zero +instbb_16bit_8 + extru yreg,16,1,neg + b dispatch + copy yreg,zero +#else + IF_OPCODE_SUPPORTED(1) + { + INC_KPC_1; + SET_INDEX_REG(yreg, xreg); + } +#endif + + break; +case 0xbc: /* LDY Abs,X */ +#ifdef ASM + GET_ABS_INDEX_ADDR_FOR_RD(xreg) + b get_yreg_from_mem + nop +#else + C_LDY_ABS_X(); +#endif + + break; +case 0xbd: /* LDA Abs,X */ + GET_ABS_X_RD(); + LDA_INST(); + + break; +case 0xbe: /* LDX Abs,y */ +#ifdef ASM + GET_ABS_INDEX_ADDR_FOR_RD(yreg) + b get_xreg_from_mem + nop +#else + C_LDX_ABS_Y(); +#endif + + break; +case 0xbf: /* LDA Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + LDA_INST(); + } + + break; +case 0xc0: /* CPY #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + bb,>= psr,27,instc0_16bit_8 + INC_KPC_2; + CMP_INDEX_REG_MEAT8(yreg) +instc0_16bit_8 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + INC_KPC_1 + dep scratch1,23,8,ret0 + CMP_INDEX_REG_MEAT16(yreg) +#else + C_CPY_IMM(); +#endif + + + break; +case 0xc1: /* CMP (Dloc,X) */ +/* called with arg = val to CMP in */ + GET_DLOC_X_IND_RD(); + CMP_INST(); + + break; +case 0xc2: /* REP #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_2; + dep neg,24,1,psr + CYCLES_PLUS_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + andcm psr,ret0,ret0 + ldi 0,zero + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + b update_system_state + extru ret0,24,1,neg +#else + IF_OPCODE_SUPPORTED(2) // 0xC2 + { + GET_1BYTE_ARG; + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_2; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + psr = psr & ~(arg & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); + } +#endif + + + break; +case 0xc3: /* CMP Disp8,S */ +/* called with arg = val to CMP in */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + CMP_INST(); + } + break; +case 0xc4: /* CPY Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + CMP_INDEX_REG_LOAD(instc4_16bit_8, yreg) +#else + C_CPY_DLOC(); +#endif + + + break; +case 0xc5: /* CMP Dloc */ + GET_DLOC_RD(); + CMP_INST(); + + break; +case 0xc6: /* DEC Dloc */ + GET_DLOC_RD(); + DEC_INST(1); + + break; +case 0xc7: /* CMP [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + CMP_INST(); + } + break; +case 0xc8: /* INY */ +#ifdef ASM + INC_KPC_1 + addi 1,yreg,yreg + bb,>= psr,27,instc8_16bit_8 + extru yreg,31,8,zero + + extru yreg,24,1,neg + b dispatch + copy zero,yreg + +instc8_16bit_8 + extru yreg,31,16,zero + extru yreg,16,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(yreg + 1, yreg); +#endif + + break; +case 0xc9: /* CMP #imm */ + GET_IMM_MEM(); + CMP_INST(); + + break; +case 0xca: /* DEX */ +#ifdef ASM + INC_KPC_1 + addi -1,xreg,xreg + bb,>= psr,27,instca_16bit_8 + extru xreg,31,8,zero + + extru xreg,24,1,neg + b dispatch + copy zero,xreg + +instca_16bit_8 + extru xreg,31,16,zero + extru xreg,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(xreg - 1, xreg); +#endif + + break; +case 0xcb: /* WAI */ +#ifdef ASM + ldil l%g_sim65816.g_wait_pending,scratch1 + CYCLES_FINISH + ldi 1,scratch2 + b dispatch + stw scratch2,r%g_sim65816.g_wait_pending(scratch1) +#else + IF_OPCODE_SUPPORTED(1) + { + g_sim65816.g_wait_pending = 1; + CYCLES_FINISH + } +#endif + + break; +case 0xcc: /* CPY abs */ +#ifdef ASM + GET_ABS_ADDR() + CMP_INDEX_REG_LOAD(instcc_16bit_8, yreg) +#else + C_CPY_ABS(); +#endif + + + + + break; +case 0xcd: /* CMP abs */ + GET_ABS_RD(); + CMP_INST(); + + break; +case 0xce: /* DEC abs */ + GET_ABS_RD(); + DEC_INST(0); + + + break; +case 0xcf: /* CMP long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + CMP_INST(); + } + + break; +case 0xd0: /* BNE disp8 */ +#ifdef ASM + COND_BR1 + comib,= 0,zero,instd0_2_8 + COND_BR2 + +instd0_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(zero != 0); +#endif + + break; +case 0xd1: /* CMP (Dloc),y */ + GET_DLOC_IND_Y_RD(); + CMP_INST(); + + break; +case 0xd2: /* CMP (Dloc) */ + GET_DLOC_IND_RD(); + CMP_INST(); + + break; +case 0xd3: /* CMP (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + CMP_INST(); + } + break; +case 0xd4: /* PEI Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + bl get_mem_long_16,link + CYCLES_PLUS_1 + +/* push ret0 */ + extru ret0,31,16,arg0 + ldil l%dispatch,link + b push_16_unsafe + ldo r%dispatch(link),link +#else + IF_OPCODE_SUPPORTED(2) // 0xD4 + { + GET_DLOC_ADDR() + GET_MEMORY16(arg, arg, 1); + CYCLES_PLUS_1; + PUSH16_UNSAFE(arg); + } +#endif + + break; +case 0xd5: /* CMP Dloc,x */ + GET_DLOC_X_RD(); + CMP_INST(); + + break; +case 0xd6: /* DEC Dloc,x */ + GET_DLOC_X_RD(); + DEC_INST(1); + + break; +case 0xd7: /* CMP [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + CMP_INST(); + } + break; +case 0xd8: /* CLD */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,28,1,psr /* clear decimal */ +#else + psr = psr & (~0x8); + INC_KPC_1; +#endif + + break; +case 0xd9: /* CMP abs,y */ + GET_ABS_Y_RD(); + CMP_INST(); + + break; +case 0xda: /* PHX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instda_16bit_8 + ldil l%dispatch,link + + extru xreg,31,8,arg0 + b push_8 + ldo r%dispatch(link),link + +instda_16bit_8 + extru xreg,31,16,arg0 + b push_16 + ldo r%dispatch(link),link +#else + INC_KPC_1; + if(psr & 0x10) { + PUSH8(xreg); + } else { + PUSH16(xreg); + } +#endif + + break; +case 0xdb: /* STP */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_1 + b dispatch_done + depi RET_STP,3,4,ret0 +#else + IF_OPCODE_SUPPORTED(1) + { + CYCLES_FINISH + FINISH(RET_STP, 0); + } +#endif + + break; +case 0xdc: /* JML (Abs) */ +#ifdef ASM + ldb 1(scratch1),arg0 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + bl get_mem_long_24,link + dep scratch1,23,8,arg0 + + b dispatch + copy ret0,kpc +#else + IF_OPCODE_SUPPORTED(2) // 0xDC + { + GET_2BYTE_ARG; + CYCLES_PLUS_1; + GET_MEMORY24(arg, kpc, 1); + } +#endif + + break; +case 0xdd: /* CMP Abs,X */ + GET_ABS_X_RD(); + CMP_INST(); + + break; +case 0xde: /* DEC Abs,X */ + GET_ABS_X_RD_WR(); + DEC_INST(0); + + break; +case 0xdf: /* CMP Long,X */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + CMP_INST(); + } + + break; +case 0xe0: /* CPX #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + bb,>= psr,27,inste0_16bit_8 + INC_KPC_2; + CMP_INDEX_REG_MEAT8(xreg) +inste0_16bit_8 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + INC_KPC_1 + dep scratch1,23,8,ret0 + CMP_INDEX_REG_MEAT16(xreg) +#else + C_CPX_IMM(); +#endif + + + break; +case 0xe1: /* SBC (Dloc,X) */ +/* called with arg = val to SBC in */ + GET_DLOC_X_IND_RD(); + SBC_INST(); + + break; +case 0xe2: /* SEP #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_2; + dep neg,24,1,psr + CYCLES_PLUS_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + or psr,ret0,ret0 + ldi 0,zero + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + b update_system_state + extru ret0,24,1,neg +#else + IF_OPCODE_SUPPORTED(2) // 0xE2 + { + GET_1BYTE_ARG; + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_2; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + psr = psr | (arg & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); + } +#endif + + + break; +case 0xe3: /* SBC Disp8,S */ +/* called with arg = val to SBC in */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_RD(); + SBC_INST(); + } + break; +case 0xe4: /* CPX Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + CMP_INDEX_REG_LOAD(inste4_16bit_8, xreg) +#else + C_CPX_DLOC(); +#endif + + + break; +case 0xe5: /* SBC Dloc */ +/* called with arg = val to SBC in */ + GET_DLOC_RD(); + SBC_INST(); + + break; +case 0xe6: /* INC Dloc */ + GET_DLOC_RD(); + INC_INST(1); + + break; +case 0xe7: /* SBC [Dloc] */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_RD(); + SBC_INST(); + } + break; +case 0xe8: /* INX */ +#ifdef ASM + INC_KPC_1 + addi 1,xreg,xreg + bb,>= psr,27,inste8_16bit_8 + extru xreg,31,8,zero + + extru xreg,24,1,neg + b dispatch + copy zero,xreg + +inste8_16bit_8 + extru xreg,31,16,zero + extru xreg,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(xreg + 1, xreg); +#endif + + break; +case 0xe9: /* SBC #imm */ + GET_IMM_MEM(); + SBC_INST(); + + break; +case 0xea: /* NOP */ +#ifdef ASM + INC_KPC_1 + b dispatch + nop +#else + INC_KPC_1; +#endif + + break; +case 0xeb: /* XBA */ +#ifdef ASM + extru acc,16,1,neg /* Z and N reflect status of low 8 */ + CYCLES_PLUS_1 /* bits of final acc value! */ + copy acc,scratch1 /* regardlessof ACC 8 or 16 bit */ + extru acc,23,8,acc + INC_KPC_1 + copy acc,zero + b dispatch + dep scratch1,23,8,acc +#else + IF_OPCODE_SUPPORTED(1) + { + tmp1 = acc & 0xff; + CYCLES_PLUS_1 + acc = (tmp1 << 8) + (acc >> 8); + INC_KPC_1; + SET_NEG_ZERO8(acc & 0xff); + } +#endif + + break; +case 0xec: /* CPX abs */ +#ifdef ASM + GET_ABS_ADDR() + CMP_INDEX_REG_LOAD(instec_16bit_8, xreg) +#else + C_CPX_ABS(); +#endif + + + + + break; +case 0xed: /* SBC abs */ + GET_ABS_RD(); + SBC_INST(); + + break; +case 0xee: /* INC abs */ + GET_ABS_RD(); + INC_INST(0); + + + break; +case 0xef: /* SBC long */ + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_RD(); + SBC_INST(); + } + + break; +case 0xf0: /* BEQ disp8 */ +#ifdef ASM + COND_BR1 + comib,<> 0,zero,instf0_2_8 + COND_BR2 + +instf0_2_8 + COND_BR_UNTAKEN +#else + BRANCH_DISP8(zero == 0); +#endif + + break; +case 0xf1: /* SBC (Dloc),y */ + GET_DLOC_IND_Y_RD(); + SBC_INST(); + + break; +case 0xf2: /* SBC (Dloc) */ + GET_DLOC_IND_RD(); + SBC_INST(); + + break; +case 0xf3: /* SBC (Disp8,s),y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DISP8_S_IND_Y_RD(); + SBC_INST(); + } + break; +case 0xf4: /* PEA Abs */ +#ifdef ASM + ldb 1(scratch1),arg0 + ldil l%dispatch,link + ldb 2(scratch1),scratch1 + INC_KPC_3 + CYCLES_PLUS_1 + ldo r%dispatch(link),link + b push_16_unsafe + dep scratch1,23,8,arg0 +#else + IF_OPCODE_SUPPORTED(2) // 0xF4 + { + GET_2BYTE_ARG; + CYCLES_PLUS_1; + INC_KPC_3; + PUSH16_UNSAFE(arg); + } +#endif + + break; +case 0xf5: /* SBC Dloc,x */ + GET_DLOC_X_RD(); + SBC_INST(); + + break; +case 0xf6: /* INC Dloc,x */ + GET_DLOC_X_RD(); + INC_INST(1); + + break; +case 0xf7: /* SBC [Dloc],Y */ + IF_OPCODE_SUPPORTED(1) + { + GET_DLOC_L_IND_Y_RD(); + SBC_INST(); + } + break; +case 0xf8: /* SED */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,28,1,psr /* set decimal */ +#else + INC_KPC_1; + psr |= 0x8; +#endif + + break; +case 0xf9: /* SBC abs,y */ + GET_ABS_Y_RD(); + SBC_INST(); + + break; +case 0xfa: /* PLX */ +#ifdef ASM + bb,< psr,27,instfa_8bit_8 + CYCLES_PLUS_1 + + INC_KPC_1 + bl pull_16,link + nop + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,xreg + +instfa_8bit_8 + INC_KPC_1 + bl pull_8,link + nop + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + CYCLES_PLUS_1; + if(psr & 0x10) { + PULL8(xreg); + SET_NEG_ZERO8(xreg); + } else { + PULL16(xreg); + SET_NEG_ZERO16(xreg); + } +#endif + + break; +case 0xfb: /* XCE */ +#ifdef ASM + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_1 + extru psr,23,1,scratch1 /* e bit */ + dep psr,23,1,psr /* copy carry to e bit */ + b update_system_state + dep scratch1,31,1,psr /* copy e bit to carry */ +#else + IF_OPCODE_SUPPORTED(1) + { + tmp2 = psr; + INC_KPC_1; + psr = (tmp2 & 0xfe) | ((tmp2 & 1) << 8) | ((tmp2 >> 8) & 1); + UPDATE_PSR(psr, tmp2); + } +#endif + + break; +case 0xfc: /* JSR (Abs,X) */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru kpc,15,8,scratch2 + ldb 2(scratch1),scratch1 + dep scratch2,15,16,ret0 + INC_KPC_2; + dep scratch1,23,8,ret0 + add xreg,ret0,arg0 + bl get_mem_long_16,link + extru arg0,31,24,arg0 + + CYCLES_PLUS_2 + extru kpc,31,16,arg0 + ldil l%dispatch,link + dep ret0,31,16,kpc + b push_16_unsafe + ldo r%dispatch(link),link +#else + IF_OPCODE_SUPPORTED(2) // 0xFC + { + GET_2BYTE_ARG; + INC_KPC_2; + tmp1 = kpc; + arg = (kpc & 0xff0000) + ((arg + xreg) & 0xffff); + GET_MEMORY16(arg, tmp2, 1); + kpc = (kpc & 0xff0000) + tmp2; + CYCLES_PLUS_2 + PUSH16_UNSAFE(tmp1); + } +#endif + + break; +case 0xfd: /* SBC Abs,X */ + GET_ABS_X_RD(); + SBC_INST(); + + break; +case 0xfe: /* INC Abs,X */ + GET_ABS_X_RD_WR(); + INC_INST(0); + + break; +case 0xff: /* SBC Long,X */ + + + IF_OPCODE_SUPPORTED(1) + { + GET_LONG_X_RD(); + SBC_INST(); + } + \ No newline at end of file diff --git a/kegs/Src/GraphCounter.cpp b/kegs/Src/GraphCounter.cpp new file mode 100644 index 0000000..8b0857e --- /dev/null +++ b/kegs/Src/GraphCounter.cpp @@ -0,0 +1,209 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "video.h" +#include "sim65816.h" +#include "GraphCounter.h" +#include "raster.h" + +#ifdef ENABLE_GRAPH + +s_graph g_graph; + +#define GRAPH_X 0 +#define GRAPH_Y 100 + + +void s_graph::add_graph(int _counter, float _value, int _vblcount) +{ + int v = _vblcount%NB_GRAPH_VALUES; + values[_counter][v]=_value; +// printf("addgraph (%d)(%f) vbl:%d %f\n", _counter,g_sim65816.g_last_vbl_dcycs,_vblcount,_value); +} + +s_graph::s_graph() +{ + + memset(this,0,sizeof(*this)); + + // Counter 0 = frame rate + min[0] = 5.0f; + max[0] = 60.0f; + ref[0] = 10.0f; + color[0]=0xFF0000; // RED + + // Counter 1 = frame/sleep precision + min[1] = 55.0f; + max[1] = 65.0f; + ref[1] = 60.0f; + color[1]=0x00FFFF; + + // Counter 2 = c054/page flipping + min[2] = 5.0f; + max[2] = 20.0f; + ref[2] = 10.0f; + color[2]=0xFFFFFF; + + // Counter 3 = sleep precision + min[3] = -.020f; + max[3] = 0.020f; + ref[3] = 0.0f; + color[3]=0x00FF00; + + +} + + + +void s_graph::draw_graph(Kimage* _dest, int _curvbl) +{ + if (!_dest->data_ptr) return ; + // Clear Rect + + int pw = (_dest->mdepth >> 3); + int wd = _dest->width_act*pw; + byte* ptr = _dest->data_ptr + GRAPH_X*pw + GRAPH_Y*wd; + for(int h=0;h=0 && hdata_ptr+ (h+GRAPH_Y)*wd + (v+GRAPH_X)*pw ) ; + *ptr2 = 0xFF; + } + int i = (_curvbl -v + NB_GRAPH_VALUES)%NB_GRAPH_VALUES; + float va = values[c][i]; + m = (va - min[c]); + + h = (int)( m*NB_GRAPH_HEIGHT/d ); + if (h>=0 && hdata_ptr+ (h+GRAPH_Y)*wd + (v+GRAPH_X)*pw ) ; + *ptr = color[c]; + } + + + + } + } +} + +#endif + +#ifdef BORDER_SCAN + +#define NB_BORDER 3 +#define MAX_BORDER 100 +int iBorder[NB_BORDER]; +double reftime=0.0; +int borders[NB_BORDER][MAX_BORDER]; +int colors[NB_BORDER][MAX_BORDER]; + +extern int screenHeight; + +void change_border(int c,int _color) +{ + double t = get_dtime(); + double d = t - reftime; + int l; +#ifdef WIN32 + if (c==2) + { + extern int screenHeight; + l = getScanLine() * (float)X_A2_WINDOW_HEIGHT/(float)screenHeight; + } + else +#endif + l = d * X_A2_WINDOW_HEIGHT / (1/60.0); + + if (l<0) l=0; + if (l>X_A2_WINDOW_HEIGHT) l=X_A2_WINDOW_HEIGHT; + + + borders[c][iBorder[c]]=l; + colors[c][iBorder[c]++]=_color; +// ASSERT(iBorderwidth_act * (image->mdepth >> 3); + + + // cherche le plus petit scanline + int min=1000000; + int imin=-1; + for(int k=0;kdata_ptr ; + for(int i=0;iheight;i+=1) + { + if (i>borders[c][imin] && !done) + { + col = colors[c][imin]; + imin++; + if (imin>=iBorder[c]) + imin=0; + if (imin==istart) + done=1; + + } + for(int j=0;j<32;j++) + ((word32*)ptrdest)[00+j+c*32] = col ; + + // memset(ptrdest,col,bitmapBytesPerRow); + ptrdest += bitmapBytesPerRow; + // col += 10; + } + } +#endif + reset_border(); +} + +void reset_border() +{ + for(int c=0;c> 3 ); + offscreen.size = wb * g_kimage_offscreen.height / STEP ; + offscreen.fastalloc = fastalloc; + offscreen.data = (byte*)x_malloc( offscreen.size,fastalloc ); + if (!offscreen.data) + x_fatal_exit("out of memory error!"); + byte* ptrs = (byte*)g_kimage_offscreen.data_ptr; + byte* ptrd = (byte*)offscreen.data; + + + for(int h=0;h> 3; + + temp.data_ptr = (byte*)malloc(X_A2_WINDOW_WIDTH*X_A2_WINDOW_HEIGHT*pb); + +#ifdef VIDEO_SINGLEVLINE + // restore l'offscreen l'identique + int wb = temp.width_act * pb; + byte* ptrs = (byte*)offscreen.data; + byte* ptrd = (byte*)temp.data_ptr; + + for(int h=0;h pour profiter des effets post prod + x_push_kimage(&temp,0,0,0,0,temp.width_req,temp.height); + + offscreen.releaseuncompressed(); + + // libre le fichier temp + free(temp.data_ptr ); + + refresh_video(1); +// double dtime = get_dtime(); +// double delay = dtime - lastcycs; +// lastcycs = dtime; + +// debug_printf("displaying frame:%d (%f)\n",vbl,delay); +#endif + +} + +void s_savestate::handleKey(int _key,int _isup) +{ + #if (!defined(MAC) || defined(ACTIVEGSPLUGIN)) && !defined(ACTIVEGS_NOSAVESTATE) + if (!_isup && (_key == 0x3B || _key == 0x3C || _key == 0x24 /*RET*/|| _key == 0x60 /*VK_F5*/ ) ) + { + if (_key == 0x24 || _key == 0x60) + { + + r_sim65816.set_state(RUNNING); + return ; + } + + + int next ; + if (iCurState==-1) + { + // TODO A AMELIORER + iCurState = (MAX_STATE+iNextState -1 )%MAX_STATE; + } + + if (_key==0x3B) + { + targetStateSens = 0; + + // vrifie qu'il y a encore une clef + + int next = (MAX_STATE+iCurState -1 )%MAX_STATE; + while(next != iNextState ) + { + if (states[next].isEmpty()) + // plus de clef + break; + if (states[next].fullsave) + { + targetStateSens = -1; + break; + } + next = (MAX_STATE+next -1 )%MAX_STATE; + + } + if (!targetStateSens) + + printf("begin rewind\n"); + + } + else + { + targetStateSens = +1; + next = (MAX_STATE+iCurState +1 )%MAX_STATE; + + if (next == iNextState || states[next].isEmpty() ) + { + targetStateSens = 0; + iCurState=-1; + printf("end rewind\n"); + return ; + } + } + + } +#endif +} + + +int s_savestate::getSavedStateVBL() +{ + return state.param.vbl; + +} + + +void s_savestate::saveState(const char* _filename) +{ + if (r_sim65816.get_state() ==IN_PAUSE) + { + // en pause, sauve immdiatement (sauf si on est en mode rewind + + if (iCurState!=-1) + { + printf("cannot save state if rewind has started"); + return ; + } + if (_filename==NULL) + { + // save to memory + state.save(1,0); + debug_printf("save state @%d \n",state->vbl); + } + else + { + savedState temp; + temp.save(1,0); + temp.writeToDisk(_filename); + } + + return ; + } + + + stateActionRequired=STATE_SAVE; + filename = _filename; + +} + + +void s_savestate::restoreState(const char* _filename) +{ + + + if (r_sim65816.get_state() ==IN_PAUSE) + { + // en pause, on peut faire le restore immdiatement (si on est pas en mode rewind) + + if (iCurState!=-1) + { + printf("cannot restore state if rewind has started"); + return ; + } + if (_filename==NULL) + { + if (!state.isEmpty()) + { + // on est revenu une position quelconque : le rewind n'a plus de sens + state.restore(); + reset_rewind(); + } + } + else + { + savedState temp; + int ret = temp.loadFromDisk(_filename); + if (ret) + { + temp.restore(); + reset_rewind(); + } + } + + return ; + } + + // prpare le save la prochaine boucle + stateActionRequired=STATE_RESTORE; + filename = _filename; + +} + + +void s_savestate::delete_state(int pos) +{ + if (states[pos].isEmpty()) return ; + + states[pos].release(); + + // dtruit les tat prsents jusqu' la prochaine clef + int deleteState=(pos +1 )%MAX_STATE; + while(deleteState!=pos) + { + if (states[deleteState].isEmpty()) break; + if (states[deleteState].fullsave) + // on a trouv la prochaine clef : on s'arrete + break; + // dtruit les cran intermdiaires + states[deleteState].release(); + debug_printf("deleting state:%d\n",deleteState); + deleteState=(deleteState +1 )%MAX_STATE; + } +} + + +void s_savestate::handleState() +{ + +// double d = get_dtime(); + #if (!defined(MAC) || defined(ACTIVEGSPLUGIN)) && !defined(ACTIVEGS_NOSAVESTATE) + + if (r_sim65816.should_emulator_terminate()) +{ + printf("ignoring handleState : emulator is quitting...\n"); + return ; + } + + iCurState = -1; + + int b = r_sim65816.get_rewind_enable(); + + int savescreen = ( b && g_sim65816.g_vbl_count >= nextScreenVBL ) ; + int s = r_sim65816.get_state(); + int fullsave = b && ( g_sim65816.g_vbl_count>=nextStateVBL || s==IN_PAUSE) ; + + if (savescreen||fullsave) + { + nextScreenVBL = g_sim65816.g_vbl_count + VBL_DELAY_BETWEEN_SCREEN ; + + delete_state(iNextState); + + // s'assure que l'on a assez de mmoire libre + int n = (iNextState +1 )%MAX_STATE; + while( 1) + { + int f = get_free_memory_size(); + if ( f> (int)savedState::maxSize*1.20 ) + break; + if (!states[n].isEmpty()) + { + debug_printf("only %dKB remaining : trying to free space\n",f/1024); + delete_state(n); + debug_printf("now %dKB!\n",get_free_memory_size()/1204); + } + n = (n +1 )%MAX_STATE; + if (n == iNextState) + { + x_fatal_exit("err: out of memory error"); + } + + } + + // capture l'tat courant + states[iNextState].save(fullsave,1); + + // positionne la prochaine place libre + iNextState = (iNextState +1 )%MAX_STATE; + + if (fullsave) + nextStateVBL = g_sim65816.g_vbl_count+NB_SCREEN_PER_STATE*VBL_DELAY_BETWEEN_SCREEN; + + } + else + g_compression.process_jobs(1); + + + switch( stateActionRequired) + { + case STATE_SAVE: + // if (filename.IsEmpty()) + if (filename[0]==0) + + { + state.save(1,0); + debug_printf("save state @ \n",state->vbl); + } + else + { + savedState temp; + temp.save(1,0); + temp.writeToDisk(filename); + } + + stateActionRequired = STATE_NONE; + break; + + case STATE_RESTORE: + // if (filename.IsEmpty()) + if (filename[0]==0) + { + if (!state.isEmpty()) + { + // on est revenu une position quelconque : le rewind n'a plus de sens + state.restore(); + reset_rewind(); + } + } + else + { + savedState temp; + int ret = temp.loadFromDisk(filename); + if (ret) + { + temp.restore(); + reset_rewind(); + } + } + + + stateActionRequired = STATE_NONE; + break ; + + case STATE_NONE: + + + // if (r_sim65816.get_state() == IN_PAUSE) + if (s == PAUSE_REQUESTED ) // !!!! L'ETAT PEUT AVOIR CHANGE DEPUIS LE DEBUT DE LA FONCTION : NE LE RELIT PAS! + { + r_sim65816.set_state(IN_PAUSE); + printf("in pause (cache=%dMB, maxStateSize=%dMB)\n",cacheSize/(1024*1024),savedState::maxSize/(1024*1024)); + + while(r_sim65816.get_state() == IN_PAUSE || ( iCurState!=-1 && !states[iCurState].isEmpty() && !states[iCurState].fullsave ) ) + { + if (r_sim65816.should_emulator_terminate()) + { + printf("aborting PAUSE mode...\n"); + r_sim65816.set_state(RUNNING); + return; + } + x_sleep(1); // 50hz + + if (targetStateSens) + { + double dtime = get_dtime(); + double delaysincelastrefresh = dtime - lastrefreshcycs; + if (delaysincelastrefresh > VBL_DELAY_BETWEEN_SCREEN/2/60.0) + { + if (targetStateSens>0) + iCurState = (iCurState +1 )%MAX_STATE; + else + iCurState = (MAX_STATE+iCurState -1 )%MAX_STATE; + + states[iCurState].display(); + + if (states[iCurState].fullsave) + targetStateSens = 0; + else + lastrefreshcycs = dtime; + + } + + } + + } + + printf("out pause\n"); + + + if (iCurState!=-1) + { + + if (!states[iCurState].isEmpty()) + states[iCurState].restore(); + + int n = (iCurState+1)%MAX_STATE; + while(n!=iNextState) + { + delete_state(n); + n = ( n + 1 ) % MAX_STATE; + } + iNextState = (iCurState+1)%MAX_STATE; + + nextScreenVBL = g_sim65816.g_vbl_count + VBL_DELAY_BETWEEN_SCREEN; + nextStateVBL = g_sim65816.g_vbl_count + NB_SCREEN_PER_STATE*VBL_DELAY_BETWEEN_SCREEN; + + } + + } + break; + } +#endif +// double delay = get_dtime() - d; +// g_graph.add_graph(1,delay,g_sim65816.g_vbl_count); + +} + + +#define CHECK_RESTORE_VAR(CLASS,VAR) \ + if ( g_##CLASS.VAR != ((s_##CLASS*)(##CLASS.data))->##VAR) \ + printf("serialization error for var "#CLASS"."#VAR" %d vs. %d",g_##CLASS.VAR,((s_##CLASS*)(##CLASS.data))->##VAR); + +#define CHECK_RESTORE_CLASS(CLASS) \ + if ( sizeof(s_##CLASS) != ((s_##CLASS*)(##CLASS.data))->_size) \ + printf("serialization error for class "#CLASS" %d vs. %d\n",sizeof(s_##CLASS),((s_##CLASS*)(##CLASS.data))->_size ); + +#define SAVE_VERSION 0x01020304 + +void serialize::save(const char*_name,void* _fileptr) +{ + + FILE* f= (FILE*)_fileptr; + fwrite(_name,1,4,f); + word32 version = SAVE_VERSION; + fwrite(&version,1,sizeof(version),f); + fwrite(&size,1,sizeof(size),f); + fwrite(data,1,size,f); + +} + +int serialize::load(const char*_name,void* _fileptr) +{ + char name[5]; + memset(name,0,5); + FILE* f= (FILE*)_fileptr; + fread(name,1,4,f); + if (strcmp(name,_name)) + { + printf("#%s save state name mismatch(%s vs %s)\n",_name,_name,name); + return 0; + } + + word32 version = 0; + fread(&version,1,sizeof(version),f); + if (version != SAVE_VERSION) + { + printf("#%s save state version mismatch(%X vs %X)\n",_name,version,SAVE_VERSION); + return 0; + } + + int nbread = fread(&size,1,sizeof(size),f); + if (nbread !=4) + { + printf("#%s save state size mismatch(%d)\n",_name,size); + return 0; + } + + fastalloc = 0; + data = (void*)malloc(size); + nbread = fread(data,1,size,f); + if (nbread!=size) + { + printf("#%s save state data mismatch(%d vs %d)\n",_name,nbread,size); + return 0; + } + + return 1; +} + +void savedState::writeToDisk(const char* _filename) +{ + if (isEmpty()) + { + printf("nothing to save"); + return ; + } + if (_filename==NULL) + { + printf("no filename"); + return ; + } + FILE* f= fopen(_filename,"wb"); + if (f==NULL) + { + printf("cannot create file"); + return ; + } + + fwrite(¶m,1,sizeof(savedStateParam),f); + + adb.save("adb ",f); + async_event.save("asyn",f); + clock.save("cloc",f); + iwm.save("iwm ",f); + moremem.save("more",f); + paddles.save("padd",f); + scc.save("scc ",f); + sim65816.save("sim6",f); + sound.save("soun",f); + video.save("vide",f); +// offscreen.save("offs",f); ne sauve pas l'offscreen + + + + + fclose(f); +} + +int savedState::loadFromDisk(const char* _filename) +{ + release(); + int ret = loadFromDiskInternal(_filename); + if (!ret) + release(); + return ret; +} + +int savedState::loadFromDiskInternal(const char* _filename) +{ + + FILE* f= fopen(_filename,"rb"); + if (f==NULL) + { + printf("cannot load %s\n",_filename); + return 0; + } + + int nbread = fread(¶m,1,sizeof(savedStateParam),f); + if (nbread!=sizeof(savedStateParam)) + { + printf("could not read savedStateParam\n"); + return 0; + } + if (param.size != sizeof(savedStateParam)) + { + printf("alignement mismatch\n"); + return 0; + } + + if (param.version != SAVEDSTATE_SIG) + { + printf("invalid sig\n"); + return 0; + } + + int ret = adb.load("adb ",f); + if (ret==0) + return 0; + + ret = async_event.load("asyn",f); + if (ret==0) + return 0; + + clock.load("cloc",f); + if (ret==0) + return 0; + + iwm.load("iwm ",f); + if (ret==0) + return 0; + + moremem.load("more",f); + if (ret==0) + return 0; + + paddles.load("padd",f); + if (ret==0) + return 0; + + scc.load("scc ",f); + if (ret==0) + return 0; + + sim65816.load("sim6",f); + if (ret==0) + return 0; + + sound.load("soun",f); + if (ret==0) + return 0; + + video.load("vide",f); + if (ret==0) + return 0; + + offscreen.release(); + /* + offscreen.load("offs",f); + if (ret==0) + return 0; + */ + + + return 1; +} + +void savedState::restore() +{ + //writeToDisk("d:\\temp\\test.bin"); + + if (isEmpty()) + { + printf("nothing to restore!\n"); + return ; + } + +#if (!defined(MAC) || defined(ACTIVEGSPLUGIN)) && !defined(ACTIVEGS_NOSAVESTATE) + + debug_printf("current state :vbl:%d dcycs:%f last_vbl_dcys:%f\n",g_sim65816.g_vbl_count,g_sim65816.g_cur_dcycs,g_sim65816.g_last_vbl_dcycs); + +#ifdef WIN32 + CHECK_RESTORE_CLASS(sim65816); + CHECK_RESTORE_VAR(sim65816,g_mem_size_total); +#endif + g_adb.in(&adb); + g_async_event.in(&async_event); + g_clock.in(&clock); + g_iwm.in(&iwm); + g_moremem.in(&moremem); + g_paddles.in(&paddles); + g_scc.in(&scc); + g_sim65816.in(&sim65816); + g_sound.in(&sound); + g_video.in(&video); + + r_sim65816.request_update_emulator_runtime_config(); + display(); + printf("restoring vbl:%d dcycs:%f last_vbl_dcys:%f\n",param.vbl,param.dcycs,g_sim65816.g_last_vbl_dcycs); + +#endif +} + +void s_savestate::init() +{ +#ifdef WIN32 + MEMORYSTATUS memStatus = {0}; + ::GlobalMemoryStatus(&memStatus); + DWORD dwTotalPhys =memStatus.dwTotalPhys; + printf("Total physical memory: %u MB\n", dwTotalPhys / (1024*1024) ); +#endif + + reset_rewind(); + + stateActionRequired=STATE_NONE; + state.release(); + +#ifdef CACHE_SIZE + cache = (byte*)malloc(CACHE_SIZE); + printf("Nb State = %d\n",MAX_STATE); + printf("Max replay = %fs\n",(float)MAX_STATE/60.0); + printf("Key duration = %fs\n",(float)(NB_SCREEN_PER_STATE*VBL_DELAY_BETWEEN_SCREEN)/60.0); +#else + cache=NULL; +#endif + cachefree = 0; + cachepos = 0; + cacheSize= 0; + + +} + + +void* s_savestate::x_free(void* _data,int _size, int _fastalloc) +{ + if (!cache || !_fastalloc) + { + free(_data); + return NULL; + } + + int pos = (intptr_t)_data - (intptr_t)cache; + + // xxxx#######xxFREEE....POS##### + + //printf("freeing :%d (size:%d)\n",pos,_size); + // POSxxxxxx######xxxxFREEE + + if (cachepos<=pos || cachepos>cachefree) + { + cachepos = pos + _size; + // printf("newpos:%d\n",cachepos); + } + + cacheSize -= _size; + return NULL; +} + +int s_savestate::get_free_memory_size() +{ +#ifdef CACHE_SIZE + int p = cachepos; + int f = cachefree; + + if (f>=p) + // #####POS.....FREE####### + return MAX(p,CACHE_SIZE-f); + else + // ....FREE#####POS... + return p-f; +#else + return 0; +#endif +} + +void* x_free(void* _data,int _size, int _fastalloc) +{ + return g_savestate.x_free(_data,_size,_fastalloc); + +} + +void* s_savestate::x_malloc(int _size, int _fastalloc) +{ + + if (!cache || !_fastalloc) + { + void* p = (void*)malloc(_size); + if (!p) + x_fatal_exit("Out of Memory Error : relaunch with rewind mode off"); + cacheSize+=_size; + return p; + } +#ifndef CACHE_SIZE + // ne doit jamais arriver + return NULL; +#else + int c = cachefree; + + if (c >= cachepos) + { + // ......POS#####################FREE......... + + if (c+_size > CACHE_SIZE) + { + // on boucle + c = 0; + // FREEE......POS#####################00000000 + if (c+_size > cachepos) + { + printf("x_malloc : out of memory error\n"); + return NULL; + } + } + else + { + // ok + } + } + else + { + // ######FREE......POS########################## + + if (c+_size < cachepos) + { + // il y a de la place entre free & pos = on l'utilise + // ok + } + else + { + printf("x_malloc: out of memory error\n"); + return NULL; + + } + } + + cachefree = c+_size; + cacheSize += _size; +// printf("alloc size:%d ptr:%d (cachepos:%d cachefree:%d)\n",_size,c,cachepos,cachefree); + return &cache[c]; +#endif +} + +void* x_malloc(int _size, int _fastalloc) +{ + return g_savestate.x_malloc(_size,_fastalloc); + +} +void* x_realloc(void* ptr,int _newsize, int _formersize) +{ + printf("x_realloc not implemented\n"); + return ptr; + /* + void*p =(void*)x_malloc(_newsize); + memcpy(p,ptr,_newsize); + x_free(ptr,_formersize); + return p; + */ +} + +void s_savestate::reset_state() +{ + state.release(); +} + +void s_savestate::reset_rewind() +{ + printf("reset_rewind\n"); + for(int i=0;i 1100) + #pragma component(browser, off, references, "CStdString") + #pragma warning (disable : 4290) // C++ Exception Specification ignored + #pragma warning (disable : 4127) // Conditional expression is constant + #pragma warning (disable : 4097) // typedef name used as synonym for class name + #if (_MSC_VER >= 1400) // AR: VS2005 and VCExpress + #define _SCL_SECURE_NO_DEPRECATE + #ifndef _INC_CRTDEFS // AR: should be defined before inclusion of + #ifndef _CRT_SECURE_NO_DEPRECATE // OG + #define _CRT_SECURE_NO_DEPRECATE + #endif + #endif + #endif +#endif + +// Borland warnings to turn off + +#ifdef __BORLANDC__ + #pragma option push -w-inl +// #pragma warn -inl // Turn off inline function warnings +#endif + +// SS_IS_INTRESOURCE +// ----------------- +// A copy of IS_INTRESOURCE from VC7. Because old VC6 version of winuser.h +// doesn't have this. + +#define SS_IS_INTRESOURCE(_r) (false) + +#if !defined (SS_ANSI) && defined(_MSC_VER) + #undef SS_IS_INTRESOURCE + #if defined(_WIN64) + #define SS_IS_INTRESOURCE(_r) (((unsigned __int64)(_r) >> 16) == 0) + #else + #define SS_IS_INTRESOURCE(_r) (((unsigned long)(_r) >> 16) == 0) + #endif +#endif + + +// MACRO: SS_UNSIGNED +// ------------------ +// This macro causes the addition of a constructor and assignment operator +// which take unsigned characters. CString has such functions and in order +// to provide maximum CString-compatability, this code needs them as well. +// In practice you will likely never need these functions... + +//#define SS_UNSIGNED + +#if defined(SS_ALLOW_UNSIGNED_CHARS) || defined(_WTL_VER) // AR + #define SS_UNSIGNED +#endif + +// MACRO: SS_SAFE_FORMAT +// --------------------- +// This macro provides limited compatability with a questionable CString +// "feature". You can define it in order to avoid a common problem that +// people encounter when switching from CString to CStdString. +// +// To illustrate the problem -- With CString, you can do this: +// +// CString sName("Joe"); +// CString sTmp; +// sTmp.Format("My name is %s", sName); // WORKS! +// +// However if you were to try this with CStdString, your program would +// crash. +// +// CStdString sName("Joe"); +// CStdString sTmp; +// sTmp.Format("My name is %s", sName); // CRASHES! +// +// You must explicitly call c_str() or cast the object to the proper type +// +// sTmp.Format("My name is %s", sName.c_str()); // WORKS! +// sTmp.Format("My name is %s", static_cast(sName));// WORKS! +// sTmp.Format("My name is %s", (PCSTR)sName); // WORKS! +// +// This is because it is illegal to pass anything but a POD type as a +// variadic argument to a variadic function (i.e. as one of the "..." +// arguments). The type const char* is a POD type. The type CStdString +// is not. Of course, neither is the type CString, but CString lets you do +// it anyway due to the way they laid out the class in binary. I have no +// control over this in CStdString since I derive from whatever +// implementation of basic_string is available. +// +// However if you have legacy code (which does this) that you want to take +// out of the MFC world and you don't want to rewrite all your calls to +// Format(), then you can define this flag and it will no longer crash. +// +// Note however that this ONLY works for Format(), not sprintf, fprintf, +// etc. If you pass a CStdString object to one of those functions, your +// program will crash. Not much I can do to get around this, short of +// writing substitutes for those functions as well. + +#define SS_SAFE_FORMAT // use new template style Format() function + + +// MACRO: SS_NO_IMPLICIT_CAST +// -------------------------- +// Some people don't like the implicit cast to const char* (or rather to +// const CT*) that CStdString (and MFC's CString) provide. That was the +// whole reason I created this class in the first place, but hey, whatever +// bakes your cake. Just #define this macro to get rid of the the implicit +// cast. + +//#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*() + + +// MACRO: SS_NO_REFCOUNT +// --------------------- +// turns off reference counting at the assignment level. Only needed +// for the version of basic_string<> that comes with Visual C++ versions +// 6.0 or earlier, and only then in some heavily multithreaded scenarios. +// Uncomment it if you feel you need it. + +//#define SS_NO_REFCOUNT + +// MACRO: SS_WIN32 +// --------------- +// When this flag is set, we are building code for the Win32 platform and +// may use Win32 specific functions (such as LoadString). This gives us +// a couple of nice extras for the code. +// +// Obviously, Microsoft's is not the only compiler available for Win32 out +// there. So I can't just check to see if _MSC_VER is defined to detect +// if I'm building on Win32. So for now, if you use MS Visual C++ or +// Borland's compiler, I turn this on. Otherwise you may turn it on +// yourself, if you prefer + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32) +//OG #define SS_WIN32 +#endif + +// MACRO: SS_ANSI +// -------------- +// When this macro is defined, the code attempts only to use ANSI/ISO +// standard library functions to do it's work. It will NOT attempt to use +// any Win32 of Visual C++ specific functions -- even if they are +// available. You may define this flag yourself to prevent any Win32 +// of VC++ specific functions from being called. + +// If we're not on Win32, we MUST use an ANSI build + +#ifndef SS_WIN32 + #if !defined(SS_NO_ANSI) + #define SS_ANSI + #endif +#endif + +// MACRO: SS_ALLOCA +// ---------------- +// Some implementations of the Standard C Library have a non-standard +// function known as alloca(). This functions allows one to allocate a +// variable amount of memory on the stack. It is needed to implement +// the ASCII/MBCS conversion macros. +// +// I wanted to find some way to determine automatically if alloca() is +// available on this platform via compiler flags but that is asking for +// trouble. The crude test presented here will likely need fixing on +// other platforms. Therefore I'll leave it up to you to fiddle with +// this test to determine if it exists. Just make sure SS_ALLOCA is or +// is not defined as appropriate and you control this feature. + +#if defined(_MSC_VER) && !defined(SS_ANSI) + #define SS_ALLOCA +#endif + + +// MACRO: SS_MBCS +// -------------- +// Setting this macro means you are using MBCS characters. In MSVC builds, +// this macro gets set automatically by detection of the preprocessor flag +// _MBCS. For other platforms you may set it manually if you wish. The +// only effect it currently has is to cause the allocation of more space +// for wchar_t --> char conversions. +// Note that MBCS does not mean UNICODE. +// +// #define SS_MBCS +// + +#ifdef _MBCS + #define SS_MBCS +#endif + + +// MACRO SS_NO_LOCALE +// ------------------ +// If your implementation of the Standard C++ Library lacks the header, +// you can #define this macro to make your code build properly. Note that this +// is some of my newest code and frankly I'm not very sure of it, though it does +// pass my unit tests. + +// Compiler Error regarding _UNICODE and UNICODE +// ----------------------------------------------- +// Microsoft header files are screwy. Sometimes they depend on a preprocessor +// flag named "_UNICODE". Other times they check "UNICODE" (note the lack of +// leading underscore in the second version". In several places, they silently +// "synchronize" these two flags this by defining one of the other was defined. +// In older version of this header, I used to try to do the same thing. +// +// However experience has taught me that this is a bad idea. You get weird +// compiler errors that seem to indicate things like LPWSTR and LPTSTR not being +// equivalent in UNICODE builds, stuff like that (when they MUST be in a proper +// UNICODE build). You end up scratching your head and saying, "But that HAS +// to compile!". +// +// So what should you do if you get this error? +// +// Make sure that both macros (_UNICODE and UNICODE) are defined before this +// file is included. You can do that by either +// +// a) defining both yourself before any files get included +// b) including the proper MS headers in the proper order +// c) including this file before any other file, uncommenting +// the #defines below, and commenting out the #errors +// +// Personally I recommend solution a) but it's your call. + +#ifdef _MSC_VER + #if defined (_UNICODE) && !defined (UNICODE) + #error UNICODE defined but not UNICODE + // #define UNICODE // no longer silently fix this + #endif + #if defined (UNICODE) && !defined (_UNICODE) + #error Warning, UNICODE defined but not _UNICODE + // #define _UNICODE // no longer silently fix this + #endif +#endif + + +// ----------------------------------------------------------------------------- +// MIN and MAX. The Standard C++ template versions go by so many names (at +// at least in the MS implementation) that you never know what's available +// ----------------------------------------------------------------------------- +template +inline const Type& SSMIN(const Type& arg1, const Type& arg2) +{ + return arg2 < arg1 ? arg2 : arg1; +} +template +inline const Type& SSMAX(const Type& arg1, const Type& arg2) +{ + return arg2 > arg1 ? arg2 : arg1; +} + +// If they have not #included W32Base.h (part of my W32 utility library) then +// we need to define some stuff. Otherwise, this is all defined there. + +#if !defined(W32BASE_H) + + // If they want us to use only standard C++ stuff (no Win32 stuff) + + #ifdef SS_ANSI + + // On Win32 we have TCHAR.H so just include it. This is NOT violating + // the spirit of SS_ANSI as we are not calling any Win32 functions here. + + #ifdef SS_WIN32 + + #include + #include + #ifndef STRICT + #define STRICT + #endif + + // ... but on non-Win32 platforms, we must #define the types we need. + + #else + + typedef const char* PCSTR; + typedef char* PSTR; + typedef const wchar_t* PCWSTR; + typedef wchar_t* PWSTR; + #ifdef UNICODE + typedef wchar_t TCHAR; + #else + typedef char TCHAR; + #endif + typedef wchar_t OLECHAR; + + #endif // #ifndef _WIN32 + + + // Make sure ASSERT and verify are defined using only ANSI stuff + + #ifndef ASSERT + #include +#ifndef ASSERT + #define ASSERT(f) assert((f)) +#endif +#endif + #ifndef VERIFY + #ifdef _DEBUG + #define VERIFY(x) ASSERT((x)) + #else + #define VERIFY(x) x + #endif + #endif + + #else // ...else SS_ANSI is NOT defined + + #include + #include + #ifndef STRICT + #define STRICT + #endif + + // Make sure ASSERT and verify are defined + + #ifndef ASSERT + #include + #define ASSERT(f) _ASSERTE((f)) + #endif + #ifndef VERIFY + #ifdef _DEBUG + #define VERIFY(x) ASSERT((x)) + #else + #define VERIFY(x) x + #endif + #endif + + #endif // #ifdef SS_ANSI + + #ifndef UNUSED + #define UNUSED(x) x + #endif + +#endif // #ifndef W32BASE_H + +// Standard headers needed + +#include // basic_string +#include // for_each, etc. +#include // for StdStringLessNoCase, et al +#ifndef SS_NO_LOCALE + #ifdef _WIN32_WCE // AR + #define SS_NO_LOCALE + #else + #include // for various facets + #endif +#endif + +// If this is a recent enough version of VC include comdef.h, so we can write +// member functions to deal with COM types & compiler support classes e.g. +// _bstr_t + +#if defined (_MSC_VER) && (_MSC_VER >= 1100) + #include + #define SS_INC_COMDEF // signal that we #included MS comdef.h file + #define STDSTRING_INC_COMDEF + #define SS_NOTHROW __declspec(nothrow) +#else + #define SS_NOTHROW +#endif + +#ifndef TRACE + #define TRACE_DEFINED_HERE + #define TRACE +#endif + +// Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the +// versions with the "L" in front of them because that's a leftover from Win 16 +// days, even though it evaluates to the same thing. Therefore, Define a PCSTR +// as an LPCTSTR. + +#if !defined(PCTSTR) && !defined(PCTSTR_DEFINED) + typedef const TCHAR* PCTSTR; + #define PCTSTR_DEFINED +#endif + +#if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED) + typedef const OLECHAR* PCOLESTR; + #define PCOLESTR_DEFINED +#endif + +#if !defined(POLESTR) && !defined(POLESTR_DEFINED) + typedef OLECHAR* POLESTR; + #define POLESTR_DEFINED +#endif + +#if !defined(PCUSTR) && !defined(PCUSTR_DEFINED) + typedef const unsigned char* PCUSTR; + typedef unsigned char* PUSTR; + #define PCUSTR_DEFINED +#endif + + +// SGI compiler 7.3 doesnt know these types - oh and btw, remember to use +// -LANG:std in the CXX Flags +#if defined(__sgi) + typedef unsigned long DWORD; + typedef void * LPCVOID; +#endif + + +// SS_USE_FACET macro and why we need it: +// +// Since I'm a good little Standard C++ programmer, I use locales. Thus, I +// need to make use of the use_facet<> template function here. Unfortunately, +// this need is complicated by the fact the MS' implementation of the Standard +// C++ Library has a non-standard version of use_facet that takes more +// arguments than the standard dictates. Since I'm trying to write CStdString +// to work with any version of the Standard library, this presents a problem. +// +// The upshot of this is that I can't do 'use_facet' directly. The MS' docs +// tell me that I have to use a macro, _USE() instead. Since _USE obviously +// won't be available in other implementations, this means that I have to write +// my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the +// standard, use_facet. +// +// If you are having trouble with the SS_USE_FACET macro, in your implementation +// of the Standard C++ Library, you can define your own version of SS_USE_FACET. + +#ifndef schMSG + #define schSTR(x) #x + #define schSTR2(x) schSTR(x) + #define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc) +#endif + +#ifndef SS_USE_FACET + + // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for + // all MSVC builds, erroneously in my opinion. It causes problems for + // my SS_ANSI builds. In my code, I always comment out that line. You'll + // find it in \stlport\config\stl_msvc.h + + #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 ) + + #if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER) + #ifdef SS_ANSI + #pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!) + #endif + #endif + #define SS_USE_FACET(loc, fac) std::use_facet(loc) + + #elif defined(_MSC_VER ) + + #define SS_USE_FACET(loc, fac) std::_USE(loc, fac) + + // ...and + #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) + + #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0) + + #else + + #define SS_USE_FACET(loc, fac) std::use_facet(loc) + + #endif + +#endif + +// ============================================================================= +// UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones. +// ============================================================================= + +#include // Added to Std Library with Amendment #1. + +// First define the conversion helper functions. We define these regardless of +// any preprocessor macro settings since their names won't collide. + +// Not sure if we need all these headers. I believe ANSI says we do. + +#include +#include +#include +#include +#include +#ifndef va_start + #include +#endif + + +#ifdef SS_NO_LOCALE + + #if defined(_WIN32) + + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, + UINT acp=CP_ACP) + { + ASSERT(0 != pSrcA); + ASSERT(0 != pDstW); + pDstW[0] = '\0'; + MultiByteToWideChar(acp, 0, pSrcA, nSrc, pDstW, nDst); + return pDstW; + } + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc, + UINT acp=CP_ACP) + { + return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp); + } + + inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + UINT acp=CP_ACP) + { + ASSERT(0 != pDstA); + ASSERT(0 != pSrcW); + pDstA[0] = '\0'; + WideCharToMultiByte(acp, 0, pSrcW, nSrc, pDstA, nDst, 0, 0); + return pDstA; + } + inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + UINT acp=CP_ACP) + { + return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp); + } + #else + #endif + +#else + + // StdCodeCvt - made to look like Win32 functions WideCharToMultiByte + // and MultiByteToWideChar but uses locales in SS_ANSI + // builds. There are a number of overloads. + // First argument is the destination buffer. + // Second argument is the source buffer + //#if defined (SS_ANSI) || !defined (SS_WIN32) + + // 'SSCodeCvt' - shorthand name for the codecvt facet we use + + typedef std::codecvt SSCodeCvt; + + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, + const std::locale& loc=std::locale()) + { + ASSERT(0 != pSrcA); + ASSERT(0 != pDstW); + + pDstW[0] = '\0'; + + if ( nSrc > 0 ) + { + PCSTR pNextSrcA = pSrcA; + PWSTR pNextDstW = pDstW; + SSCodeCvt::result res = SSCodeCvt::ok; + const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt); + SSCodeCvt::state_type st= { 0 }; + res = conv.in(st, + pSrcA, pSrcA + nSrc, pNextSrcA, + pDstW, pDstW + nDst, pNextDstW); + + ASSERT(SSCodeCvt::ok == res); + ASSERT(SSCodeCvt::error != res); + ASSERT(pNextDstW >= pDstW); + ASSERT(pNextSrcA >= pSrcA); + + // Null terminate the converted string + + if ( pNextDstW - pDstW > nDst ) + *(pDstW + nDst) = '\0'; + else + *pNextDstW = '\0'; + } + return pDstW; + } + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc, + const std::locale& loc=std::locale()) + { + return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, loc); + } + + inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + const std::locale& loc=std::locale()) + { + ASSERT(0 != pDstA); + ASSERT(0 != pSrcW); + + pDstA[0] = '\0'; + + if ( nSrc > 0 ) + { + PSTR pNextDstA = pDstA; + PCWSTR pNextSrcW = pSrcW; + SSCodeCvt::result res = SSCodeCvt::ok; + const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt); + SSCodeCvt::state_type st= { 0 }; + res = conv.out(st, + pSrcW, pSrcW + nSrc, pNextSrcW, + pDstA, pDstA + nDst, pNextDstA); + + ASSERT(SSCodeCvt::error != res); + ASSERT(SSCodeCvt::ok == res); // strict, comment out for sanity + ASSERT(pNextDstA >= pDstA); + ASSERT(pNextSrcW >= pSrcW); + + // Null terminate the converted string + + if ( pNextDstA - pDstA > nDst ) + *(pDstA + nDst) = '\0'; + else + *pNextDstA = '\0'; + } + return pDstA; + } + + inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + const std::locale& loc=std::locale()) + { + return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, loc); + } + +#endif + + + +// Unicode/MBCS conversion macros are only available on implementations of +// the "C" library that have the non-standard _alloca function. As far as I +// know that's only Microsoft's though I've heard that the function exists +// elsewhere. + +#if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION + + #include // needed for _alloca + + // Define our conversion macros to look exactly like Microsoft's to + // facilitate using this stuff both with and without MFC/ATL + + #ifdef _CONVERSION_USES_THREAD_LOCALE + + #ifndef _DEBUG + #define SSCVT int _cvt; _cvt; UINT _acp=GetACP(); \ + _acp; PCWSTR _pw; _pw; PCSTR _pa; _pa + #else + #define SSCVT int _cvt = 0; _cvt; UINT _acp=GetACP();\ + _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa + #endif + #define SSA2W(pa) (\ + ((_pa = pa) == 0) ? 0 : (\ + _cvt = (sslen(_pa)),\ + StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pa, _cvt, _acp))) + #define SSW2A(pw) (\ + ((_pw = pw) == 0) ? 0 : (\ + _cvt = sslen(_pw), \ + StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pw, _cvt, _acp))) + #else + + #ifndef _DEBUG + #define SSCVT int _cvt; _cvt; UINT _acp=CP_ACP; _acp;\ + PCWSTR _pw; _pw; PCSTR _pa; _pa + #else + #define SSCVT int _cvt = 0; _cvt; UINT _acp=CP_ACP; \ + _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa + #endif + #define SSA2W(pa) (\ + ((_pa = pa) == 0) ? 0 : (\ + _cvt = (sslen(_pa)),\ + StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pa, _cvt))) + #define SSW2A(pw) (\ + ((_pw = pw) == 0) ? 0 : (\ + _cvt = (sslen(_pw)),\ + StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pw, _cvt))) + #endif + + #define SSA2CW(pa) ((PCWSTR)SSA2W((pa))) + #define SSW2CA(pw) ((PCSTR)SSW2A((pw))) + + #ifdef UNICODE + #define SST2A SSW2A + #define SSA2T SSA2W + #define SST2CA SSW2CA + #define SSA2CT SSA2CW + // (Did you get a compiler error here about not being able to convert + // PTSTR into PWSTR? Then your _UNICODE and UNICODE flags are messed + // up. Best bet: #define BOTH macros before including any MS headers.) + inline PWSTR SST2W(PTSTR p) { return p; } + inline PTSTR SSW2T(PWSTR p) { return p; } + inline PCWSTR SST2CW(PCTSTR p) { return p; } + inline PCTSTR SSW2CT(PCWSTR p) { return p; } + #else + #define SST2W SSA2W + #define SSW2T SSW2A + #define SST2CW SSA2CW + #define SSW2CT SSW2CA + inline PSTR SST2A(PTSTR p) { return p; } + inline PTSTR SSA2T(PSTR p) { return p; } + inline PCSTR SST2CA(PCTSTR p) { return p; } + inline PCTSTR SSA2CT(PCSTR p) { return p; } + #endif // #ifdef UNICODE + + #if defined(UNICODE) + // in these cases the default (TCHAR) is the same as OLECHAR + inline PCOLESTR SST2COLE(PCTSTR p) { return p; } + inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; } + inline POLESTR SST2OLE(PTSTR p) { return p; } + inline PTSTR SSOLE2T(POLESTR p) { return p; } + #elif defined(OLE2ANSI) + // in these cases the default (TCHAR) is the same as OLECHAR + inline PCOLESTR SST2COLE(PCTSTR p) { return p; } + inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; } + inline POLESTR SST2OLE(PTSTR p) { return p; } + inline PTSTR SSOLE2T(POLESTR p) { return p; } + #else + //CharNextW doesn't work on Win95 so we use this + #define SST2COLE(pa) SSA2CW((pa)) + #define SST2OLE(pa) SSA2W((pa)) + #define SSOLE2CT(po) SSW2CA((po)) + #define SSOLE2T(po) SSW2A((po)) + #endif + + #ifdef OLE2ANSI + #define SSW2OLE SSW2A + #define SSOLE2W SSA2W + #define SSW2COLE SSW2CA + #define SSOLE2CW SSA2CW + inline POLESTR SSA2OLE(PSTR p) { return p; } + inline PSTR SSOLE2A(POLESTR p) { return p; } + inline PCOLESTR SSA2COLE(PCSTR p) { return p; } + inline PCSTR SSOLE2CA(PCOLESTR p){ return p; } + #else + #define SSA2OLE SSA2W + #define SSOLE2A SSW2A + #define SSA2COLE SSA2CW + #define SSOLE2CA SSW2CA + inline POLESTR SSW2OLE(PWSTR p) { return p; } + inline PWSTR SSOLE2W(POLESTR p) { return p; } + inline PCOLESTR SSW2COLE(PCWSTR p) { return p; } + inline PCWSTR SSOLE2CW(PCOLESTR p){ return p; } + #endif + + // Above we've defined macros that look like MS' but all have + // an 'SS' prefix. Now we need the real macros. We'll either + // get them from the macros above or from MFC/ATL. + + #if defined (USES_CONVERSION) + + #define _NO_STDCONVERSION // just to be consistent + + #else + + #ifdef _MFC_VER + + #include + #define _NO_STDCONVERSION // just to be consistent + + #else + + #define USES_CONVERSION SSCVT + #define A2CW SSA2CW + #define W2CA SSW2CA + #define T2A SST2A + #define A2T SSA2T + #define T2W SST2W + #define W2T SSW2T + #define T2CA SST2CA + #define A2CT SSA2CT + #define T2CW SST2CW + #define W2CT SSW2CT + #define ocslen sslen + #define ocscpy sscpy + #define T2COLE SST2COLE + #define OLE2CT SSOLE2CT + #define T2OLE SST2COLE + #define OLE2T SSOLE2CT + #define A2OLE SSA2OLE + #define OLE2A SSOLE2A + #define W2OLE SSW2OLE + #define OLE2W SSOLE2W + #define A2COLE SSA2COLE + #define OLE2CA SSOLE2CA + #define W2COLE SSW2COLE + #define OLE2CW SSOLE2CW + + #endif // #ifdef _MFC_VER + #endif // #ifndef USES_CONVERSION +#endif // #ifndef SS_NO_CONVERSION + +// Define ostring - generic name for std::basic_string + +#if !defined(ostring) && !defined(OSTRING_DEFINED) + typedef std::basic_string ostring; + #define OSTRING_DEFINED +#endif + +// StdCodeCvt when there's no conversion to be done +inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCSTR pSrc, int nSrc) +{ + int nChars = SSMIN(nSrc, nDst); + + if ( nChars > 0 ) + { + pDst[0] = '\0'; + std::basic_string::traits_type::copy(pDst, pSrc, nChars); +// std::char_traits::copy(pDst, pSrc, nChars); + pDst[nChars] = '\0'; + } + + return pDst; +} +inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCUSTR pSrc, int nSrc) +{ + return StdCodeCvt(pDst, nDst, (PCSTR)pSrc, nSrc); +} +inline PUSTR StdCodeCvt(PUSTR pDst, int nDst, PCSTR pSrc, int nSrc) +{ + return (PUSTR)StdCodeCvt((PSTR)pDst, nDst, pSrc, nSrc); +} + +inline PWSTR StdCodeCvt(PWSTR pDst, int nDst, PCWSTR pSrc, int nSrc) +{ + int nChars = SSMIN(nSrc, nDst); + + if ( nChars > 0 ) + { + pDst[0] = '\0'; + std::basic_string::traits_type::copy(pDst, pSrc, nChars); +// std::char_traits::copy(pDst, pSrc, nChars); + pDst[nChars] = '\0'; + } + + return pDst; +} + + +// Define tstring -- generic name for std::basic_string + +#if !defined(tstring) && !defined(TSTRING_DEFINED) + typedef std::basic_string tstring; + #define TSTRING_DEFINED +#endif + +// a very shorthand way of applying the fix for KB problem Q172398 +// (basic_string assignment bug) + +#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) + #define Q172398(x) (x).erase() +#else + #define Q172398(x) +#endif + +// ============================================================================= +// INLINE FUNCTIONS ON WHICH CSTDSTRING RELIES +// +// Usually for generic text mapping, we rely on preprocessor macro definitions +// to map to string functions. However the CStdStr<> template cannot use +// macro-based generic text mappings because its character types do not get +// resolved until template processing which comes AFTER macro processing. In +// other words, the preprocessor macro UNICODE is of little help to us in the +// CStdStr template +// +// Therefore, to keep the CStdStr declaration simple, we have these inline +// functions. The template calls them often. Since they are inline (and NOT +// exported when this is built as a DLL), they will probably be resolved away +// to nothing. +// +// Without these functions, the CStdStr<> template would probably have to broken +// out into two, almost identical classes. Either that or it would be a huge, +// convoluted mess, with tons of "if" statements all over the place checking the +// size of template parameter CT. +// ============================================================================= + +#ifdef SS_NO_LOCALE + + // -------------------------------------------------------------------------- + // Win32 GetStringTypeEx wrappers + // -------------------------------------------------------------------------- + inline bool wsGetStringType(LCID lc, DWORD dwT, PCSTR pS, int nSize, + WORD* pWd) + { + return FALSE; + //OG return FALSE != GetStringTypeExA(lc, dwT, pS, nSize, pWd); + } + inline bool wsGetStringType(LCID lc, DWORD dwT, PCWSTR pS, int nSize, + WORD* pWd) + { + return FALSE != GetStringTypeExW(lc, dwT, pS, nSize, pWd); + } + + + template + inline bool ssisspace (CT t) + { + WORD toYourMother; + return wsGetStringType(GetThreadLocale(), CT_CTYPE1, &t, 1, &toYourMother) + && 0 != (C1_BLANK & toYourMother); + } + + +#endif + +// If they defined SS_NO_REFCOUNT, then we must convert all assignments + +#if defined (_MSC_VER) && (_MSC_VER < 1300) + #ifdef SS_NO_REFCOUNT + #define SSREF(x) (x).c_str() + #else + #define SSREF(x) (x) + #endif +#else + #define SSREF(x) (x) +#endif + +// ----------------------------------------------------------------------------- +// sslen: strlen/wcslen wrappers +// ----------------------------------------------------------------------------- +template inline int sslen(const CT* pT) +{ + return 0 == pT ? 0 : (int)std::basic_string::traits_type::length(pT); +// return 0 == pT ? 0 : std::char_traits::length(pT); +} +inline SS_NOTHROW int sslen(const std::string& s) +{ + return static_cast(s.length()); +} +inline SS_NOTHROW int sslen(const std::wstring& s) +{ + return static_cast(s.length()); +} + +// ----------------------------------------------------------------------------- +// sstolower/sstoupper -- convert characters to upper/lower case +// ----------------------------------------------------------------------------- + +#ifdef SS_NO_LOCALE + inline char sstoupper(char ch) { return (char)::toupper(ch); } + inline wchar_t sstoupper(wchar_t ch){ return (wchar_t)::towupper(ch); } + inline char sstolower(char ch) { return (char)::tolower(ch); } + inline wchar_t sstolower(wchar_t ch){ return (wchar_t)::tolower(ch); } +#else + template + inline CT sstolower(const CT& t, const std::locale& loc = std::locale()) + { + return std::tolower(t, loc); + } + template + inline CT sstoupper(const CT& t, const std::locale& loc = std::locale()) + { + return std::toupper(t, loc); + } +#endif + +// ----------------------------------------------------------------------------- +// ssasn: assignment functions -- assign "sSrc" to "sDst" +// ----------------------------------------------------------------------------- +typedef std::string::size_type SS_SIZETYPE; // just for shorthand, really +typedef std::string::pointer SS_PTRTYPE; +typedef std::wstring::size_type SW_SIZETYPE; +typedef std::wstring::pointer SW_PTRTYPE; + +inline void ssasn(std::string& sDst, const std::string& sSrc) +{ + if ( sDst.c_str() != sSrc.c_str() ) + { + sDst.erase(); + sDst.assign(SSREF(sSrc)); + } +} +inline void ssasn(std::string& sDst, PCSTR pA) +{ + // Watch out for NULLs, as always. + + if ( 0 == pA ) + { + sDst.erase(); + } + + // If pA actually points to part of sDst, we must NOT erase(), but + // rather take a substring + + else if ( pA >= sDst.c_str() && pA <= sDst.c_str() + sDst.size() ) + { + sDst =sDst.substr(static_cast(pA-sDst.c_str())); + } + + // Otherwise (most cases) apply the assignment bug fix, if applicable + // and do the assignment + + else + { + Q172398(sDst); + sDst.assign(pA); + } +} +inline void ssasn(std::string& sDst, const std::wstring& sSrc) +{ + if ( sSrc.empty() ) + { + sDst.erase(); + } + else + { + int nDst = static_cast(sSrc.size()); + + // In MBCS builds, pad the buffer to account for the possibility of + // some 3 byte characters. Not perfect but should get most cases. + +#ifdef SS_MBCS + nDst = static_cast(static_cast(nDst) * 1.3); +#endif + + sDst.resize(nDst+1); + +#ifdef SS_MBCS + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, + sSrc.c_str(), static_cast(sSrc.size())); + + // In MBCS builds, we don't know how long the destination string will be. + + sDst.resize(sslen(szCvt)); +#else +// szCvt; + sDst.resize(sSrc.size()); +#endif + } +} +inline void ssasn(std::string& sDst, PCWSTR pW) +{ + int nSrc = sslen(pW); + if ( nSrc > 0 ) + { + int nSrc = sslen(pW); + int nDst = nSrc; + + // In MBCS builds, pad the buffer to account for the possibility of + // some 3 byte characters. Not perfect but should get most cases. + +#ifdef SS_MBCS + nDst = static_cast(static_cast(nDst) * 1.3); +#endif + + sDst.resize(nDst + 1); +#ifdef SS_MBCS + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, + pW, nSrc); + + // In MBCS builds, we don't know how long the destination string will be. + + + sDst.resize(sslen(szCvt)); +#else + sDst.resize(nDst); + // szCvt; +#endif + } + else + { + sDst.erase(); + } +} +#ifdef _DEBUG +inline void ssasn(std::string& sDst, const int nNull) +{ + ASSERT(nNull==0); +#else + inline void ssasn(std::string& sDst, const int /*nNull*/) +{ +#endif + + sDst.assign(""); +} +inline void ssasn(std::wstring& sDst, const std::wstring& sSrc) +{ + if ( sDst.c_str() != sSrc.c_str() ) + { + sDst.erase(); + sDst.assign(SSREF(sSrc)); + } +} +inline void ssasn(std::wstring& sDst, PCWSTR pW) +{ + // Watch out for NULLs, as always. + + if ( 0 == pW ) + { + sDst.erase(); + } + + // If pW actually points to part of sDst, we must NOT erase(), but + // rather take a substring + + else if ( pW >= sDst.c_str() && pW <= sDst.c_str() + sDst.size() ) + { + sDst = sDst.substr(static_cast(pW-sDst.c_str())); + } + + // Otherwise (most cases) apply the assignment bug fix, if applicable + // and do the assignment + + else + { + Q172398(sDst); + sDst.assign(pW); + } +} +// #undef StrSizeType // AR: never referenced +inline void ssasn(std::wstring& sDst, const std::string& sSrc) +{ + if ( sSrc.empty() ) + { + sDst.erase(); + } + else + { + int nSrc = static_cast(sSrc.size()); + int nDst = nSrc; + + sDst.resize(nSrc+1); + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, + sSrc.c_str(), nSrc); + +#ifndef _WIN32_WCE // AR: WinCE MultiByteToWideChar() does no multibyte length adjustment + sDst.resize(sslen(szCvt)); +#else + sDst.resize(nDst); +#endif + } +} +inline void ssasn(std::wstring& sDst, PCSTR pA) +{ + int nSrc = sslen(pA); + + if ( 0 == nSrc ) + { + sDst.erase(); + } + else + { + int nDst = nSrc; + sDst.resize(nDst+1); + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, pA, + nSrc); + +#ifndef _WIN32_WCE // AR: WinCE MultiByteToWideChar() does no multibyte length adjustment + sDst.resize(sslen(szCvt)); +#else + sDst.resize(nDst); +#endif + } +} +#ifdef _DEBUG +inline void ssasn(std::wstring& sDst, const int nNull) +{ + ASSERT(nNull==0); +#else +inline void ssasn(std::wstring& sDst, const int /*nNull*/) +{ +#endif + sDst.assign(L""); +} + + +// ----------------------------------------------------------------------------- +// ssadd: string object concatenation -- add second argument to first +// ----------------------------------------------------------------------------- +inline void ssadd(std::string& sDst, const std::wstring& sSrc) +{ + int nSrc = static_cast(sSrc.size()); + + if ( nSrc > 0 ) + { + int nDst = static_cast(sDst.size()); + int nAdd = nSrc; + + // In MBCS builds, pad the buffer to account for the possibility of + // some 3 byte characters. Not perfect but should get most cases. + +#ifdef SS_MBCS + nAdd = static_cast(static_cast(nAdd) * 1.3); +#endif + + sDst.resize(nDst+nAdd+1); +#ifdef SS_MBCS + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nAdd, sSrc.c_str(), nSrc); + + + sDst.resize(nDst + sslen(szCvt)); +#else + sDst.resize(nDst + nAdd); + +#endif + } +} +inline void ssadd(std::string& sDst, const std::string& sSrc) +{ + sDst += sSrc; +} +inline void ssadd(std::string& sDst, PCWSTR pW) +{ + int nSrc = sslen(pW); + if ( nSrc > 0 ) + { + int nDst = static_cast(sDst.size()); + int nAdd = nSrc; + +#ifdef SS_MBCS + nAdd = static_cast(static_cast(nAdd) * 1.3); +#endif + + sDst.resize(nDst + nAdd + 1); +#ifdef SS_MBCS + + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nAdd, pW, nSrc); + + sDst.resize(nDst + sslen(szCvt)); +#else + sDst.resize(nDst + nSrc); +#endif + } +} +inline void ssadd(std::string& sDst, PCSTR pA) +{ + if ( pA ) + { + // If the string being added is our internal string or a part of our + // internal string, then we must NOT do any reallocation without + // first copying that string to another object (since we're using a + // direct pointer) + + if ( pA >= sDst.c_str() && pA <= sDst.c_str()+sDst.length()) + { + if ( sDst.capacity() <= sDst.size()+sslen(pA) ) + sDst.append(std::string(pA)); + else + sDst.append(pA); + } + else + { + sDst.append(pA); + } + } +} +inline void ssadd(std::wstring& sDst, const std::wstring& sSrc) +{ + sDst += sSrc; +} +inline void ssadd(std::wstring& sDst, const std::string& sSrc) +{ + if ( !sSrc.empty() ) + { + int nSrc = static_cast(sSrc.size()); + int nDst = static_cast(sDst.size()); + + sDst.resize(nDst + nSrc + 1); +#ifdef SS_MBCS + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nSrc, sSrc.c_str(), nSrc+1); + + + sDst.resize(nDst + sslen(szCvt)); +#else + sDst.resize(nDst + nSrc); + +#endif + } +} +inline void ssadd(std::wstring& sDst, PCSTR pA) +{ + int nSrc = sslen(pA); + + if ( nSrc > 0 ) + { + int nDst = static_cast(sDst.size()); + + sDst.resize(nDst + nSrc + 1); +#ifdef SS_MBCS + + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nSrc, pA, nSrc+1); + + sDst.resize(nDst + sslen(szCvt)); +#else + sDst.resize(nDst + nSrc); +#endif + } +} +inline void ssadd(std::wstring& sDst, PCWSTR pW) +{ + if ( pW ) + { + // If the string being added is our internal string or a part of our + // internal string, then we must NOT do any reallocation without + // first copying that string to another object (since we're using a + // direct pointer) + + if ( pW >= sDst.c_str() && pW <= sDst.c_str()+sDst.length()) + { + if ( sDst.capacity() <= sDst.size()+sslen(pW) ) + sDst.append(std::wstring(pW)); + else + sDst.append(pW); + } + else + { + sDst.append(pW); + } + } +} + + +// ----------------------------------------------------------------------------- +// sscmp: comparison (case sensitive, not affected by locale) +// ----------------------------------------------------------------------------- +template +inline int sscmp(const CT* pA1, const CT* pA2) +{ + CT f; + CT l; + + do + { + f = *(pA1++); + l = *(pA2++); + } while ( (f) && (f == l) ); + + return (int)(f - l); +} + +#ifdef SS_NO_LOCALE // AR: we need these because StdStringxxxNoCasex calls them +inline int ssicmp(const char* pA1, const char* pA2) +{ + return _stricmp(pA1, pA2); +} +inline int ssicmp(const wchar_t* pA1, const wchar_t* pA2) +{ + return _wcsicmp(pA1, pA2); +} +#else +// ----------------------------------------------------------------------------- +// ssicmp: comparison (case INsensitive, not affected by locale) +// ----------------------------------------------------------------------------- +template +inline int ssicmp(const CT* pA1, const CT* pA2) +{ + // Using the "C" locale = "not affected by locale" + + std::locale loc = std::locale::classic(); + const std::ctype& ct = SS_USE_FACET(loc, std::ctype); + CT f; + CT l; + + do + { + f = ct.tolower(*(pA1++)); + l = ct.tolower(*(pA2++)); + } while ( (f) && (f == l) ); + + return (int)(f - l); +} + +// ----------------------------------------------------------------------------- +// ssupr/sslwr: Uppercase/Lowercase conversion functions +// ----------------------------------------------------------------------------- + +template +inline void sslwr(CT* pT, size_t nLen, const std::locale& loc=std::locale()) +{ + SS_USE_FACET(loc, std::ctype).tolower(pT, pT+nLen); +} +template +inline void ssupr(CT* pT, size_t nLen, const std::locale& loc=std::locale()) +{ + SS_USE_FACET(loc, std::ctype).toupper(pT, pT+nLen); +} +#endif // SS_NO_LOCALE // AR +// ----------------------------------------------------------------------------- +// vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents. In standard +// builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions. +// +// ----------------------------------------------------------------------------- +// Borland's headers put some ANSI "C" functions in the 'std' namespace. +// Promote them to the global namespace so we can use them here. + +#if defined(__BORLANDC__) + using std::vsprintf; + using std::vswprintf; +#endif + + // GNU is supposed to have vsnprintf and vsnwprintf. But only the newer + // distributions do. + +#if defined(__GNUC__) + + inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl) + { + return vsnprintf(pA, nCount, pFmtA, vl); + } + inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + return vswprintf(pW, nCount, pFmtW, vl); + } + + // Microsofties can use +#elif defined(_MSC_VER) && !defined(SS_ANSI) + + inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl) + { + return _vsnprintf(pA, nCount, pFmtA, vl); + } + inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + return _vsnwprintf(pW, nCount, pFmtW, vl); + } + +#elif defined (SS_DANGEROUS_FORMAT) // ignore buffer size parameter if needed? + + inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl) + { + return vsprintf(pA, pFmtA, vl); + } + + inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + // JMO: Some distributions of the "C" have a version of vswprintf that + // takes 3 arguments (e.g. Microsoft, Borland, GNU). Others have a + // version which takes 4 arguments (an extra "count" argument in the + // second position. The best stab I can take at this so far is that if + // you are NOT running with MS, Borland, or GNU, then I'll assume you + // have the version that takes 4 arguments. + // + // I'm sure that these checks don't catch every platform correctly so if + // you get compiler errors on one of the lines immediately below, it's + // probably because your implemntation takes a different number of + // arguments. You can comment out the offending line (and use the + // alternate version) or you can figure out what compiler flag to check + // and add that preprocessor check in. Regardless, if you get an error + // on these lines, I'd sure like to hear from you about it. + // + // Thanks to Ronny Schulz for the SGI-specific checks here. + +// #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC) + #if !defined(_MSC_VER) \ + && !defined (__BORLANDC__) \ + && !defined(__GNUC__) \ + && !defined(__sgi) + + return vswprintf(pW, nCount, pFmtW, vl); + + // suddenly with the current SGI 7.3 compiler there is no such function as + // vswprintf and the substitute needs explicit casts to compile + + #elif defined(__sgi) + + nCount; + return vsprintf( (char *)pW, (char *)pFmtW, vl); + + #else + + nCount; + return vswprintf(pW, pFmtW, vl); + + #endif + + } + +#else + + // GOT COMPILER PROBLEMS HERE? + // --------------------------- + // Does your compiler choke on one or more of the following 2 functions? It + // probably means that you don't have have either vsnprintf or vsnwprintf in + // your version of the CRT. This is understandable since neither is an ANSI + // "C" function. However it still leaves you in a dilemma. In order to make + // this code build, you're going to have to to use some non-length-checked + // formatting functions that every CRT has: vsprintf and vswprintf. + // + // This is very dangerous. With the proper erroneous (or malicious) code, it + // can lead to buffer overlows and crashing your PC. Use at your own risk + // In order to use them, just #define SS_DANGEROUS_FORMAT at the top of + // this file. + // + // Even THEN you might not be all the way home due to some non-conforming + // distributions. More on this in the comments below. + + inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl) + { + #ifdef _MSC_VER + return _vsnprintf(pA, nCount, pFmtA, vl); + #else + return vsnprintf(pA, nCount, pFmtA, vl); + #endif + } + + inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + #ifdef _MSC_VER + return _vsnwprintf(pW, nCount, pFmtW, vl); + #else + return vsnwprintf(pW, nCount, pFmtW, vl); + #endif + } + +#endif + + +// ----------------------------------------------------------------------------- +// ssload: Type safe, overloaded ::LoadString wrappers +// There is no equivalent of these in non-Win32-specific builds. However, I'm +// thinking that with the message facet, there might eventually be one +// ----------------------------------------------------------------------------- +#if defined (SS_WIN32) && !defined(SS_ANSI) + inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax) + { +#ifndef _WIN32_WCE // AR: WinCE has no defined LoadStringA + return ::LoadStringA(hInst, uId, pBuf, nMax); +#else + return 0; +#endif + } + inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax) + { + return ::LoadStringW(hInst, uId, pBuf, nMax); + } +#endif + + +// ----------------------------------------------------------------------------- +// sscoll/ssicoll: Collation wrappers +// Note -- with MSVC I have reversed the arguments order here because the +// functions appear to return the opposite of what they should +// ----------------------------------------------------------------------------- +#ifndef SS_NO_LOCALE +template +inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2) +{ + const std::collate& coll = + SS_USE_FACET(std::locale(), std::collate); + + return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1); +} +template +inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2) +{ + const std::locale loc; + const std::collate& coll = SS_USE_FACET(loc, std::collate); + + // Some implementations seem to have trouble using the collate<> + // facet typedefs so we'll just default to basic_string and hope + // that's what the collate facet uses (which it generally should) + +// std::collate::string_type s1(sz1); +// std::collate::string_type s2(sz2); + const std::basic_string sEmpty; + std::basic_string s1(sz1 ? sz1 : sEmpty.c_str()); + std::basic_string s2(sz2 ? sz2 : sEmpty.c_str()); + + sslwr(const_cast(s1.c_str()), nLen1, loc); + sslwr(const_cast(s2.c_str()), nLen2, loc); + return coll.compare(s2.c_str(), s2.c_str()+nLen2, + s1.c_str(), s1.c_str()+nLen1); +} +#endif + + +// ----------------------------------------------------------------------------- +// ssfmtmsg: FormatMessage equivalents. Needed because I added a CString facade +// Again -- no equivalent of these on non-Win32 builds but their might one day +// be one if the message facet gets implemented +// ----------------------------------------------------------------------------- +#if defined (SS_WIN32) && !defined(SS_ANSI) + inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId, + DWORD dwLangId, PSTR pBuf, DWORD nSize, + va_list* vlArgs) + { + return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId, + pBuf, nSize,vlArgs); + } + inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId, + DWORD dwLangId, PWSTR pBuf, DWORD nSize, + va_list* vlArgs) + { + return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId, + pBuf, nSize,vlArgs); + } +#else +#endif + + + +// FUNCTION: sscpy. Copies up to 'nMax' characters from pSrc to pDst. +// ----------------------------------------------------------------------------- +// FUNCTION: sscpy +// inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1); +// inline int sscpy(PUSTR pDst, PCSTR pSrc, int nMax=-1) +// inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1); +// inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1); +// inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1); +// +// DESCRIPTION: +// This function is very much (but not exactly) like strcpy. These +// overloads simplify copying one C-style string into another by allowing +// the caller to specify two different types of strings if necessary. +// +// The strings must NOT overlap +// +// "Character" is expressed in terms of the destination string, not +// the source. If no 'nMax' argument is supplied, then the number of +// characters copied will be sslen(pSrc). A NULL terminator will +// also be added so pDst must actually be big enough to hold nMax+1 +// characters. The return value is the number of characters copied, +// not including the NULL terminator. +// +// PARAMETERS: +// pSrc - the string to be copied FROM. May be a char based string, an +// MBCS string (in Win32 builds) or a wide string (wchar_t). +// pSrc - the string to be copied TO. Also may be either MBCS or wide +// nMax - the maximum number of characters to be copied into szDest. Note +// that this is expressed in whatever a "character" means to pDst. +// If pDst is a wchar_t type string than this will be the maximum +// number of wchar_ts that my be copied. The pDst string must be +// large enough to hold least nMaxChars+1 characters. +// If the caller supplies no argument for nMax this is a signal to +// the routine to copy all the characters in pSrc, regardless of +// how long it is. +// +// RETURN VALUE: none +// ----------------------------------------------------------------------------- +template +inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nMax) +{ + // Note -- we assume pDst is big enough to hold pSrc. If not, we're in + // big trouble. No bounds checking. Caveat emptor. + + int nSrc = sslen(pSrc); + + const CT1* szCvt = StdCodeCvt(pDst, nMax, pSrc, nSrc); + + // If we're copying the same size characters, then all the "code convert" + // just did was basically memcpy so the #of characters copied is the same + // as the number requested. I should probably specialize this function + // template to achieve this purpose as it is silly to do a runtime check + // of a fact known at compile time. I'll get around to it. + + return sslen(szCvt); +} + +inline int sscpycvt(PSTR pDst, PCSTR pSrc, int nMax) +{ + int nCount = nMax; + for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount) + std::basic_string::traits_type::assign(*pDst, *pSrc); + + *pDst = '\0'; + return nMax - nCount; +} +inline int sscpycvt(PWSTR pDst, PCWSTR pSrc, int nMax) +{ + int nCount = nMax; + for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount) + std::basic_string::traits_type::assign(*pDst, *pSrc); + + *pDst = L'\0'; + return nMax - nCount; +} +inline int sscpycvt(PWSTR pDst, PCSTR pSrc, int nMax) +{ + // Note -- we assume pDst is big enough to hold pSrc. If not, we're in + // big trouble. No bounds checking. Caveat emptor. + + const PWSTR szCvt = StdCodeCvt(pDst, nMax, pSrc, nMax); + return sslen(szCvt); +} + +template +inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen) +{ + return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen)); +} +template +inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax) +{ + return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc))); +} +template +inline int sscpy(CT1* pDst, const CT2* pSrc) +{ + return sscpycvt(pDst, pSrc, sslen(pSrc)); +} +template +inline int sscpy(CT1* pDst, const std::basic_string& sSrc, int nMax) +{ + return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length())); +} +template +inline int sscpy(CT1* pDst, const std::basic_string& sSrc) +{ + return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length()); +} + +#ifdef SS_INC_COMDEF + template + inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax) + { + return sscpycvt(pDst, static_cast(bs), + SSMIN(nMax, static_cast(bs.length()))); + } + template + inline int sscpy(CT1* pDst, const _bstr_t& bs) + { + return sscpy(pDst, bs, static_cast(bs.length())); + } +#endif + + +// ----------------------------------------------------------------------------- +// Functional objects for changing case. They also let you pass locales +// ----------------------------------------------------------------------------- + +#ifdef SS_NO_LOCALE + template + struct SSToUpper : public std::unary_function + { + inline CT operator()(const CT& t) const + { + return sstoupper(t); + } + }; + template + struct SSToLower : public std::unary_function + { + inline CT operator()(const CT& t) const + { + return sstolower(t); + } + }; +#else + template + struct SSToUpper : public std::binary_function + { + inline CT operator()(const CT& t, const std::locale& loc) const + { + return sstoupper(t, loc); + } + }; + template + struct SSToLower : public std::binary_function + { + inline CT operator()(const CT& t, const std::locale& loc) const + { + return sstolower(t, loc); + } + }; +#endif + +// This struct is used for TrimRight() and TrimLeft() function implementations. +//template +//struct NotSpace : public std::unary_function +//{ +// const std::locale& loc; +// inline NotSpace(const std::locale& locArg) : loc(locArg) {} +// inline bool operator() (CT t) { return !std::isspace(t, loc); } +//}; +template +struct NotSpace : public std::unary_function +{ + // DINKUMWARE BUG: + // Note -- using std::isspace in a COM DLL gives us access violations + // because it causes the dynamic addition of a function to be called + // when the library shuts down. Unfortunately the list is maintained + // in DLL memory but the function is in static memory. So the COM DLL + // goes away along with the function that was supposed to be called, + // and then later when the DLL CRT shuts down it unloads the list and + // tries to call the long-gone function. + // This is DinkumWare's implementation problem. If you encounter this + // problem, you may replace the calls here with good old isspace() and + // iswspace() from the CRT unless they specify SS_ANSI + +#ifdef SS_NO_LOCALE + + // OG + bool operator() (CT t) const { return !ssisspace(t); } + +#else + const std::locale loc; + NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {} + bool operator() (CT t) const { return !std::isspace(t, loc); } +#endif +}; + + + + +// Now we can define the template (finally!) +// ============================================================================= +// TEMPLATE: CStdStr +// template class CStdStr : public std::basic_string +// +// REMARKS: +// This template derives from basic_string and adds some MFC CString- +// like functionality +// +// Basically, this is my attempt to make Standard C++ library strings as +// easy to use as the MFC CString class. +// +// Note that although this is a template, it makes the assumption that the +// template argument (CT, the character type) is either char or wchar_t. +// ============================================================================= + +//#define CStdStr _SS // avoid compiler warning 4786 + +// template ARG& FmtArg(ARG& arg) { return arg; } +// PCSTR FmtArg(const std::string& arg) { return arg.c_str(); } +// PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); } + +template +struct FmtArg +{ + explicit FmtArg(const ARG& arg) : a_(arg) {} + const ARG& operator()() const { return a_; } + const ARG& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; + +template +class CStdStr : public std::basic_string +{ + // Typedefs for shorter names. Using these names also appears to help + // us avoid some ambiguities that otherwise arise on some platforms + + //#define MYBASE std::basic_string // my base class // AR: use the typedef with WTL + typedef typename std::basic_string MYBASE; // my base class + typedef CStdStr MYTYPE; // myself + typedef typename MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR + typedef typename MYBASE::pointer PMYSTR; // PSTR or PWSTR + typedef typename MYBASE::iterator MYITER; // my iterator type + typedef typename MYBASE::const_iterator MYCITER; // you get the idea... + typedef typename MYBASE::reverse_iterator MYRITER; + typedef typename MYBASE::size_type MYSIZE; + typedef typename MYBASE::value_type MYVAL; + typedef typename MYBASE::allocator_type MYALLOC; + +public: + // shorthand conversion from PCTSTR to string resource ID + #define SSRES(pctstr) LOWORD(reinterpret_cast(pctstr)) + + bool TryLoad(const void* pT) + { + bool bLoaded = false; + +#if defined(SS_WIN32) && !defined(SS_ANSI) + if ( ( pT != NULL ) && SS_IS_INTRESOURCE(pT) ) + { + UINT nId = LOWORD(reinterpret_cast(pT)); + if ( !LoadString(nId) ) + { + TRACE(_T("Can't load string %u\n"), SSRES(pT)); + } + bLoaded = true; + } +#endif + + return bLoaded; + } + + + // CStdStr inline constructors + CStdStr() + { + } + + /* + // OG Added getExt + PCMYSTR getExt() + { + int pos = ReverseFind('.'); + return c_str()+pos+1; + } + */ + + + CStdStr(const MYTYPE& str) : MYBASE(SSREF(str)) + { + } + + CStdStr(const std::string& str) + { + ssasn(*this, SSREF(str)); + } + + CStdStr(const std::wstring& str) + { + ssasn(*this, SSREF(str)); + } + +#ifndef _WTL_VER // AR: kept the existing for compatibility security + CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(pT, n) + { + } +#else // AR: WTL::CString exposes constructors with both types + template + CStdStr(const TC* pTC, MYSIZE n) + { + *this = pTC; + this->resize(n); + } +#endif + +#ifdef SS_UNSIGNED + CStdStr(PCUSTR pU) + { + *this = reinterpret_cast(pU); + } +#endif + + CStdStr(PCSTR pA) + { + #ifdef SS_ANSI + *this = pA; + #else + if ( !TryLoad(pA) ) + *this = pA; + #endif + } + + CStdStr(PCWSTR pW) + { + #ifdef SS_ANSI + *this = pW; + #else + if ( !TryLoad(pW) ) + *this = pW; + #endif + } + + CStdStr(MYCITER first, MYCITER last) + : MYBASE(first, last) + { + } + + CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC()) + : MYBASE(nSize, ch, al) + { + } + + #ifdef SS_INC_COMDEF + CStdStr(const _bstr_t& bstr) + { + if ( bstr.length() > 0 ) + this->append(static_cast(bstr), bstr.length()); + } + #endif + + // CStdStr inline assignment operators -- the ssasn function now takes care + // of fixing the MSVC assignment bug (see knowledge base article Q172398). + MYTYPE& operator=(const MYTYPE& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& operator=(const std::string& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& operator=(const std::wstring& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& operator=(PCSTR pA) + { + ssasn(*this, pA); + return *this; + } + + MYTYPE& operator=(PCWSTR pW) + { + ssasn(*this, pW); + return *this; + } + +#ifdef SS_UNSIGNED + MYTYPE& operator=(PCUSTR pU) + { + ssasn(*this, reinterpret_cast(pU)); + return *this; + } +#endif + + MYTYPE& operator=(CT t) + { + Q172398(*this); + this->assign(1, t); + return *this; + } + + #ifdef SS_INC_COMDEF + MYTYPE& operator=(const _bstr_t& bstr) + { + if ( bstr.length() > 0 ) + { + this->assign(static_cast(bstr), bstr.length()); + return *this; + } + else + { + this->erase(); + return *this; + } + } + #endif + + + // Overloads also needed to fix the MSVC assignment bug (KB: Q172398) + // *** Thanks to Pete The Plumber for catching this one *** + // They also are compiled if you have explicitly turned off refcounting + #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT) + + MYTYPE& assign(const MYTYPE& str) + { + Q172398(*this); + sscpy(GetBuffer(str.size()+1), SSREF(str)); + this->ReleaseBuffer(str.size()); + return *this; + } + + MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars) + { + // This overload of basic_string::assign is supposed to assign up to + // or the NULL terminator, whichever comes first. Since we + // are about to call a less forgiving overload (in which + // must be a valid length), we must adjust the length here to a safe + // value. Thanks to Ullrich Pollähne for catching this bug + + nChars = SSMIN(nChars, str.length() - nStart); + MYTYPE strTemp(str.c_str()+nStart, nChars); + Q172398(*this); + this->assign(strTemp); + return *this; + } + + MYTYPE& assign(const MYBASE& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE nChars) + { + // This overload of basic_string::assign is supposed to assign up to + // or the NULL terminator, whichever comes first. Since we + // are about to call a less forgiving overload (in which + // must be a valid length), we must adjust the length here to a safe + // value. Thanks to Ullrich Pollähne for catching this bug + + nChars = SSMIN(nChars, str.length() - nStart); + + // Watch out for assignment to self + + if ( this == &str ) + { + MYTYPE strTemp(str.c_str() + nStart, nChars); + static_cast(this)->assign(strTemp); + } + else + { + Q172398(*this); + static_cast(this)->assign(str.c_str()+nStart, nChars); + } + return *this; + } + + MYTYPE& assign(const CT* pC, MYSIZE nChars) + { + // Q172398 only fix -- erase before assigning, but not if we're + // assigning from our own buffer + + #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) + if ( !this->empty() && + ( pC < this->data() || pC > this->data() + this->capacity() ) ) + { + this->erase(); + } + #endif + Q172398(*this); + static_cast(this)->assign(pC, nChars); + return *this; + } + + MYTYPE& assign(MYSIZE nChars, MYVAL val) + { + Q172398(*this); + static_cast(this)->assign(nChars, val); + return *this; + } + + MYTYPE& assign(const CT* pT) + { + return this->assign(pT, MYBASE::traits_type::length(pT)); + } + + MYTYPE& assign(MYCITER iterFirst, MYCITER iterLast) + { + #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) + // Q172398 fix. don't call erase() if we're assigning from ourself + if ( iterFirst < this->begin() || + iterFirst > this->begin() + this->size() ) + { + this->erase() + } + #endif + this->replace(this->begin(), this->end(), iterFirst, iterLast); + return *this; + } + #endif + + + // ------------------------------------------------------------------------- + // CStdStr inline concatenation. + // ------------------------------------------------------------------------- + MYTYPE& operator+=(const MYTYPE& str) + { + ssadd(*this, str); + return *this; + } + + MYTYPE& operator+=(const std::string& str) + { + ssadd(*this, str); + return *this; + } + + MYTYPE& operator+=(const std::wstring& str) + { + ssadd(*this, str); + return *this; + } + + MYTYPE& operator+=(PCSTR pA) + { + ssadd(*this, pA); + return *this; + } + + MYTYPE& operator+=(PCWSTR pW) + { + ssadd(*this, pW); + return *this; + } + + MYTYPE& operator+=(CT t) + { + this->append(1, t); + return *this; + } + #ifdef SS_INC_COMDEF // if we have _bstr_t, define a += for it too. + MYTYPE& operator+=(const _bstr_t& bstr) + { + return this->operator+=(static_cast(bstr)); + } + #endif + + + // ------------------------------------------------------------------------- + // Case changing functions + // ------------------------------------------------------------------------- + +#ifndef SS_NO_LOCALE // AR + MYTYPE& ToUpper(const std::locale& loc=std::locale()) + { + // Note -- if there are any MBCS character sets in which the lowercase + // form a character takes up a different number of bytes than the + // uppercase form, this would probably not work... + + std::transform(this->begin(), + this->end(), + this->begin(), + std::bind2nd(SSToUpper(), loc)); + + // ...but if it were, this would probably work better. Also, this way + // seems to be a bit faster when anything other then the "C" locale is + // used... + +// if ( !empty() ) +// { +// ssupr(this->GetBuf(), this->size(), loc); +// this->RelBuf(); +// } + + return *this; + } + + MYTYPE& ToLower(const std::locale& loc=std::locale()) + { + // Note -- if there are any MBCS character sets in which the lowercase + // form a character takes up a different number of bytes than the + // uppercase form, this would probably not work... + + std::transform(this->begin(), + this->end(), + this->begin(), + std::bind2nd(SSToLower(), loc)); + + // ...but if it were, this would probably work better. Also, this way + // seems to be a bit faster when anything other then the "C" locale is + // used... + +// if ( !empty() ) +// { +// sslwr(this->GetBuf(), this->size(), loc); +// this->RelBuf(); +// } + return *this; + } +#endif + + + MYTYPE& Normalize() + { + return Trim().ToLower(); + } + + + // ------------------------------------------------------------------------- + // CStdStr -- Direct access to character buffer. In the MS' implementation, + // the at() function that we use here also calls _Freeze() providing us some + // protection from multithreading problems associated with ref-counting. + // In VC 7 and later, of course, the ref-counting stuff is gone. + // ------------------------------------------------------------------------- + + CT* GetBuf(int nMinLen=-1) + { + if ( static_cast(this->size()) < nMinLen ) + this->resize(static_cast(nMinLen)); + + return this->empty() ? const_cast(this->data()) : &(this->at(0)); + } + + CT* SetBuf(int nLen) + { + nLen = ( nLen > 0 ? nLen : 0 ); + if ( this->capacity() < 1 && nLen == 0 ) + this->resize(1); + + this->resize(static_cast(nLen)); + return const_cast(this->data()); + } + void RelBuf(int nNewLen=-1) + { + this->resize(static_cast(nNewLen > -1 ? nNewLen : + sslen(this->c_str()))); + } + + void BufferRel() { RelBuf(); } // backwards compatability + CT* Buffer() { return GetBuf(); } // backwards compatability + CT* BufferSet(int nLen) { return SetBuf(nLen);}// backwards compatability + + bool Equals(const CT* pT, bool bUseCase=false) const + { + return 0 == (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT)); + } + + // ------------------------------------------------------------------------- + // FUNCTION: CStdStr::Load + // REMARKS: + // Loads string from resource specified by nID + // + // PARAMETERS: + // nID - resource Identifier. Purely a Win32 thing in this case + // + // RETURN VALUE: + // true if successful, false otherwise + // ------------------------------------------------------------------------- + +#ifndef SS_ANSI + + bool Load(UINT nId, HMODULE hModule=NULL) + { + bool bLoaded = false; // set to true of we succeed. + + #ifdef _MFC_VER // When in Rome (or MFC land)... + + // If they gave a resource handle, use it. Note - this is archaic + // and not really what I would recommend. But then again, in MFC + // land, you ought to be using CString for resources anyway since + // it walks the resource chain for you. + + HMODULE hModuleOld = NULL; + + if ( NULL != hModule ) + { + hModuleOld = AfxGetResourceHandle(); + AfxSetResourceHandle(hModule); + } + + // ...load the string + + CString strRes; + bLoaded = FALSE != strRes.LoadString(nId); + + // ...and if we set the resource handle, restore it. + + if ( NULL != hModuleOld ) + AfxSetResourceHandle(hModule); + + if ( bLoaded ) + *this = strRes; + + #else // otherwise make our own hackneyed version of CString's Load + + // Get the resource name and module handle + + if ( NULL == hModule ) + hModule = GetResourceHandle(); + + PCTSTR szName = MAKEINTRESOURCE((nId>>4)+1); // lifted + DWORD dwSize = 0; + + // No sense continuing if we can't find the resource + + HRSRC hrsrc = ::FindResource(hModule, szName, RT_STRING); + + if ( NULL == hrsrc ) + { + TRACE(_T("Cannot find resource %d: 0x%X"), nId, ::GetLastError()); + } + else if ( 0 == (dwSize = ::SizeofResource(hModule, hrsrc) / sizeof(CT))) + { + TRACE(_T("Cant get size of resource %d 0x%X\n"),nId,GetLastError()); + } + else + { + bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize); + ReleaseBuffer(); + } + + #endif // #ifdef _MFC_VER + + if ( !bLoaded ) + TRACE(_T("String not loaded 0x%X\n"), ::GetLastError()); + + return bLoaded; + } + +#endif // #ifdef SS_ANSI + + // ------------------------------------------------------------------------- + // FUNCTION: CStdStr::Format + // void _cdecl Formst(CStdStringA& PCSTR szFormat, ...) + // void _cdecl Format(PCSTR szFormat); + // + // DESCRIPTION: + // This function does sprintf/wsprintf style formatting on CStdStringA + // objects. It looks a lot like MFC's CString::Format. Some people + // might even call this identical. Fortunately, these people are now + // dead... heh heh. + // + // PARAMETERS: + // nId - ID of string resource holding the format string + // szFormat - a PCSTR holding the format specifiers + // argList - a va_list holding the arguments for the format specifiers. + // + // RETURN VALUE: None. + // ------------------------------------------------------------------------- + // formatting (using wsprintf style formatting) + + // If they want a Format() function that safely handles string objects + // without casting + +#ifdef SS_SAFE_FORMAT + + // Question: Joe, you wacky coder you, why do you have so many overloads + // of the Format() function + // Answer: One reason only - CString compatability. In short, by making + // the Format() function a template this way, I can do strong typing + // and allow people to pass CStdString arguments as fillers for + // "%s" format specifiers without crashing their program! The downside + // is that I need to overload on the number of arguments. If you are + // passing more arguments than I have listed below in any of my + // overloads, just add another one. + // + // Yes, yes, this is really ugly. In essence what I am doing here is + // protecting people from a bad (and incorrect) programming practice + // that they should not be doing anyway. I am protecting them from + // themselves. Why am I doing this? Well, if you had any idea the + // number of times I've been emailed by people about this + // "incompatability" in my code, you wouldn't ask. + + void Fmt(const CT* szFmt, ...) + { + va_list argList; + va_start(argList, szFmt); + FormatV(szFmt, argList); + va_end(argList); + } + +#ifndef SS_ANSI + + void Format(UINT nId) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + this->swap(strFmt); + } + template + void Format(UINT nId, const A1& v) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + Fmt(strFmt, FmtArg(v)()); + } + template + void Format(UINT nId, const A1& v1, const A2& v2) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)()); + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(),FmtArg(v5)(), + FmtArg(v6)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(),FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(),FmtArg(v10)(),FmtArg(v11)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)(),FmtArg(v14)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(), FmtArg(v16)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16, const A17& v17) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(),FmtArg(v16)(),FmtArg(v17)()); + } + } + +#endif // #ifndef SS_ANSI + + // ...now the other overload of Format: the one that takes a string literal + + void Format(const CT* szFmt) + { + *this = szFmt; + } + template + void Format(const CT* szFmt, const A1& v) + { + Fmt(szFmt, FmtArg(v)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(),FmtArg(v10)(),FmtArg(v11)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)(),FmtArg(v14)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(), FmtArg(v16)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16, const A17& v17) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(),FmtArg(v16)(),FmtArg(v17)()); + } + +#else // #ifdef SS_SAFE_FORMAT + + +#ifndef SS_ANSI + + void Format(UINT nId, ...) + { + va_list argList; + va_start(argList, nId); + + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + FormatV(strFmt, argList); + + va_end(argList); + } + +#endif // #ifdef SS_ANSI + + void Format(const CT* szFmt, ...) + { + va_list argList; + va_start(argList, szFmt); + FormatV(szFmt, argList); + va_end(argList); + } + +#endif // #ifdef SS_SAFE_FORMAT + + void AppendFormat(const CT* szFmt, ...) + { + va_list argList; + va_start(argList, szFmt); + AppendFormatV(szFmt, argList); + va_end(argList); + } + + #define MAX_FMT_TRIES 5 // #of times we try + #define FMT_BLOCK_SIZE 2048 // # of bytes to increment per try + #define BUFSIZE_1ST 256 + #define BUFSIZE_2ND 512 + #define STD_BUF_SIZE 1024 + + // an efficient way to add formatted characters to the string. You may only + // add up to STD_BUF_SIZE characters at a time, though + void AppendFormatV(const CT* szFmt, va_list argList) + { + CT szBuf[STD_BUF_SIZE]; + int nLen = ssnprintf(szBuf, STD_BUF_SIZE-1, szFmt, argList); + + if ( 0 < nLen ) + this->append(szBuf, nLen); + } + + // ------------------------------------------------------------------------- + // FUNCTION: FormatV + // void FormatV(PCSTR szFormat, va_list, argList); + // + // DESCRIPTION: + // This function formats the string with sprintf style format-specs. + // It makes a general guess at required buffer size and then tries + // successively larger buffers until it finds one big enough or a + // threshold (MAX_FMT_TRIES) is exceeded. + // + // PARAMETERS: + // szFormat - a PCSTR holding the format of the output + // argList - a Microsoft specific va_list for variable argument lists + // + // RETURN VALUE: + // ------------------------------------------------------------------------- + + void FormatV(const CT* szFormat, va_list argList) + { + #ifdef SS_ANSI + + MYTYPE str; + int nLen = sslen(szFormat) + STD_BUF_SIZE; + +// OG replace ssnprint by ssvsprint for mac osx +#if !defined(DRIVER_WINDOWS) + ssvsprintf(str.GetBuffer(nLen), nLen-1, szFormat, argList); +#else + ssnprintf(str.GetBuffer(nLen), nLen-1, szFormat, argList); +#endif + + str.ReleaseBuffer(); + *this = str; + + #else + + CT* pBuf = NULL; + int nChars = 1; + int nUsed = 0; + size_type nActual = 0; + int nTry = 0; + + do + { + // Grow more than linearly (e.g. 512, 1536, 3072, etc) + + nChars += ((nTry+1) * FMT_BLOCK_SIZE); + pBuf = reinterpret_cast(_alloca(sizeof(CT)*nChars)); + nUsed = ssnprintf(pBuf, nChars-1, szFormat, argList); + + // Ensure proper NULL termination. + + nActual = nUsed == -1 ? nChars-1 : SSMIN(nUsed, nChars-1); + pBuf[nActual]= '\0'; + + + } while ( nUsed < 0 && nTry++ < MAX_FMT_TRIES ); + + // assign whatever we managed to format + + this->assign(pBuf, nActual); + + #endif + } + + // ------------------------------------------------------------------------- + // CString Facade Functions: + // + // The following methods are intended to allow you to use this class as a + // near drop-in replacement for CString. + // ------------------------------------------------------------------------- + #ifdef SS_WIN32 + BSTR AllocSysString() const + { + ostring os; + ssasn(os, *this); + return ::SysAllocString(os.c_str()); + } + #endif + +#ifndef SS_NO_LOCALE + int Collate(PCMYSTR szThat) const + { + return sscoll(this->c_str(), this->length(), szThat, sslen(szThat)); + } + + int CollateNoCase(PCMYSTR szThat) const + { + return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat)); + } +#endif + int Compare(PCMYSTR szThat) const + { + return this->compare(szThat); + } + + int CompareNoCase(PCMYSTR szThat) const + { + return ssicmp(this->c_str(), szThat); + } + + int Delete(int nIdx, int nCount=1) + { + if ( nIdx < 0 ) + nIdx = 0; + + if ( nIdx < this->GetLength() ) + this->erase(static_cast(nIdx), static_cast(nCount)); + + return GetLength(); + } + + void Empty() + { + this->erase(); + } + + int Find(CT ch) const + { + MYSIZE nIdx = this->find_first_of(ch); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int Find(PCMYSTR szSub) const + { + MYSIZE nIdx = this->find(szSub); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int Find(CT ch, int nStart) const + { + // CString::Find docs say add 1 to nStart when it's not zero + // CString::Find code doesn't do that however. We'll stick + // with what the code does + + MYSIZE nIdx = this->find_first_of(ch, static_cast(nStart)); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int Find(PCMYSTR szSub, int nStart) const + { + // CString::Find docs say add 1 to nStart when it's not zero + // CString::Find code doesn't do that however. We'll stick + // with what the code does + + MYSIZE nIdx = this->find(szSub, static_cast(nStart)); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int FindOneOf(PCMYSTR szCharSet) const + { + MYSIZE nIdx = this->find_first_of(szCharSet); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + +#ifndef SS_ANSI + void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception) + { + va_list argList; + va_start(argList, szFormat); + PMYSTR szTemp; + if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, + szFormat, 0, 0, + reinterpret_cast(&szTemp), 0, &argList) == 0 || + szTemp == 0 ) + { + throw std::runtime_error("out of memory"); + } + *this = szTemp; + LocalFree(szTemp); + va_end(argList); + } + + void FormatMessage(UINT nFormatId, ...) throw(std::exception) + { + MYTYPE sFormat; + VERIFY(sFormat.LoadString(nFormatId)); + va_list argList; + va_start(argList, nFormatId); + PMYSTR szTemp; + if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, + sFormat, 0, 0, + reinterpret_cast(&szTemp), 0, &argList) == 0 || + szTemp == 0) + { + throw std::runtime_error("out of memory"); + } + *this = szTemp; + LocalFree(szTemp); + va_end(argList); + } +#endif + + // GetAllocLength -- an MSVC7 function but it costs us nothing to add it. + + int GetAllocLength() + { + return static_cast(this->capacity()); + } + + // ------------------------------------------------------------------------- + // GetXXXX -- Direct access to character buffer + // ------------------------------------------------------------------------- + CT GetAt(int nIdx) const + { + return this->at(static_cast(nIdx)); + } + + CT* GetBuffer(int nMinLen=-1) + { + return GetBuf(nMinLen); + } + + CT* GetBufferSetLength(int nLen) + { + return BufferSet(nLen); + } + + // GetLength() -- MFC docs say this is the # of BYTES but + // in truth it is the number of CHARACTERs (chars or wchar_ts) + int GetLength() const + { + return static_cast(this->length()); + } + + int Insert(int nIdx, CT ch) + { + if ( static_cast(nIdx) > this->size()-1 ) + this->append(1, ch); + else + this->insert(static_cast(nIdx), 1, ch); + + return GetLength(); + } + int Insert(int nIdx, PCMYSTR sz) + { + if ( static_cast(nIdx) >= this->size() ) + this->append(sz, static_cast(sslen(sz))); + else + this->insert(static_cast(nIdx), sz); + + return GetLength(); + } + + bool IsEmpty() const + { + return this->empty(); + } + + MYTYPE Left(int nCount) const + { + // Range check the count. + + nCount = SSMAX(0, SSMIN(nCount, static_cast(this->size()))); + return this->substr(0, static_cast(nCount)); + } + +#ifndef SS_ANSI + bool LoadString(UINT nId) + { + return this->Load(nId); + } +#endif + + void MakeLower() + { + ToLower(); + } + + void MakeReverse() + { + std::reverse(this->begin(), this->end()); + } + + void MakeUpper() + { + ToUpper(); + } + + MYTYPE Mid(int nFirst) const + { + return Mid(nFirst, this->GetLength()-nFirst); + } + + MYTYPE Mid(int nFirst, int nCount) const + { + // CString does range checking here. Since we're trying to emulate it, + // we must check too. + + if ( nFirst < 0 ) + nFirst = 0; + if ( nCount < 0 ) + nCount = 0; + + int nSize = static_cast(this->size()); + + if ( nFirst + nCount > nSize ) + nCount = nSize - nFirst; + + if ( nFirst > nSize ) + return MYTYPE(); + + ASSERT(nFirst >= 0); + ASSERT(nFirst + nCount <= nSize); + + return this->substr(static_cast(nFirst), + static_cast(nCount)); + } + + void ReleaseBuffer(int nNewLen=-1) + { + RelBuf(nNewLen); + } + + int Remove(CT ch) + { + MYSIZE nIdx = 0; + int nRemoved = 0; + while ( (nIdx=this->find_first_of(ch)) != MYBASE::npos ) + { + this->erase(nIdx, 1); + nRemoved++; + } + return nRemoved; + } + + int Replace(CT chOld, CT chNew) + { + int nReplaced = 0; + + for ( MYITER iter=this->begin(); iter != this->end(); iter++ ) + { + if ( *iter == chOld ) + { + *iter = chNew; + nReplaced++; + } + } + + return nReplaced; + } + + int Replace(PCMYSTR szOld, PCMYSTR szNew) + { + int nReplaced = 0; + MYSIZE nIdx = 0; + MYSIZE nOldLen = sslen(szOld); + + if ( 0 != nOldLen ) + { + // If the replacement string is longer than the one it replaces, this + // string is going to have to grow in size, Figure out how much + // and grow it all the way now, rather than incrementally + + MYSIZE nNewLen = sslen(szNew); + if ( nNewLen > nOldLen ) + { + int nFound = 0; + while ( nIdx < this->length() && + (nIdx=this->find(szOld, nIdx)) != MYBASE::npos ) + { + nFound++; + nIdx += nOldLen; + } + this->reserve(this->size() + nFound * (nNewLen - nOldLen)); + } + + + static const CT ch = CT(0); + PCMYSTR szRealNew = szNew == 0 ? &ch : szNew; + nIdx = 0; + + while ( nIdx < this->length() && + (nIdx=this->find(szOld, nIdx)) != MYBASE::npos ) + { + this->replace(this->begin()+nIdx, this->begin()+nIdx+nOldLen, + szRealNew); + + nReplaced++; + nIdx += nNewLen; + } + } + + return nReplaced; + } + + int ReverseFind(CT ch) const + { + MYSIZE nIdx = this->find_last_of(ch); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + // ReverseFind overload that's not in CString but might be useful + // OG : had to add (PCMYSTR) cast to cope with XCode compilation issue + int ReverseFind(PCMYSTR szFind, MYSIZE pos=MYBASE::npos) const + { + MYSIZE nIdx = this->rfind(0 == szFind ? (PCMYSTR) MYTYPE() : szFind, pos); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + MYTYPE Right(int nCount) const + { + // Range check the count. + + nCount = SSMAX(0, SSMIN(nCount, static_cast(this->size()))); + return this->substr(this->size()-static_cast(nCount)); + } + + void SetAt(int nIndex, CT ch) + { + ASSERT(this->size() > static_cast(nIndex)); + this->at(static_cast(nIndex)) = ch; + } + +#ifndef SS_ANSI + BSTR SetSysString(BSTR* pbstr) const + { + ostring os; + ssasn(os, *this); + if ( !::SysReAllocStringLen(pbstr, os.c_str(), os.length()) ) + throw std::runtime_error("out of memory"); + + ASSERT(*pbstr != 0); + return *pbstr; + } +#endif + + MYTYPE SpanExcluding(PCMYSTR szCharSet) const + { + MYSIZE pos = this->find_first_of(szCharSet); + return pos == MYBASE::npos ? *this : Left(pos); + } + + MYTYPE SpanIncluding(PCMYSTR szCharSet) const + { + MYSIZE pos = this->find_first_not_of(szCharSet); + return pos == MYBASE::npos ? *this : Left(pos); + } + +#if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI) + + // CString's OemToAnsi and AnsiToOem functions are available only in + // Unicode builds. However since we're a template we also need a + // runtime check of CT and a reinterpret_cast to account for the fact + // that CStdStringW gets instantiated even in non-Unicode builds. + + void AnsiToOem() + { + if ( sizeof(CT) == sizeof(char) && !empty() ) + { + ::CharToOem(reinterpret_cast(this->c_str()), + reinterpret_cast(GetBuf())); + } + else + { + ASSERT(false); + } + } + + void OemToAnsi() + { + if ( sizeof(CT) == sizeof(char) && !empty() ) + { + ::OemToChar(reinterpret_cast(this->c_str()), + reinterpret_cast(GetBuf())); + } + else + { + ASSERT(false); + } + } + +#endif + + + // ------------------------------------------------------------------------- + // Trim and its variants + // ------------------------------------------------------------------------- + MYTYPE& Trim() + { + return TrimLeft().TrimRight(); + } + + MYTYPE& TrimLeft() + { + this->erase(this->begin(), + std::find_if(this->begin(), this->end(), NotSpace())); + + return *this; + } + + MYTYPE& TrimLeft(CT tTrim) + { + this->erase(0, this->find_first_not_of(tTrim)); + return *this; + } + + MYTYPE& TrimLeft(PCMYSTR szTrimChars) + { + this->erase(0, this->find_first_not_of(szTrimChars)); + return *this; + } + + MYTYPE& TrimRight() + { + // NOTE: When comparing reverse_iterators here (MYRITER), I avoid using + // operator!=. This is because namespace rel_ops also has a template + // operator!= which conflicts with the global operator!= already defined + // for reverse_iterator in the header . + // Thanks to John James for alerting me to this. + + MYRITER it = std::find_if(this->rbegin(), this->rend(), NotSpace()); + if ( !(this->rend() == it) ) + this->erase(this->rend() - it); + + this->erase(!(it == this->rend()) ? this->find_last_of(*it) + 1 : 0); + return *this; + } + + MYTYPE& TrimRight(CT tTrim) + { + MYSIZE nIdx = this->find_last_not_of(tTrim); + this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx); + return *this; + } + + MYTYPE& TrimRight(PCMYSTR szTrimChars) + { + MYSIZE nIdx = this->find_last_not_of(szTrimChars); + this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx); + return *this; + } + + void FreeExtra() + { + MYTYPE mt; + this->swap(mt); + if ( !mt.empty() ) + this->assign(mt.c_str(), mt.size()); + } + + // I have intentionally not implemented the following CString + // functions. You cannot make them work without taking advantage + // of implementation specific behavior. However if you absolutely + // MUST have them, uncomment out these lines for "sort-of-like" + // their behavior. You're on your own. + + CT* LockBuffer() { return GetBuf(); }// won't really lock + void UnlockBuffer() { }; // why have UnlockBuffer w/o LockBuffer? + + // Array-indexing operators. Required because we defined an implicit cast + // to operator const CT* (Thanks to Julian Selman for pointing this out) + + CT& operator[](int nIdx) + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + const CT& operator[](int nIdx) const + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + CT& operator[](unsigned int nIdx) + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + const CT& operator[](unsigned int nIdx) const + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + +#ifndef SS_NO_IMPLICIT_CAST + operator const CT*() const + { + return this->c_str(); + } +#endif + + // IStream related functions. Useful in IPersistStream implementations + +#ifdef SS_INC_COMDEF + + // struct SSSHDR - useful for non Std C++ persistence schemes. + typedef struct SSSHDR + { + BYTE byCtrl; + ULONG nChars; + } SSSHDR; // as in "Standard String Stream Header" + + #define SSSO_UNICODE 0x01 // the string is a wide string + #define SSSO_COMPRESS 0x02 // the string is compressed + + // ------------------------------------------------------------------------- + // FUNCTION: StreamSize + // REMARKS: + // Returns how many bytes it will take to StreamSave() this CStdString + // object to an IStream. + // ------------------------------------------------------------------------- + ULONG StreamSize() const + { + // Control header plus string + ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR)); + return (this->size() * sizeof(CT)) + sizeof(SSSHDR); + } + + // ------------------------------------------------------------------------- + // FUNCTION: StreamSave + // REMARKS: + // Saves this CStdString object to a COM IStream. + // ------------------------------------------------------------------------- + HRESULT StreamSave(IStream* pStream) const + { + ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR)); + HRESULT hr = E_FAIL; + ASSERT(pStream != 0); + SSSHDR hdr; + hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0; + hdr.nChars = this->size(); + + + if ( FAILED(hr=pStream->Write(&hdr, sizeof(SSSHDR), 0)) ) + { + TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),hr); + } + else if ( empty() ) + { + ; // nothing to write + } + else if ( FAILED(hr=pStream->Write(this->c_str(), + this->size()*sizeof(CT), 0)) ) + { + TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr); + } + + return hr; + } + + + // ------------------------------------------------------------------------- + // FUNCTION: StreamLoad + // REMARKS: + // This method loads the object from an IStream. + // ------------------------------------------------------------------------- + HRESULT StreamLoad(IStream* pStream) + { + ASSERT(pStream != 0); + SSSHDR hdr; + HRESULT hr = E_FAIL; + + if ( FAILED(hr=pStream->Read(&hdr, sizeof(SSSHDR), 0)) ) + { + TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr); + } + else if ( hdr.nChars > 0 ) + { + ULONG nRead = 0; + PMYSTR pMyBuf = BufferSet(hdr.nChars); + + // If our character size matches the character size of the string + // we're trying to read, then we can read it directly into our + // buffer. Otherwise, we have to read into an intermediate buffer + // and convert. + + if ( (hdr.byCtrl & SSSO_UNICODE) != 0 ) + { + ULONG nBytes = hdr.nChars * sizeof(wchar_t); + if ( sizeof(CT) == sizeof(wchar_t) ) + { + if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + } + else + { + PWSTR pBufW = reinterpret_cast(_alloca((nBytes)+1)); + if ( FAILED(hr=pStream->Read(pBufW, nBytes, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + else + sscpy(pMyBuf, pBufW, hdr.nChars); + } + } + else + { + ULONG nBytes = hdr.nChars * sizeof(char); + if ( sizeof(CT) == sizeof(char) ) + { + if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + } + else + { + PSTR pBufA = reinterpret_cast(_alloca(nBytes)); + if ( FAILED(hr=pStream->Read(pBufA, hdr.nChars, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + else + sscpy(pMyBuf, pBufA, hdr.nChars); + } + } + } + else + { + this->erase(); + } + return hr; + } +#endif // #ifdef SS_INC_COMDEF + +#ifndef SS_ANSI + + // SetResourceHandle/GetResourceHandle. In MFC builds, these map directly + // to AfxSetResourceHandle and AfxGetResourceHandle. In non-MFC builds they + // point to a single static HINST so that those who call the member + // functions that take resource IDs can provide an alternate HINST of a DLL + // to search. This is not exactly the list of HMODULES that MFC provides + // but it's better than nothing. + + #ifdef _MFC_VER + static void SetResourceHandle(HMODULE hNew) + { + AfxSetResourceHandle(hNew); + } + static HMODULE GetResourceHandle() + { + return AfxGetResourceHandle(); + } + #elif defined(_WTL_VER) // AR: WTL has no SetResourceHandle equivalent + static HMODULE GetResourceHandle() + { + #if (_ATL_VER >= 0x0700) + return ATL::_AtlBaseModule.GetResourceInstance(); + #else // !(_ATL_VER >= 0x0700) + return _Module.GetResourceInstance(); + #endif // !(_ATL_VER >= 0x0700) + } + #else + static void SetResourceHandle(HMODULE hNew) + { + SSResourceHandle() = hNew; + } + + static HMODULE GetResourceHandle() + { + return SSResourceHandle(); + } + #endif + +#endif +}; + +// ----------------------------------------------------------------------------- +// MSVC USERS: HOW TO EXPORT CSTDSTRING FROM A DLL +// +// If you are using MS Visual C++ and you want to export CStdStringA and +// CStdStringW from a DLL, then all you need to +// +// 1. make sure that all components link to the same DLL version +// of the CRT (not the static one). +// 2. Uncomment the 3 lines of code below +// 3. #define 2 macros per the instructions in MS KnowledgeBase +// article Q168958. The macros are: +// +// MACRO DEFINTION WHEN EXPORTING DEFINITION WHEN IMPORTING +// ----- ------------------------ ------------------------- +// SSDLLEXP (nothing, just #define it) extern +// SSDLLSPEC __declspec(dllexport) __declspec(dllimport) +// +// Note that these macros must be available to ALL clients who want to +// link to the DLL and use the class. If they +// +// A word of advice: Don't bother. +// +// Really, it is not necessary to export CStdString functions from a DLL. I +// never do. In my projects, I do generally link to the DLL version of the +// Standard C++ Library, but I do NOT attempt to export CStdString functions. +// I simply include the header where it is needed and allow for the code +// redundancy. +// +// That redundancy is a lot less than you think. This class does most of its +// work via the Standard C++ Library, particularly the base_class basic_string<> +// member functions. Most of the functions here are small enough to be inlined +// anyway. Besides, you'll find that in actual practice you use less than 1/2 +// of the code here, even in big projects and different modules will use as +// little as 10% of it. That means a lot less functions actually get linked +// your binaries. If you export this code from a DLL, it ALL gets linked in. +// +// I've compared the size of the binaries from exporting vs NOT exporting. Take +// my word for it -- exporting this code is not worth the hassle. +// +// ----------------------------------------------------------------------------- +//#pragma warning(disable:4231) // non-standard extension ("extern template") +// SSDLLEXP template class SSDLLSPEC CStdStr; +// SSDLLEXP template class SSDLLSPEC CStdStr; + + +// ============================================================================= +// END OF CStdStr INLINE FUNCTION DEFINITIONS +// ============================================================================= + +// Now typedef our class names based upon this humongous template + +typedef CStdStr CStdStringA; // a better std::string +typedef CStdStr CStdStringW; // a better std::wstring +typedef CStdStr CStdStringO; // almost always CStdStringW + +// ----------------------------------------------------------------------------- +// CStdStr addition functions defined as inline +// ----------------------------------------------------------------------------- + + +inline CStdStringA operator+(const CStdStringA& s1, const CStdStringA& s2) +{ + CStdStringA sRet(SSREF(s1)); + sRet.append(s2); + return sRet; +} +inline CStdStringA operator+(const CStdStringA& s1, CStdStringA::value_type t) +{ + CStdStringA sRet(SSREF(s1)); + sRet.append(1, t); + return sRet; +} +inline CStdStringA operator+(const CStdStringA& s1, PCSTR pA) +{ + CStdStringA sRet(SSREF(s1)); + sRet.append(pA); + return sRet; +} +inline CStdStringA operator+(PCSTR pA, const CStdStringA& sA) +{ + CStdStringA sRet; + CStdStringA::size_type nObjSize = sA.size(); + CStdStringA::size_type nLitSize = + static_cast(sslen(pA)); + + sRet.reserve(nLitSize + nObjSize); + sRet.assign(pA); + sRet.append(sA); + return sRet; +} + + +inline CStdStringA operator+(const CStdStringA& s1, const CStdStringW& s2) +{ + return s1 + CStdStringA(s2); +} +inline CStdStringW operator+(const CStdStringW& s1, const CStdStringW& s2) +{ + CStdStringW sRet(SSREF(s1)); + sRet.append(s2); + return sRet; +} +inline CStdStringA operator+(const CStdStringA& s1, PCWSTR pW) +{ + return s1 + CStdStringA(pW); +} + +#ifdef UNICODE + inline CStdStringW operator+(PCWSTR pW, const CStdStringA& sA) + { + return CStdStringW(pW) + CStdStringW(SSREF(sA)); + } + inline CStdStringW operator+(PCSTR pA, const CStdStringW& sW) + { + return CStdStringW(pA) + sW; + } +#else + inline CStdStringA operator+(PCWSTR pW, const CStdStringA& sA) + { + return CStdStringA(pW) + sA; + } + inline CStdStringA operator+(PCSTR pA, const CStdStringW& sW) + { + return pA + CStdStringA(sW); + } +#endif + +// ...Now the wide string versions. +inline CStdStringW operator+(const CStdStringW& s1, CStdStringW::value_type t) +{ + CStdStringW sRet(SSREF(s1)); + sRet.append(1, t); + return sRet; +} +inline CStdStringW operator+(const CStdStringW& s1, PCWSTR pW) +{ + CStdStringW sRet(SSREF(s1)); + sRet.append(pW); + return sRet; +} +inline CStdStringW operator+(PCWSTR pW, const CStdStringW& sW) +{ + CStdStringW sRet; + CStdStringW::size_type nObjSize = sW.size(); + CStdStringA::size_type nLitSize = + static_cast(sslen(pW)); + + sRet.reserve(nLitSize + nObjSize); + sRet.assign(pW); + sRet.append(sW); + return sRet; +} + +inline CStdStringW operator+(const CStdStringW& s1, const CStdStringA& s2) +{ + return s1 + CStdStringW(s2); +} +inline CStdStringW operator+(const CStdStringW& s1, PCSTR pA) +{ + return s1 + CStdStringW(pA); +} + + +// New-style format function is a template + +#ifdef SS_SAFE_FORMAT + +template<> +struct FmtArg +{ + explicit FmtArg(const CStdStringA& arg) : a_(arg) {} + PCSTR operator()() const { return a_.c_str(); } + const CStdStringA& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; +template<> +struct FmtArg +{ + explicit FmtArg(const CStdStringW& arg) : a_(arg) {} + PCWSTR operator()() const { return a_.c_str(); } + const CStdStringW& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; + +template<> +struct FmtArg +{ + explicit FmtArg(const std::string& arg) : a_(arg) {} + PCSTR operator()() const { return a_.c_str(); } + const std::string& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; +template<> +struct FmtArg +{ + explicit FmtArg(const std::wstring& arg) : a_(arg) {} + PCWSTR operator()() const { return a_.c_str(); } + const std::wstring& a_; +private: + FmtArg& operator=(const FmtArg&) {return *this;} +}; +#endif // #ifdef SS_SAFEFORMAT + +#ifndef SS_ANSI + // SSResourceHandle: our MFC-like resource handle + inline HMODULE& SSResourceHandle() + { + static HMODULE hModuleSS = GetModuleHandle(0); + return hModuleSS; + } +#endif + + +// In MFC builds, define some global serialization operators +// Special operators that allow us to serialize CStdStrings to CArchives. +// Note that we use an intermediate CString object in order to ensure that +// we use the exact same format. + +#ifdef _MFC_VER + /* + //OG + inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringA& strA) + { + CString strTemp = strA; + return ar << strTemp; + } + inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringW& strW) + { + CString strTemp = strW; + return ar << strTemp; + } + */ + + inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringA& strA) + { + CString strTemp; + ar >> strTemp; + strA = strTemp; + return ar; + } + inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringW& strW) + { + CString strTemp; + ar >> strTemp; + strW = strTemp; + return ar; + } +#endif // #ifdef _MFC_VER -- (i.e. is this MFC?) + + + +// ----------------------------------------------------------------------------- +// GLOBAL FUNCTION: WUFormat +// CStdStringA WUFormat(UINT nId, ...); +// CStdStringA WUFormat(PCSTR szFormat, ...); +// +// REMARKS: +// This function allows the caller for format and return a CStdStringA +// object with a single line of code. +// ----------------------------------------------------------------------------- + +inline CStdStringA WUFormatA(PCSTR szFormat, ...) +{ + va_list argList; + va_start(argList, szFormat); + CStdStringA strOut; + strOut.FormatV(szFormat, argList); + va_end(argList); + return strOut; +} +inline CStdStringW WUFormatW(PCWSTR szwFormat, ...) +{ + va_list argList; + va_start(argList, szwFormat); + CStdStringW strOut; + strOut.FormatV(szwFormat, argList); + va_end(argList); + return strOut; +} +#ifdef SS_ANSI +#else + inline CStdStringA WUFormatA(UINT nId, ...) + { + va_list argList; + va_start(argList, nId); + + CStdStringA strFmt; + CStdStringA strOut; + if ( strFmt.Load(nId) ) + strOut.FormatV(strFmt, argList); + + va_end(argList); + return strOut; + } + + inline CStdStringW WUFormatW(UINT nId, ...) + { + va_list argList; + va_start(argList, nId); + + CStdStringW strFmt; + CStdStringW strOut; + if ( strFmt.Load(nId) ) + strOut.FormatV(strFmt, argList); + + va_end(argList); + return strOut; + } +#endif // #ifdef SS_ANSI + + + +#if defined(SS_WIN32) && !defined (SS_ANSI) + // ------------------------------------------------------------------------- + // FUNCTION: WUSysMessage + // CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID); + // CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID); + // + // DESCRIPTION: + // This function simplifies the process of obtaining a string equivalent + // of a system error code returned from GetLastError(). You simply + // supply the value returned by GetLastError() to this function and the + // corresponding system string is returned in the form of a CStdStringA. + // + // PARAMETERS: + // dwError - a DWORD value representing the error code to be translated + // dwLangId - the language id to use. defaults to english. + // + // RETURN VALUE: + // a CStdStringA equivalent of the error code. Currently, this function + // only returns either English of the system default language strings. + // ------------------------------------------------------------------------- + #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT) + inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID) + { + CHAR szBuf[512]; + + if ( 0 != ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, + dwLangId, szBuf, 511, NULL) ) + return WUFormatA("%s (0x%X)", szBuf, dwError); + else + return WUFormatA("Unknown error (0x%X)", dwError); + } + inline CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID) + { + WCHAR szBuf[512]; + + if ( 0 != ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, + dwLangId, szBuf, 511, NULL) ) + return WUFormatW(L"%s (0x%X)", szBuf, dwError); + else + return WUFormatW(L"Unknown error (0x%X)", dwError); + } +#endif + +// Define TCHAR based friendly names for some of these functions + +#ifdef UNICODE + //#define CStdString CStdStringW + typedef CStdStringW CStdString; + #define WUSysMessage WUSysMessageW + #define WUFormat WUFormatW +#else + //#define CStdString CStdStringA + typedef CStdStringA CStdString; + #define WUSysMessage WUSysMessageA + #define WUFormat WUFormatA +#endif + +// ...and some shorter names for the space-efficient + +#define WUSysMsg WUSysMessage +#define WUSysMsgA WUSysMessageA +#define WUSysMsgW WUSysMessageW +#define WUFmtA WUFormatA +#define WUFmtW WUFormatW +#define WUFmt WUFormat +#define WULastErrMsg() WUSysMessage(::GetLastError()) +#define WULastErrMsgA() WUSysMessageA(::GetLastError()) +#define WULastErrMsgW() WUSysMessageW(::GetLastError()) + + +// ----------------------------------------------------------------------------- +// FUNCTIONAL COMPARATORS: +// REMARKS: +// These structs are derived from the std::binary_function template. They +// give us functional classes (which may be used in Standard C++ Library +// collections and algorithms) that perform case-insensitive comparisons of +// CStdString objects. This is useful for maps in which the key may be the +// proper string but in the wrong case. +// ----------------------------------------------------------------------------- +#define StdStringLessNoCaseW SSLNCW // avoid VC compiler warning 4786 +#define StdStringEqualsNoCaseW SSENCW +#define StdStringLessNoCaseA SSLNCA +#define StdStringEqualsNoCaseA SSENCA + +#ifdef UNICODE + #define StdStringLessNoCase SSLNCW + #define StdStringEqualsNoCase SSENCW +#else + #define StdStringLessNoCase SSLNCA + #define StdStringEqualsNoCase SSENCA +#endif + +struct StdStringLessNoCaseW + : std::binary_function +{ + inline + bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; } +}; +struct StdStringEqualsNoCaseW + : std::binary_function +{ + inline + bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; } +}; +struct StdStringLessNoCaseA + : std::binary_function +{ + inline + bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; } +}; +struct StdStringEqualsNoCaseA + : std::binary_function +{ + inline + bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; } +}; + +// If we had to define our own version of TRACE above, get rid of it now + +#ifdef TRACE_DEFINED_HERE + #undef TRACE + #undef TRACE_DEFINED_HERE +#endif + + +// These std::swap specializations come courtesy of Mike Crusader. + +//namespace std +//{ +// inline void swap(CStdStringA& s1, CStdStringA& s2) throw() +// { +// s1.swap(s2); +// } +// template<> +// inline void swap(CStdStringW& s1, CStdStringW& s2) throw() +// { +// s1.swap(s2); +// } +//} + +// Turn back on any Borland warnings we turned off. + +#ifdef __BORLANDC__ + #pragma option pop // Turn back on inline function warnings +// #pragma warn +inl // Turn back on inline function warnings +#endif + + +#define MyString CStdStringA // Force Non Unicode + +#endif // #ifndef STDSTRING_H diff --git a/kegs/Src/adb.cpp b/kegs/Src/adb.cpp new file mode 100644 index 0000000..8d0d376 --- /dev/null +++ b/kegs/Src/adb.cpp @@ -0,0 +1,2089 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "adb.h" +#include "moremem.h" +#include "paddles.h" +#include "sim65816.h" +#include "video.h" +#include "iwm.h" +#include "config.h" +#include "async_event.h" +#include "driver.h" + +s_adb g_adb; + +#define SHIFT_DOWN ( (g_adb.g_c025_val & 0x01) ) +#define CTRL_DOWN ( (g_adb.g_c025_val & 0x02) ) +#define CAPS_LOCK_DOWN ( (g_adb.g_c025_val & 0x04) ) +#define OPTION_DOWN ( (g_adb.g_c025_val & 0x40) ) +#define CMD_DOWN ( (g_adb.g_c025_val & 0x80) ) + +#define adb_print printf + +/* Format: a2code, ascii if no shift, ascii if shift, ascii if ctl */ + +const int a2_key_to_ascii[][4] = +{ + { 0x00, 'a', 'A', 0x01 }, + { 0x01, 's', 'S', 0x13 }, + { 0x02, 'd', 'D', 0x04 }, + { 0x03, 'f', 'F', 0x06 }, + { 0x04, 'h', 'H', 0x08 }, + { 0x05, 'g', 'G', 0x07 }, + { 0x06, 'z', 'Z', 0x1a }, + { 0x07, 'x', 'X', 0x18 }, + + { 0x08, 'c', 'C', 0x03 }, + { 0x09, 'v', 'V', 0x16 }, + { 0x0a, -1, -1, -1 }, + { 0x0b, 'b', 'B', 0x02 }, + { 0x0c, 'q', 'Q', 0x11 }, + { 0x0d, 'w', 'W', 0x17 }, + { 0x0e, 'e', 'E', 0x05 }, + { 0x0f, 'r', 'R', 0x12 }, + + { 0x10, 'y', 'Y', 0x19 }, + { 0x11, 't', 'T', 0x14 }, + { 0x12, '1', '!', -1 }, + { 0x13, '2', '@', 0x00 }, + { 0x14, '3', '#', -1 }, + { 0x15, '4', '$', -1 }, + { 0x16, '6', '^', 0x1e }, + { 0x17, '5', '%', -1 }, + + { 0x18, '=', '+', -1 }, + { 0x19, '9', '(', -1 }, + { 0x1a, '7', '&', -1 }, + { 0x1b, '-', '_', 0x1f }, + { 0x1c, '8', '*', -1 }, + { 0x1d, '0', ')', -1 }, + { 0x1e, ']', '}', 0x1d }, + { 0x1f, 'o', 'O', 0x0f }, + + { 0x20, 'u', 'U', 0x15 }, + { 0x21, '[', '{', 0x1b }, + { 0x22, 'i', 'I', 0x09 }, + { 0x23, 'p', 'P', 0x10 }, + { 0x24, 0x0d, 0x0d, -1 }, /* return */ + { 0x25, 'l', 'L', 0x0c }, + { 0x26, 'j', 'J', 0x0a }, + { 0x27, 0x27, '"', -1 }, /* single quote */ + + { 0x28, 'k', 'K', 0x0b }, + { 0x29, ';', ':', -1 }, + { 0x2a, 0x5c, '|', 0x1c }, /* \, | */ + { 0x2b, ',', '<', -1 }, + { 0x2c, '/', '?', 0x7f }, + { 0x2d, 'n', 'N', 0x0e }, + { 0x2e, 'm', 'M', 0x0d }, + { 0x2f, '.', '>', -1 }, + + { 0x30, 0x09, 0x09, -1 }, /* tab */ + { 0x31, ' ', ' ', -1 }, + { 0x32, '`', '~', -1 }, + { 0x33, 0x7f, 0x7f, -1 }, /* Delete */ + { 0x34, -1, -1, -1 }, + { 0x35, 0x1b, 0x1b, -1 }, /* Esc */ + { 0x36, 0x0200, 0x0200, -1 }, /* control */ + { 0x37, 0x8000, 0x8000, -1 }, /* Command */ + + { 0x38, 0x0100, 0x0100, -1 }, /* shift */ + { 0x39, 0x0400, 0x0400, -1 }, /* caps lock */ + { 0x3a, 0x4000, 0x4000, -1 }, /* Option */ + { 0x3b, 0x08, 0x08, -1 }, /* left */ + { 0x3c, 0x15, 0x15, -1 }, /* right */ + { 0x3d, 0x0a, 0x0a, -1 }, /* down */ + { 0x3e, 0x0b, 0x0b, -1 }, /* up arrow */ + { 0x3f, -1, -1, -1 }, + + { 0x40, -1, -1, -1 }, + { 0x41, 0x102e, 0x102c, -1 }, /* keypad . */ + { 0x42, -1, -1, -1 }, + { 0x43, 0x102a, 0x102a, -1 }, /* keypad * */ + { 0x44, -1, -1, -1 }, + { 0x45, 0x102b, 0x102b, -1 }, /* keypad + */ + { 0x46, -1, -1, -1 }, + { 0x47, 0x1018, 0x1018, -1 }, /* keypad Clear */ + + { 0x48, -1, -1, -1 }, + { 0x49, -1, -1, -1 }, + { 0x4a, -1, -1, -1 }, + { 0x4b, 0x102f, 0x102f, -1 }, /* keypad / */ + { 0x4c, 0x100d, 0x100d, -1 }, /* keypad enter */ + { 0x4d, -1, -1, -1 }, + { 0x4e, 0x102d, 0x102d, -1 }, /* keypad - */ + { 0x4f, -1, -1, -1 }, + + { 0x50, -1, -1, -1 }, + { 0x51, 0x103d, 0x103d, -1 }, /* keypad = */ + { 0x52, 0x1030, 0x1030, -1 }, /* keypad 0 */ + { 0x53, 0x1031, 0x1031, -1 }, /* keypad 1 */ + { 0x54, 0x1032, 0x1032, -1 }, /* keypad 2 */ + { 0x55, 0x1033, 0x1033, -1 }, /* keypad 3 */ + { 0x56, 0x1034, 0x1034, -1 }, /* keypad 4 */ + { 0x57, 0x1035, 0x1035, -1 }, /* keypad 5 */ + + { 0x58, 0x1036, 0x1036, -1 }, /* keypad 6 */ + { 0x59, 0x1037, 0x1037, -1 }, /* keypad 7 */ + { 0x5a, 'a', 'A', 0x01 }, /* probably not necessary */ + { 0x5b, 0x1038, 0x1038, -1 }, /* keypad 8 */ + { 0x5c, 0x1039, 0x1039, -1 }, /* keypad 9 */ + { 0x5d, -1, -1, -1 }, + { 0x5e, -1, -1, -1 }, + { 0x5f, -1, -1, -1 }, + + { 0x60, 0x8005, 0x1060, -1 }, /* F5 */ + { 0x61, 0x8006, 0x1061, -1 }, /* F6 */ + { 0x62, 0x8007, 0x1062, -1 }, /* F7 */ + { 0x63, 0x8003, 0x1063, -1 }, /* F3 */ + { 0x64, 0x8008, 0x1064, -1 }, /* F8 */ + { 0x65, 0x8009, 0x1065, -1 }, /* F9 */ + { 0x66, -1, -1, -1 }, + { 0x67, 0x800b, 0x1067, -1 }, /* F11 */ + + { 0x68, -1, -1, -1 }, +// { 0x69, 0x800d, 0x1069, -1 }, /* F13 */ +// OG remap F13 to reset + { 0x69, 0x800c, 0x1069, -1 }, /* F13 */ + { 0x6a, -1, -1, -1 }, + { 0x6b, 0x800e, 0x106b, -1 }, /* F14 */ + { 0x6c, -1, -1, -1 }, + { 0x6d, 0x800a, 0x106d, -1 }, /* F10 */ + { 0x6e, 0x4000, 0x4000, -1 }, /* windows key alias to option */ + { 0x6f, 0x800c, 0x106f, -1 }, /* F12 */ + + { 0x70, -1, -1, -1 }, + { 0x71, 0x800f, 0x1071, -1 }, /* F15 */ + { 0x72, 0x1072, 0x1072, -1 }, /* Help, insert */ + { 0x73, 0x1073, 0x1073, -1 }, /* Home */ + { 0x74, 0x1074, 0x1074, -1 }, /* Page up */ + { 0x75, 0x1075, 0x1075, -1 }, /* keypad delete */ + { 0x76, 0x8004, 0x1076, -1 }, /* F4 */ + { 0x77, 0x1077, 0x1077, -1 }, /* keypad end */ + + { 0x78, 0x8002, 0x1078, -1 }, /* F2 */ + { 0x79, 0x1079, 0x1079, -1 }, /* keypad page down */ + { 0x7a, 0x8001, 0x107a, -1 }, /* F1 */ + { 0x7b, 0x08, 0x08, -1 }, /* left */ /* remapped to 0x3b */ + { 0x7c, 0x15, 0x15, -1 }, /* right */ /* remapped to 0x3c */ + { 0x7d, 0x0a, 0x0a, -1 }, /* down */ /* remapped to 0x3d */ + { 0x7e, 0x0b, 0x0b, -1 }, /* up arrow */ /* remapped to 0x3e */ + { 0x7f, -1, -1, -1 } /* Reset */ +}; + +//extern int g_num_lines_prev_superhires640; +//extern int g_num_lines_prev_superhires; +//extern int g_fast_disk_emul; + +extern int g_swap_paddles; +extern int g_invert_paddles; +extern int g_joystick_type; +//extern int g_a2vid_palette; +extern int g_config_control_panel; +extern word32 g_cfg_vbl_count; + + + +void +adb_init() +{ + int keycode; + int i; + + if(g_adb.g_adb_init) { + halt_printf("g_adb.g_adb_init = %d!\n", g_adb.g_adb_init); + } + g_adb.g_adb_init = 1; + + for(i = 0; i < 128; i++) { + keycode = a2_key_to_ascii[i][0]; + if(keycode != i) { + printf("ADB keycode lost/skipped: i=%x: keycode=%x\n", + i, keycode); + my_exit(1); + } + } + + g_adb.g_c025_val = 0; + + for(i = 0; i < 4; i++) { + g_adb.g_virtual_key_up[i] = -1; + } + + for(i = 0; i < 10; i++) { + g_adb.g_keypad_key_is_down[i] = 0; + } + + adb_reset(); +} + +// OG Added adb_shut() +void adb_shut() +{ + g_adb.g_adb_init = 0; +} + +void +adb_reset() +{ + + g_adb.g_c027_val = 0; + + g_adb.g_key_down = 0; + + g_adb.g_kbd_dev_addr = 2; + g_adb.g_mouse_dev_addr = 3; + + g_adb.g_kbd_ctl_addr = 2; + g_adb.g_mouse_ctl_addr = 3; + + adb_clear_data_int(); + adb_clear_mouse_int(); + adb_clear_kbd_srq(); + + g_adb.g_adb_data_pending = 0; + g_adb.g_adb_interrupt_byte = 0; + g_adb.g_adb_state = ADB_IDLE; + g_adb.g_adb_mouse_coord = 0; + g_adb.g_adb_mouse_valid_data = 0; + + g_adb.g_kbd_reg0_pos = 0; + g_adb.g_kbd_reg3_16bit = 0x602; + + g_adb.g_last_c027_read = 0; +} + + +#define LEN_ADB_LOG 16 +STRUCT(Adb_log) { + word32 addr; + int val; + int state; +}; + +Adb_log g_adb_log[LEN_ADB_LOG]; +int g_adb_log_pos = 0; + +void +adb_log(word32 addr, int val) +{ + int pos; + + pos = g_adb_log_pos; + g_adb_log[pos].addr = addr; + g_adb_log[pos].val = val; + g_adb_log[pos].state = g_adb.g_adb_state; + pos++; + if(pos >= LEN_ADB_LOG) { + pos = 0; + } + g_adb_log_pos = pos; +} + +void +show_adb_log(void) +{ + int pos; + int i; + + pos = g_adb_log_pos; + printf("ADB log pos: %d\n", pos); + for(i = 0; i < LEN_ADB_LOG; i++) { + pos--; + if(pos < 0) { + pos = LEN_ADB_LOG - 1; + } + printf("%d:%d: addr:%04x = %02x, st:%d\n", i, pos, + g_adb_log[pos].addr, g_adb_log[pos].val, + g_adb_log[pos].state); + } + printf("kbd: dev: %x, ctl: %x; mouse: dev: %x, ctl: %x\n", + g_adb.g_kbd_dev_addr, g_adb.g_kbd_ctl_addr, + g_adb.g_mouse_dev_addr, g_adb.g_mouse_ctl_addr); + printf("g_adb.g_adb_state: %d, g_adb.g_adb_interrupt_byte: %02x\n", + g_adb.g_adb_state, g_adb.g_adb_interrupt_byte); +} + +void +adb_error(void) +{ + halt_printf("Adb Error\n"); + + show_adb_log(); +} + + + +void +adb_add_kbd_srq() +{ + if(g_adb.g_kbd_reg3_16bit & 0x200) { + /* generate SRQ */ + g_adb.g_adb_interrupt_byte |= 0x08; + add_irq(IRQ_PENDING_ADB_KBD_SRQ); + } else { + printf("Got keycode but no kbd SRQ!\n"); + } +} + +void +adb_clear_kbd_srq() +{ + remove_irq(IRQ_PENDING_ADB_KBD_SRQ); + + /* kbd SRQ's are the only ones to handle now, so just clean it out */ + g_adb.g_adb_interrupt_byte &= (~(0x08)); +} + +void +adb_add_data_int() +{ + if(g_adb.g_c027_val & ADB_C027_DATA_INT) { + add_irq(IRQ_PENDING_ADB_DATA); + } +} + +void +adb_add_mouse_int() +{ + if(g_adb.g_c027_val & ADB_C027_MOUSE_INT) { + add_irq(IRQ_PENDING_ADB_MOUSE); + } +} + +void +adb_clear_data_int() +{ + remove_irq(IRQ_PENDING_ADB_DATA); +} + +void +adb_clear_mouse_int() +{ + remove_irq(IRQ_PENDING_ADB_MOUSE); +} + + +void +adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2) +{ + word32 val; + int shift_amount; + int i; + + // OG > 12 (instead of >=) + if((num_bytes > 12) || (num_bytes >= MAX_ADB_DATA_PEND)) { + halt_printf("adb_send_bytes: %d is too many!\n", num_bytes); + } + + g_adb.g_adb_state = ADB_SENDING_DATA; + g_adb.g_adb_data_pending = num_bytes; + adb_add_data_int(); + + for(i = 0; i < num_bytes; i++) { + if(i < 4) { + val = val0; + } else if(i < 8) { + val = val1; + } else { + val = val2; + } + + shift_amount = 8*(3 - i&3); // OG on ARM processor, shifting with a negative value does not work as expected : added &3 + g_adb.g_adb_data[i] = (val >> shift_amount) & 0xff; + adb_printf("adb_send_bytes[%d] = %02x\n", i, g_adb.g_adb_data[i]); + } +} + + +void +adb_send_1byte(word32 val) +{ + + if(g_adb.g_adb_data_pending != 0) { + halt_printf("g_adb.g_adb_data_pending: %d\n", g_adb.g_adb_data_pending); + } + + adb_send_bytes(1, val << 24, 0, 0); +} + + + +void +adb_response_packet(int num_bytes, word32 val) +{ + + if(g_adb.g_adb_data_pending != 0) { + halt_printf("adb_response_packet, but pending: %d\n", + g_adb.g_adb_data_pending); + } + + g_adb.g_adb_state = ADB_IDLE; + g_adb.g_adb_data_pending = num_bytes; + g_adb.g_adb_data[0] = val & 0xff; + g_adb.g_adb_data[1] = (val >> 8) & 0xff; + g_adb.g_adb_data[2] = (val >> 16) & 0xff; + g_adb.g_adb_data[3] = (val >> 24) & 0xff; + if(num_bytes) { + g_adb.g_adb_interrupt_byte |= 0x80 + num_bytes - 1; + } else { + g_adb.g_adb_interrupt_byte |= 0x80; + } + + adb_printf("adb_response packet: %d: %08x\n", + num_bytes, val); + + adb_add_data_int(); +} + + +void +adb_kbd_reg0_data(int a2code, int is_up) +{ + if(g_adb.g_kbd_reg0_pos >= MAX_ADB_KBD_REG3) { + /* too many keys, toss */ + halt_printf("Had to toss key: %02x, %d\n", a2code, is_up); + return; + } + + g_adb.g_kbd_reg0_data[g_adb.g_kbd_reg0_pos] = a2code + (is_up << 7); + + adb_printf("g_adb.g_kbd_reg0_data[%d] = %02x\n", g_adb.g_kbd_reg0_pos, + g_adb.g_kbd_reg0_data[g_adb.g_kbd_reg0_pos]); + + g_adb.g_kbd_reg0_pos++; + + adb_add_kbd_srq(); +} + +void +adb_kbd_talk_reg0() +{ + word32 val0, val1; + word32 reg; + int num_bytes; + int num; + int i; + + num = 0; + val0 = g_adb.g_kbd_reg0_data[0]; + val1 = g_adb.g_kbd_reg0_data[1]; + + num_bytes = 0; + if(g_adb.g_kbd_reg0_pos > 0) { + num_bytes = 2; + num = 1; + if((val0 & 0x7f) == 0x7f) { + /* reset */ + val1 = val0; + } else if(g_adb.g_kbd_reg0_pos > 1) { + num = 2; + if((val1 & 0x7f) == 0x7f) { + /* If first byte some other key, don't */ + /* put RESET next! */ + num = 1; + val1 = 0xff; + } + } else { + val1 = 0xff; + } + } + + if(num) { + for(i = num; i < g_adb.g_kbd_reg0_pos; i++) { + g_adb.g_kbd_reg0_data[i-1] = g_adb.g_kbd_reg0_data[i]; + } + g_adb.g_kbd_reg0_pos -= num; + } + + reg = (val0 << 8) + val1; + + adb_printf("adb_kbd_talk0: %04x\n", reg); + + adb_response_packet(num_bytes, reg); + if(g_adb.g_kbd_reg0_pos == 0) { + adb_clear_kbd_srq(); + } +} + +void +adb_set_config(word32 val0, word32 val1, word32 val2) +{ + int new_mouse; + int new_kbd; + int tmp1; + + new_mouse = val0 >> 4; + new_kbd = val0 & 0xf; + if(new_mouse != g_adb.g_mouse_ctl_addr) { + printf("ADB config: mouse from %x to %x!\n", + g_adb.g_mouse_ctl_addr, new_mouse); + adb_error(); + g_adb.g_mouse_ctl_addr = new_mouse; + } + if(new_kbd != g_adb.g_kbd_ctl_addr) { + printf("ADB config: kbd from %x to %x!\n", + g_adb.g_kbd_ctl_addr, new_kbd); + adb_error(); + g_adb.g_kbd_ctl_addr = new_kbd; + } + +#ifdef VIRTUALAPPLE +#pragma message("to replace with bram adb_repeat_dealy") +#else + tmp1 = val2 >> 4; + if(tmp1 == 4) { + g_adb.g_adb_repeat_delay = 0; + } else if(tmp1 < 4) { + g_adb.g_adb_repeat_delay = (tmp1 + 1) * 15; + } else { + halt_printf("Bad ADB repeat delay: %02x\n", tmp1); + } +#endif + + tmp1 = val2 & 0xf; + if(g_sim65816.g_rom_version >= 3) { + tmp1 = 9 - tmp1; + } +#ifndef VIRTUALAPPLE + switch(tmp1) { + case 0: + g_adb.g_adb_repeat_rate = 1; + break; + case 1: + g_adb.g_adb_repeat_rate = 2; + break; + case 2: + g_adb.g_adb_repeat_rate = 3; + break; + case 3: + g_adb.g_adb_repeat_rate = 3; + break; + case 4: + g_adb.g_adb_repeat_rate = 4; + break; + case 5: + g_adb.g_adb_repeat_rate = 5; + break; + case 6: + g_adb.g_adb_repeat_rate = 7; + break; + case 7: + g_adb.g_adb_repeat_rate = 15; + break; + case 8: + /* I don't know what this should be, ROM 03 uses it */ + g_adb.g_adb_repeat_rate = 30; + break; + case 9: + /* I don't know what this should be, ROM 03 uses it */ + g_adb.g_adb_repeat_rate = 60; + break; + default: + halt_printf("Bad repeat rate: %02x\n", tmp1); + } +#endif + +} + +void +adb_set_new_mode(word32 val) +{ + if(val & 0x03) { + printf("Disabling keyboard/mouse:%02x!\n", val); + } + + if(val & 0xa2) { + halt_printf("ADB set mode: %02x!\n", val); + adb_error(); + } + + g_adb.g_adb_mode = val; +} + + +int +adb_read_c026() +{ + word32 ret; + int i; + + ret = 0; + switch(g_adb.g_adb_state) { + case ADB_IDLE: + ret = g_adb.g_adb_interrupt_byte; + g_adb.g_adb_interrupt_byte = 0; + if(g_moremem.g_irq_pending & IRQ_PENDING_ADB_KBD_SRQ) { + g_adb.g_adb_interrupt_byte |= 0x08; + } + if(g_adb.g_adb_data_pending == 0) { + if(ret & 0x80) { + /*halt_*/printf("read_c026: ret:%02x, pend:%d\n", + ret, g_adb.g_adb_data_pending); + } + adb_clear_data_int(); + } + if(g_adb.g_adb_data_pending) { + if(g_adb.g_adb_state != ADB_IN_CMD) { + g_adb.g_adb_state = ADB_SENDING_DATA; + } + } + break; + case ADB_IN_CMD: + ret = 0; + break; + case ADB_SENDING_DATA: + ret = g_adb.g_adb_data[0]; + for(i = 1; i < g_adb.g_adb_data_pending; i++) { + g_adb.g_adb_data[i-1] = g_adb.g_adb_data[i]; + } + g_adb.g_adb_data_pending--; + if(g_adb.g_adb_data_pending <= 0) { + g_adb.g_adb_data_pending = 0; + g_adb.g_adb_state = ADB_IDLE; + adb_clear_data_int(); + } + break; + default: + halt_printf("Bad ADB state: %d!\n", g_adb.g_adb_state); + adb_clear_data_int(); + break; + } + + adb_printf("Reading c026. Returning %02x, st: %02x, pend: %d\n", + ret, g_adb.g_adb_state, g_adb.g_adb_data_pending); + + adb_log(0xc026, ret); + return (ret & 0xff); +} + + +void +adb_write_c026(int val) +{ + word32 tmp; + int dev; + + adb_printf("Writing c026 with %02x\n", val); + adb_log(0x1c026, val); + + + switch(g_adb.g_adb_state) { + case ADB_IDLE: + g_adb.g_adb_cmd = val; + g_adb.g_adb_cmd_so_far = 0; + g_adb.g_adb_cmd_len = 0; + + dev = val & 0xf; + switch(val) { + case 0x01: /* Abort */ + adb_printf("Performing adb abort\n"); + /* adb_abort() */ + break; + case 0x03: /* Flush keyboard buffer */ + adb_printf("Flushing adb keyboard buffer\n"); + /* Do nothing */ + break; + case 0x04: /* Set modes */ + adb_printf("ADB set modes\n"); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 1; + break; + case 0x05: /* Clear modes */ + adb_printf("ADB clear modes\n"); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 1; + break; + case 0x06: /* Set config */ + adb_printf("ADB set config\n"); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 3; + break; + case 0x07: /* Sync */ + adb_printf("Performing sync cmd!\n"); + g_adb.g_adb_state = ADB_IN_CMD; + if(g_sim65816.g_rom_version == 1) { + g_adb.g_adb_cmd_len = 4; + } else { + g_adb.g_adb_cmd_len = 8; + } + break; + case 0x08: /* Write mem */ + adb_printf("Starting write_mem cmd\n"); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 2; + break; + case 0x09: /* Read mem */ + adb_printf("Performing read_mem cmd!\n"); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 2; + break; + case 0x0a: /* Read modes byte */ + printf("Performing read_modes cmd!\n"); + /* set_halt(1); */ + adb_send_1byte(g_adb.g_adb_mode); + break; + case 0x0b: /* Read config bytes */ + printf("Performing read_configs cmd!\n"); + tmp = (g_adb.g_mouse_ctl_addr << 20) + + (g_adb.g_kbd_ctl_addr << 16) + + (g_adb.g_adb_char_set << 12) + + (g_adb.g_adb_layout_lang << 8) + + (g_adb.g_adb_repeat_info << 0); + tmp = (0x82U << 24) + tmp; + adb_send_bytes(4, tmp, 0, 0); + break; + case 0x0d: /* Get Version */ + adb_printf("Performing get_version cmd!\n"); + val = 0; + if(g_sim65816.g_rom_version == 1) { + /* ROM 01 = revision 5 */ + val = 5; + } else { + /* ROM 03 checks for rev >= 6 */ + val = 6; + } + adb_send_1byte(val); + break; + + /* + Patch borrowed from 03 + + OG Patch ADB Read for Keyboard & Language support + Just read the value for the micro controler once, and fill counter + series + (instead of reading the value for every time) + + @100 EQU * + LDY #$0000 ;Index to batteryram buffer + LDA #$0A ;Keyboard layout counts +@101 STA |LAYOUTS,Y ;Store to buffer + TYA ;Prepare for next store + CMP |LAYOUTS ;check for end + INY ;Index to next + BCC @101 ;loop till end + + */ + + case 0x0e: /* Read avail char sets */ + adb_printf("Performing read avail char sets cmd!\n"); + // OG : Invert byte => should be taken care by endianness? + // OG : All the indexes must also be sent + + adb_send_bytes(10, // 2 for the index, + 8 for the serie + 0x00080001, + 0x02030405, + 0x06070000); + /* + adb_send_bytes(2, // just 2 bytes + 0x08000000, // number of ch sets=0x8 + 0, 0); + */ + // set_halt(1); + break; + case 0x0f: /* Read avail kbd layouts */ + adb_printf("Performing read avail kbd layouts cmd!\n"); + // OG : Invert byte => should be taken care by endianness? + // OG : All the indexes must also be sent + adb_send_bytes(12, // 2 for the index, + 10 for the serie + 0x000A0001, + 0x02030405, + 0x06070809); + /* + adb_send_bytes(0x2, // number of kbd layouts=0xa + 0x0a000000, 0, 0); + */ + // set_halt(1); + break; + case 0x10: /* Reset */ + printf("ADB reset, cmd 0x10\n"); + do_reset(); + break; + case 0x11: /* Send ADB keycodes */ + adb_printf("Sending ADB keycodes\n"); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 1; + break; + case 0x12: /* ADB cmd 12: ROM 03 only! */ + if(g_sim65816.g_rom_version >= 3) { + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 2; + } else { + printf("ADB cmd 12, but not ROM 3!\n"); + adb_error(); + } + break; + case 0x13: /* ADB cmd 13: ROM 03 only! */ + if(g_sim65816.g_rom_version >= 3) { + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 2; + } else { + printf("ADB cmd 13, but not ROM 3!\n"); + adb_error(); + } + break; + case 0x73: /* Disable SRQ device 3: mouse */ + adb_printf("Disabling Mouse SRQ's (device 3)\n"); + /* HACK HACK...should deal with SRQs on mouse */ + break; + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + /* Listen dev x reg 3 */ + adb_printf("Sending data to dev %x reg 3\n", dev); + g_adb.g_adb_state = ADB_IN_CMD; + g_adb.g_adb_cmd_len = 2; + break; + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + /* Talk dev x reg 0 */ + adb_printf("Performing talk dev %x reg 0\n", dev); + if(dev == g_adb.g_kbd_dev_addr) { + adb_kbd_talk_reg0(); + } else { + printf("Unknown talk dev %x reg 0!\n", dev); + /* send no data, on SRQ, system polls devs */ + /* so we don't want to send anything */ + adb_error(); + } + break; + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + /* Talk dev x reg 3 */ + adb_printf("Performing talk dev %x reg 3\n", dev); + if(dev == g_adb.g_kbd_dev_addr) { + adb_response_packet(2, g_adb.g_kbd_reg3_16bit); + } else { + printf("Performing talk dev %x reg 3!!\n", dev); + adb_error(); + } + break; + default: + /* The Gog's says ACS Demo 2 has a bug and writes to */ + /* c026 */ + // OG + if (val==0x84) + printf("ACS Demo2 (3: Colum& Music scroll) : discarding unknown controller command\n"); + else + halt_printf("ADB ucontroller cmd %02x unknown!\n", val); + + break; + } + break; + case ADB_IN_CMD: + adb_printf("Setting byte %d of cmd %02x to %02x\n", + g_adb.g_adb_cmd_so_far, g_adb.g_adb_cmd, val); + + g_adb.g_adb_cmd_data[g_adb.g_adb_cmd_so_far] = val; + g_adb.g_adb_cmd_so_far++; + if(g_adb.g_adb_cmd_so_far >= g_adb.g_adb_cmd_len) { + adb_printf("Finished cmd %02x\n", g_adb.g_adb_cmd); + do_adb_cmd(); + } + + break; + default: + printf("adb_state: %02x is unknown! Setting it to ADB_IDLE\n", + g_adb.g_adb_state); + g_adb.g_adb_state = ADB_IDLE; + adb_error(); + g_adb.halt_on_all_c027 = 1; + break; + } + return; +} + +void +do_adb_cmd() +{ + int dev; + int new_kbd; + int addr; + int val; + + dev = g_adb.g_adb_cmd & 0xf; + + g_adb.g_adb_state = ADB_IDLE; + + switch(g_adb.g_adb_cmd) { + case 0x04: /* Set modes */ + adb_printf("Performing ADB set mode: OR'ing in %02x\n", + g_adb.g_adb_cmd_data[0]); + + val = g_adb.g_adb_cmd_data[0] | g_adb.g_adb_mode; + adb_set_new_mode(val); + + break; + case 0x05: /* clear modes */ + adb_printf("Performing ADB clear mode: AND'ing in ~%02x\n", + g_adb.g_adb_cmd_data[0]); + + val = g_adb.g_adb_cmd_data[0]; + val = g_adb.g_adb_mode & (~val); + adb_set_new_mode(val); + break; + case 0x06: /* Set config */ + adb_printf("Set ADB config to %02x %02x %02x\n", + g_adb.g_adb_cmd_data[0], g_adb.g_adb_cmd_data[1],g_adb.g_adb_cmd_data[2]); + + adb_set_config(g_adb.g_adb_cmd_data[0], g_adb.g_adb_cmd_data[1], + g_adb.g_adb_cmd_data[2]); + + break; + case 0x07: /* SYNC */ + adb_printf("Performing ADB SYNC\n"); + adb_printf("data: %02x %02x %02x %02x\n", + g_adb.g_adb_cmd_data[0], g_adb.g_adb_cmd_data[1], g_adb.g_adb_cmd_data[2], + g_adb.g_adb_cmd_data[3]); + + adb_set_new_mode(g_adb.g_adb_cmd_data[0]); + adb_set_config(g_adb.g_adb_cmd_data[1], g_adb.g_adb_cmd_data[2], + g_adb.g_adb_cmd_data[3]); + + if(g_sim65816.g_rom_version >= 3) { + adb_printf(" and cmd12:%02x %02x cmd13:%02x %02x\n", + g_adb.g_adb_cmd_data[4], g_adb.g_adb_cmd_data[5], + g_adb.g_adb_cmd_data[6], g_adb.g_adb_cmd_data[7]); + } + break; + case 0x08: /* Write mem */ + addr = g_adb.g_adb_cmd_data[0]; + val = g_adb.g_adb_cmd_data[1]; + write_adb_ram(addr, val); + break; + case 0x09: /* Read mem */ + addr = (g_adb.g_adb_cmd_data[1] << 8) + g_adb.g_adb_cmd_data[0]; + adb_printf("Performing mem read to addr %04x\n", addr); + adb_send_1byte(read_adb_ram(addr)); + break; + case 0x11: /* Send ADB keycodes */ + val = g_adb.g_adb_cmd_data[0]; + adb_printf("Performing send ADB keycodes: %02x\n", val); + adb_virtual_key_update(val & 0x7f, val >> 7); + break; + case 0x12: /* ADB cmd12 */ + adb_printf("Performing ADB cmd 12\n"); + adb_printf("data: %02x %02x\n", g_adb.g_adb_cmd_data[0], + g_adb.g_adb_cmd_data[1]); + break; + case 0x13: /* ADB cmd13 */ + adb_printf("Performing ADB cmd 13\n"); + adb_printf("data: %02x %02x\n", g_adb.g_adb_cmd_data[0], + g_adb.g_adb_cmd_data[1]); + break; + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + /* Listen dev x reg 3 */ + if(dev == g_adb.g_kbd_dev_addr) { + if(g_adb.g_adb_cmd_data[1] == 0xfe) { + /* change keyboard addr? */ + new_kbd = g_adb.g_adb_cmd_data[0] & 0xf; + if(new_kbd != dev) { + printf("Moving kbd to dev %x!\n", + new_kbd); + adb_error(); + } + g_adb.g_kbd_dev_addr = new_kbd; + } else if(g_adb.g_adb_cmd_data[1] != 1) { + /* see what new device handler id is */ + printf("KBD listen to dev %x reg 3: 1:%02x\n", + dev, g_adb.g_adb_cmd_data[1]); + adb_error(); + } + if(g_adb.g_adb_cmd_data[0] != (word32)g_adb.g_kbd_dev_addr) { + /* see if app is trying to change addr */ + printf("KBD listen to dev %x reg 3: 0:%02x!\n", + dev, g_adb.g_adb_cmd_data[0]); + adb_error(); + } + g_adb.g_kbd_reg3_16bit = ((g_adb.g_adb_cmd_data[0] & 0xf) << 12) + + (g_adb.g_kbd_reg3_16bit & 0x0fff); + } else if(dev == g_adb.g_mouse_dev_addr) { + if(g_adb.g_adb_cmd_data[0] != (word32)dev) { + /* see if app is trying to change mouse addr */ + printf("MOUS listen to dev %x reg3: 0:%02x!\n", + dev, g_adb.g_adb_cmd_data[0]); + adb_error(); + } + if(g_adb.g_adb_cmd_data[1] != 1 && g_adb.g_adb_cmd_data[1] != 2) { + /* see what new device handler id is */ + printf("MOUS listen to dev %x reg 3: 1:%02x\n", + dev, g_adb.g_adb_cmd_data[1]); + adb_error(); + } + } else { + printf("Listen cmd to dev %x reg3????\n", dev); + printf("data0: %02x, data1: %02x ????\n", + g_adb.g_adb_cmd_data[0], g_adb.g_adb_cmd_data[1]); + adb_error(); + } + break; + default: + printf("Doing adb_cmd %02x: UNKNOWN!\n", g_adb.g_adb_cmd); + break; + } +} + + +int +adb_read_c027() +{ + word32 ret; + + // OG to monitor if mouse is being used! + g_adb.g_last_c027_read = g_sim65816.g_vbl_count; + + if(g_adb.halt_on_all_c027) { + halt_printf("halting on all c027 reads!\n"); + } + + if(g_adb.g_c027_val & (~ADB_C027_NEG_MASK)) { + halt_printf("read_c027: g_adb.g_c027_val: %02x\n", g_adb.g_c027_val); + } + + ret = (g_adb.g_c027_val & ADB_C027_NEG_MASK); + + if(g_adb.g_adb_mouse_valid_data) { + ret |= ADB_C027_MOUSE_DATA; + } + + if(g_adb.g_adb_interrupt_byte != 0) { + ret |= ADB_C027_DATA_VALID; + } else if(g_adb.g_adb_data_pending > 0) { + if((g_adb.g_adb_state != ADB_IN_CMD)) { + ret |= ADB_C027_DATA_VALID; + } + } + + if(g_adb.g_adb_mouse_coord) { + ret |= ADB_C027_MOUSE_COORD; + } + +#if 0 + adb_printf("Read c027: %02x, int_byte: %02x, d_pend: %d\n", + ret, g_adb.g_adb_interrupt_byte, g_adb.g_adb_data_pending); +#endif + +#if 0 + adb_log(0xc027, ret); +#endif + return ret; +} + +void +adb_write_c027(int val) +{ + word32 old_val; + word32 new_int; + word32 old_int; + + adb_printf("Writing c027 with %02x\n", val); + adb_log(0x1c027, val); + + + old_val = g_adb.g_c027_val; + + g_adb.g_c027_val = (val & ADB_C027_NEG_MASK); + new_int = g_adb.g_c027_val & ADB_C027_MOUSE_INT; + old_int = old_val & ADB_C027_MOUSE_INT; + if(!new_int && old_int) { + adb_clear_mouse_int(); + } + + new_int = g_adb.g_c027_val & ADB_C027_DATA_INT; + old_int = old_val & ADB_C027_DATA_INT; + if(!new_int && old_int) { + /* ints were on, now off */ + adb_clear_data_int(); + } + + if(g_adb.g_c027_val & ADB_C027_KBD_INT) { + halt_printf("Can't support kbd interrupts!\n"); + } + + return; +} + +int +read_adb_ram(word32 addr) +{ + int val; + + adb_printf("Reading adb ram addr: %02x\n", addr); + + if(addr >= 0x100) { + if(addr >= 0x1000 && addr < 0x2000) { + /* ROM self-test checksum */ + if(addr == 0x1400) { + val = 0x72; + } else if(addr == 0x1401) { + val = 0xf7; + } else { + val = 0; + } + } else { + printf("adb ram addr out of range: %04x!\n", addr); + val = 0; + } + } else { + val = g_adb.adb_memory[addr]; + if((addr == 0xb) && (g_sim65816.g_rom_version == 1)) { + // read special key state byte for Out of This World + val = (g_adb.g_c025_val >> 1) & 0x43; + val |= (g_adb.g_c025_val << 2) & 0x4; + val |= (g_adb.g_c025_val >> 2) & 0x10; + } + if((addr == 0xc) && (g_sim65816.g_rom_version >= 3)) { + // read special key state byte for Out of This World + val = g_adb.g_c025_val & 0xc7; + printf("val is %02x\n", val); + } + } + + adb_printf("adb_ram returning %02x\n", val); + return val; +} + +void +write_adb_ram(word32 addr, int val) +{ + + adb_printf("Writing adb_ram addr: %02x: %02x\n", addr, val); + + if(addr >= 0x100) { + printf("write adb_ram addr: %02x: %02x!\n", addr, val); + adb_error(); + } else { + g_adb.adb_memory[addr] = val; + } +} + +int +adb_get_keypad_xy(int get_y) +{ + int x, y; + int key; + int num_keys; + int i, j; + + key = 1; + num_keys = 0; + x = 0; + y = 0; + for(i = 0; i < 3; i++) { + for(j = 0; j < 3; j++) { + if(g_adb.g_keypad_key_is_down[key]) { + num_keys++; + x = x + (j - 1)*32768; + y = y + (1 - i)*32768; + } + key++; + } + } + if(num_keys == 0) { + num_keys = 1; + } + + adb_printf("get_xy=%d, num_keys: %d, x:%d, y:%d\n", get_y, + num_keys, x, y); + + if(get_y) { + return y / num_keys; + } else { + return x / num_keys; + } +} + +int is_mouse_used_by_host() +{ + return ! (g_adb.g_last_c027_read < ( g_sim65816.g_vbl_count - 60 ) ); +} + +int +update_mouse(int x, int y, int button_states, int buttons_valid) +{ + double dcycs; + int button1_changed; + int mouse_moved; + int unhide; + int pos; + int i; + +// printf("Mouse at %d, %d (%d) (%d)\n", x, y, button_states,buttons_valid); + + dcycs = g_sim65816.g_cur_dcycs; + + g_adb.g_mouse_raw_x = x; + g_adb.g_mouse_raw_y = y; + + // OG ignore clamping in warp mode + unhide = 0; + if (g_adb.g_warp_pointer!=WARP_POINTER) + { + if(x < 0) { + x = 0; + unhide = 1; + } + if(x >= 640) { + x = 639; + unhide = 1; + } + if(y < 0) { + y = 0; + unhide = 1; + } + if(y >= 400) { + y = 399; + unhide = 1; + } + } + + g_adb.g_unhide_pointer = unhide && (g_adb.g_warp_pointer!=WARP_POINTER); + + if(g_adb.g_warp_pointer!=WARP_POINTER) + { + if(g_adb.g_hide_pointer && g_adb.g_unhide_pointer) { + /* cursor has left a2 window, show it */ + + //OG - Disabling + g_adb.g_hide_pointer = 0; + x_hide_pointer(0); + } + if((g_video.g_num_lines_prev_superhires == 200) && + (g_video.g_num_lines_prev_superhires640 == 0) && + ((g_slow_memory_ptr[0x19d00] & 0x80) == 0)) { + // In 320-mode superhires, cut mouse range in half + x = x >> 1; + } + y = y >> 1; + } + + mouse_compress_fifo(dcycs); + +#if 0 + printf("Update Mouse called with buttons:%d (state:%d) x,y:%d,%d, fifo:%d,%d, " + " a2: %d,%d\n", buttons_valid,button_states, x, y, + g_adb.g_mouse_fifo[0].x, g_mouse_fifo[0].y, + g_adb.g_mouse_a2_x, g_adb.g_mouse_a2_y); +#endif + + if((buttons_valid == -1) &&(g_adb.g_warp_pointer==WARP_POINTER)) { + /* Warping the pointer causes it to jump here...this is not */ + /* real motion, just update info and get out */ + g_adb.g_mouse_a2_x += (x - g_adb.g_mouse_fifo[0].x); + g_adb.g_mouse_a2_y += (y - g_adb.g_mouse_fifo[0].y); + g_adb.g_mouse_fifo[0].x = x; + g_adb.g_mouse_fifo[0].y = y; + return 0; + } + +#if 0 + printf("...real move, warp: %d, %d, new x: %d, %d, a2:%d,%d\n", + g_adb.g_mouse_warp_x, g_adb.g_mouse_warp_y, g_adb.g_mouse_fifo[0].x, + g_adb.g_mouse_fifo[0].y, g_adb.g_mouse_a2_x, g_adb.g_mouse_a2_y); +#endif + + mouse_moved = (g_adb.g_mouse_fifo[0].x != x) || (g_adb.g_mouse_fifo[0].y != y); + + g_adb.g_mouse_a2_x += g_adb.g_mouse_warp_x; + g_adb.g_mouse_a2_y += g_adb.g_mouse_warp_y; + g_adb.g_mouse_fifo[0].x = x; + g_adb.g_mouse_fifo[0].y = y; + g_adb.g_mouse_fifo[0].dcycs = dcycs; + g_adb.g_mouse_warp_x = 0; + g_adb.g_mouse_warp_y = 0; + + button1_changed = (buttons_valid & 1) && ((button_states & 1) != (g_adb.g_mouse_fifo[0].buttons & 1)); + +#if defined(ACTIVEGS) && !defined(MAC) + if (g_adb.g_warp_pointer == WARP_TOUCHSCREEN) + { + + if (buttons_valid==-2) + { + button1_changed = 1; + buttons_valid = 1; + button_states = 1; + printf("*"); + } + else + { + if (!button1_changed) + { + if (!(button_states & 1)) + { + // mouse move => ignored + return 1 ; + } + } + else + { + // chgt de button + // simule un mouse move avant le click + if (button_states & 1) + { + for(int i=0;i<10;i++) + add_event_delay(); + add_event_mouse(g_adb.g_mouse_raw_x,g_adb.g_mouse_raw_y,1,-2); + button1_changed = 0; + buttons_valid = 1; + button_states = 0; + + } + } + } + + // printf("%d %d (%d)\n",x,y,button_states); + } +#endif + + if((button_states & 4) && !(g_adb.g_mouse_fifo[0].buttons & 4) && + (buttons_valid & 4)) { + /* right button pressed */ + adb_increment_speed(); + } + if((button_states & 2) && !(g_adb.g_mouse_fifo[0].buttons & 2) && + (buttons_valid & 2)) { + /* middle button pressed */ + halt2_printf("Middle button pressed\n"); + } + + pos = g_adb.g_mouse_fifo_pos; + if((pos < (ADB_MOUSE_FIFO - 2)) && button1_changed) { + /* copy delta to overflow, set overflow */ + /* overflow ensures the mouse button state is precise at */ + /* button up/down times. Using a mouse event list where */ + /* deltas accumulate until a button change would work, too */ + for(i = pos; i >= 0; i--) { + g_adb.g_mouse_fifo[i + 1] = g_adb.g_mouse_fifo[i]; /* copy struct*/ + } + g_adb.g_mouse_fifo_pos = pos + 1; + } + + + g_adb.g_mouse_fifo[0].buttons = (button_states & buttons_valid) | + (g_adb.g_mouse_fifo[0].buttons & ~buttons_valid); + + + if(mouse_moved || button1_changed) { + if( (g_adb.g_mouse_ctl_addr == g_adb.g_mouse_dev_addr) && + ((g_adb.g_adb_mode & 0x2) == 0)) { + g_adb.g_adb_mouse_valid_data = 1; + adb_add_mouse_int(); + } + } + + return mouse_moved; +} + +// OG Only decrement fifo once per check_input + +void should_decrement_fifo() +{ + if (g_adb.g_need_to_decrement_fifo) + { + g_adb.g_need_to_decrement_fifo = 0; + if (g_adb.g_mouse_fifo_pos) + g_adb.g_mouse_fifo_pos--; + } +} + + +int +mouse_read_c024(double dcycs) +{ + word32 ret; + word32 tool_start; + int em_active; + int target_x, target_y; + int delta_x, delta_y; + int a2_x, a2_y; + int mouse_button; + int clamped; + int pos; + + if(((g_adb.g_adb_mode & 0x2) != 0) || (g_adb.g_mouse_dev_addr != g_adb.g_mouse_ctl_addr)){ + /* mouse is off, return 0, or mouse is not autopoll */ + g_adb.g_adb_mouse_valid_data = 0; + adb_clear_mouse_int(); + return 0; + } + + mouse_compress_fifo(dcycs); + + pos = g_adb.g_mouse_fifo_pos; + target_x = g_adb.g_mouse_fifo[pos].x; + target_y = g_adb.g_mouse_fifo[pos].y; + mouse_button = (g_adb.g_mouse_fifo[pos].buttons & 1); + delta_x = target_x - g_adb.g_mouse_a2_x; + delta_y = target_y - g_adb.g_mouse_a2_y; + + clamped = 0; + if(delta_x > 0x3f) { + delta_x = 0x3f; + clamped = 1; + } else if(delta_x < -0x3f) { + delta_x = -0x3f; + clamped = 1; + } + if(delta_y > 0x3f) { + delta_y = 0x3f; + clamped = 1; + } else if(delta_y < -0x3f) { + delta_y = -0x3f; + clamped = 1; + } + + if(pos > 0) { + /* peek into next entry's button info if we are not clamped */ + /* and we're returning the y-coord */ + if(!clamped && g_adb.g_adb_mouse_coord) { + mouse_button = g_adb.g_mouse_fifo[pos - 1].buttons & 1; + } + } + + if(g_adb.g_adb_mouse_coord) { + /* y coord */ + delta_x = 0; /* clear unneeded x delta */ + } else { + delta_y = 0; /* clear unneeded y delta */ + } + + + adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n", + g_slow_memory_ptr[0x100e9], g_slow_memory_ptr[0x100ea], + g_slow_memory_ptr[0x100eb], g_slow_memory_ptr[0x100ec]); + adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n", + g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192], + g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]); + + /* Update event manager internal state */ + tool_start = (g_slow_memory_ptr[0x103ca] << 16) + + (g_slow_memory_ptr[0x103c9] << 8) + + g_slow_memory_ptr[0x103c8]; + + em_active = 0; + if((tool_start >= 0x20000) && (tool_start < (g_sim65816.g_mem_size_total - 28)) ) { + /* seems to be valid ptr to addr of mem space for tools */ + /* see if event manager appears to be active */ + em_active = g_memory_ptr[tool_start + 6*4] + (g_memory_ptr[tool_start + 6*4 + 1] << 8); + if(g_adb.g_warp_pointer==WARP_POINTER) + { + em_active = 0; + } + } + + a2_x = g_adb.g_mouse_a2_x; + a2_y = g_adb.g_mouse_a2_y; + + if(em_active) { + if((!g_adb.g_hide_pointer) && (g_video.g_num_lines_prev_superhires == 200) && + !g_adb.g_unhide_pointer) { + /* if super-hires and forcing tracking, then hide */ + g_adb.g_hide_pointer = 1; + x_hide_pointer(1); + + } + if(g_adb.g_adb_mouse_coord == 0) { + /* update x coord values */ + g_slow_memory_ptr[0x47c] = a2_x & 0xff; + g_slow_memory_ptr[0x57c] = a2_x >> 8; + g_memory_ptr[0x47c] = a2_x & 0xff; + g_memory_ptr[0x57c] = a2_x >> 8; + + g_slow_memory_ptr[0x10190] = a2_x & 0xff; + g_slow_memory_ptr[0x10192] = a2_x >> 8; + } else { + g_slow_memory_ptr[0x4fc] = a2_y & 0xff; + g_slow_memory_ptr[0x5fc] = a2_y >> 8; + g_memory_ptr[0x4fc] = a2_y & 0xff; + g_memory_ptr[0x5fc] = a2_y >> 8; + + g_slow_memory_ptr[0x10191] = a2_y & 0xff; + g_slow_memory_ptr[0x10193] = a2_y >> 8; + } + } else { + if(g_adb.g_hide_pointer && (g_adb.g_warp_pointer!=WARP_POINTER)) { + g_adb.g_hide_pointer = 0; + x_hide_pointer(0); + } + } + + ret = ((!mouse_button) << 7) + ((delta_x | delta_y) & 0x7f); + if(g_adb.g_adb_mouse_coord) { + g_adb.g_mouse_a2_button = mouse_button; /* y coord has button*/ + } else { + ret |= 0x80; /* mouse button not down on x coord rd */ + } + + a2_x += delta_x; + a2_y += delta_y; + g_adb.g_mouse_a2_x = a2_x; + g_adb.g_mouse_a2_y = a2_y; + if(g_adb.g_mouse_fifo_pos) { + if((target_x == a2_x) && (target_y == a2_y) && (g_adb.g_mouse_a2_button == mouse_button)) + { + // OG + // Only decrement FIFO once per check_inputs + g_adb.g_need_to_decrement_fifo = 1; + //g_adb.g_mouse_fifo_pos--; + // printf("new fifo:%d",g_adb.g_mouse_fifo_pos); + + } + } + + + adb_printf("Read c024, mouse is_y:%d, %02x, vbl:%08x, dcyc:%f, em:%d\n",g_adb.g_adb_mouse_coord, ret, g_sim65816.g_vbl_count, dcycs, em_active); + adb_printf("...mouse targ_x:%d,%d delta_x,y:%d,%d fifo:%d, a2:%d,%d\n", + target_x, target_y, delta_x, delta_y, g_adb.g_mouse_fifo_pos, + a2_x, a2_y); + adb_printf(" post a2_x:%02x,%02x,%02x,%02x\n", + g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192], + g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]); + + if((g_adb.g_mouse_fifo_pos == 0) && (g_adb.g_mouse_fifo[0].x == a2_x) && + (g_adb.g_mouse_fifo[0].y == a2_y) && + ((g_adb.g_mouse_fifo[0].buttons & 1) == g_adb.g_mouse_a2_button)) { + g_adb.g_adb_mouse_valid_data = 0; + adb_clear_mouse_int(); + } + + g_adb.g_adb_mouse_coord = !g_adb.g_adb_mouse_coord; + return ret; +} + +void +mouse_compress_fifo(double dcycs) +{ + int pos; + + /* The mouse fifo exists so that fast button changes don't get lost */ + /* if the emulator lags behind the mouse events */ + /* But the FIFO means really old mouse events are saved if */ + /* the emulated code isn't looking at the mouse registers */ + /* This routine compresses all mouse events > 0.5 seconds old */ + + for(pos = g_adb.g_mouse_fifo_pos; pos >= 1; pos--) { + if(g_adb.g_mouse_fifo[pos].dcycs < (dcycs - 500*1000.0)) { + /* Remove this entry */ + adb_printf("Old mouse FIFO pos %d removed\n", pos); + g_adb.g_mouse_fifo_pos = pos - 1; + continue; + } + /* Else, stop searching the FIFO */ + break; + } +} + +void +adb_key_event(int a2code, int is_up) +{ + word32 special; + word32 vbl_count; + int key; + int hard_key; + int pos; + int tmp_ascii; + int ascii; + +// printf("adb_key_event, key:%02x, is up:%d g_adb.g_key_down: %02x\n",a2code,is_up, g_key_down); + + if(is_up) { + adb_printf("adb_key_event, key:%02x, is up, g_adb.g_key_down: %02x\n", + a2code, g_adb.g_key_down); + } + + if(a2code < 0 || a2code > 0x7f) { + halt_printf("add_key_event: a2code: %04x!\n", a2code); + return; + } + + if(!is_up && a2code == 0x35) { + /* ESC pressed, see if ctrl & cmd key down */ + + if(CTRL_DOWN && CMD_DOWN) { + /* Desk mgr int */ + printf("Desk mgr int!\n"); + + g_adb.g_adb_interrupt_byte |= 0x20; + adb_add_data_int(); + } + } + + /* convert key to ascii, if possible */ + hard_key = 0; + if(a2_key_to_ascii[a2code][1] & 0xef00) { + /* special key */ + } else { + /* we have ascii */ + hard_key = 1; + } + + pos = 1; + ascii = a2_key_to_ascii[a2code][1]; + if(CAPS_LOCK_DOWN && (ascii >= 'a' && ascii <= 'z')) { + pos = 2; + if(SHIFT_DOWN && (g_adb.g_adb_mode & 0x40)) { + /* xor shift mode--capslock and shift == lowercase */ + pos = 1; + } + } else if(SHIFT_DOWN) { + pos = 2; + } + + ascii = a2_key_to_ascii[a2code][pos]; + if(CTRL_DOWN) { + tmp_ascii = a2_key_to_ascii[a2code][3]; + if(tmp_ascii >= 0) { + ascii = tmp_ascii; + } + } + key = (ascii & 0x7f) + 0x80; + + special = (ascii >> 8) & 0xff; + if(ascii < 0) { + printf("ascii1: %d, a2code: %02x, pos: %d\n", ascii,a2code,pos); + ascii = 0; + special = 0; + } + + + if(!is_up) { + if(hard_key) { + g_adb.g_kbd_buf[g_adb.g_kbd_chars_buffered] = key; + + // printf("adding %X at pos %d\n",key,g_adb.g_kbd_chars_buffered); + g_adb.g_kbd_chars_buffered++; + if(g_adb.g_kbd_chars_buffered >= MAX_KBD_BUF) { + g_adb.g_kbd_chars_buffered = MAX_KBD_BUF - 1; + } + g_adb.g_key_down = 1; + g_adb.g_a2code_down = a2code; + + /* first key down, set up autorepeat */ + vbl_count = g_sim65816.g_vbl_count; + if(g_config_control_panel) { + vbl_count = g_cfg_vbl_count; + } + g_adb.g_adb_repeat_vbl = vbl_count + g_adb.g_adb_repeat_delay; + if(g_adb.g_adb_repeat_delay == 0) { + g_adb.g_key_down = 0; + } + g_adb.g_hard_key_down = 1; + } + + g_adb.g_c025_val = g_adb.g_c025_val | special; + adb_printf("new c025_or: %02x\n", g_adb.g_c025_val); + } else { + if(hard_key && (a2code == g_adb.g_a2code_down)) { + g_adb.g_hard_key_down = 0; + /* Turn off repeat */ + g_adb.g_key_down = 0; + } + + g_adb.g_c025_val = g_adb.g_c025_val & (~ special); + adb_printf("new c025_and: %02x\n", g_adb.g_c025_val); + } + + if(g_adb.g_key_down) { + g_adb.g_c025_val = g_adb.g_c025_val & (~0x20); + } else { + /* If no hard key down, set update mod latch */ + g_adb.g_c025_val = g_adb.g_c025_val | 0x20; + } + +} + +word32 +adb_read_c000() +{ + word32 vbl_count; + + if( ((g_adb.g_kbd_buf[0] & 0x80) == 0) && (g_adb.g_key_down == 0)) { + /* nothing happening, just get out */ + return g_adb.g_kbd_buf[0]; + } + if(g_adb.g_kbd_buf[0] & 0x80) { + /* got one */ + if((g_adb.g_kbd_read_no_update++ > 5) && (g_adb.g_kbd_chars_buffered > 1)) { + /* read 5 times, keys pending, let's move it along */ + printf("Read %02x %d times, tossing\n", g_adb.g_kbd_buf[0], + g_adb.g_kbd_read_no_update); + adb_access_c010(); + } + } else { + vbl_count = g_sim65816.g_vbl_count; + if(g_config_control_panel) { + vbl_count = g_cfg_vbl_count; + } + if(g_adb.g_key_down && vbl_count >= g_adb.g_adb_repeat_vbl) { + /* repeat the g_adb.g_key_down */ + g_adb.g_c025_val |= 0x8; + adb_key_event(g_adb.g_a2code_down, 0); + g_adb.g_adb_repeat_vbl = vbl_count + g_adb.g_adb_repeat_rate; + } + } + + return g_adb.g_kbd_buf[0]; +} + +word32 +adb_access_c010() +{ + int tmp; + int i; + + g_adb.g_kbd_read_no_update = 0; + + tmp = g_adb.g_kbd_buf[0] & 0x7f; + g_adb.g_kbd_buf[0] = tmp; + + tmp = tmp | (g_adb.g_hard_key_down << 7); + if(g_adb.g_kbd_chars_buffered) { + // printf("c010 removing %X ",g_adb.g_kbd_buf[0]); + for(i = 1; i < g_adb.g_kbd_chars_buffered; i++) { + g_adb.g_kbd_buf[i - 1] = g_adb.g_kbd_buf[i]; + } + g_adb.g_kbd_chars_buffered--; + // printf(" @%d\n",g_adb.g_kbd_chars_buffered); + } + + g_adb.g_c025_val = g_adb.g_c025_val & (~ (0x08)); + + return tmp; +} + +word32 +adb_read_c025() +{ + + return g_adb.g_c025_val; +} + +int +adb_is_cmd_key_down() +{ + return CMD_DOWN; +} + +int +adb_is_option_key_down() +{ + return OPTION_DOWN; +} + +void +adb_increment_speed() +{ + // TODO + /* + const char *str; + + g_sim65816.g_limit_speed++; + if(g_sim65816.g_limit_speed > 3) { + g_sim65816.g_limit_speed = 0; + } + + str = ""; + switch(g_sim65816.g_limit_speed) { + case 0: + str = "...as fast as possible!"; + break; + case 1: + str = "...1.024MHz!"; + break; + case 2: + str = "...2.8MHz!"; + break; + case 3: + str = "...8.0MHz!"; + break; + } + printf("Toggling g_sim65816.g_limit_speed to %d%s\n", g_sim65816.g_limit_speed, str); + */ +} + +void +adb_physical_key_update(int a2code, int is_up) +{ + int autopoll; + int special; + int ascii_and_type; + int ascii; + + /* this routine called by xdriver to pass raw codes--handle */ + /* ucontroller and ADB bus protocol issues here */ + /* if autopoll on, pass it on through to c025,c000 regs */ + /* else only put it in kbd reg 3, and pull SRQ if needed */ + +// printf("adb_phys_key_update: %02x, %d (vbl %d)\n", a2code, is_up,g_sim65816.g_vbl_count); + + adb_printf("Handle a2code: %02x, is_up: %d\n", a2code, is_up); + + if(a2code < 0 || a2code > 0x7f) { + halt_printf("a2code: %04x!\n", a2code); + return; + } + + /* + // Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards) + if(a2code >= 0x7b && a2code <= 0x7e) { + a2code = a2code - 0x40; + } + */ + + /* Now check for special keys (function keys, etc) */ + ascii_and_type = a2_key_to_ascii[a2code][1]; + special = 0; + if((ascii_and_type & 0xf000) == 0x8000) { + /* special function key */ + special = ascii_and_type & 0xff; + switch(special) { + case 0x01: /* F1 - remap to cmd */ + a2code = 0x37; + special = 0; + break; + case 0x02: /* F2 - remap to option */ + a2code = 0x3a; + special = 0; + break; + case 0x03: /* F3 - remap to escape for OS/2 */ + a2code = 0x35; + special = 0; + break; + case 0x0c: /* F12 - remap to reset */ + a2code = 0x7f; + special = 0; + break; + default: + break; + } + } + + /* Only process reset requests here */ + if(is_up == 0 && a2code == 0x7f && CTRL_DOWN) { + /* Reset pressed! */ + printf("Reset pressed since CTRL_DOWN: %d\n", CTRL_DOWN); + do_reset(); + return; + } + + if(special && !is_up) + { + int handled=0; + if (g_driver.x_handle_fkey) + handled = g_driver.x_handle_fkey(special); + + if (!handled) + switch(special) { + + case 0x05: /* F5 */ + if (r_sim65816.get_state()==RUNNING) + r_sim65816.pause(); + else + r_sim65816.resume(); + break; + +#ifndef ACTIVEGS + case 0x04: /* F4 - Emulator config panel */ + cfg_toggle_config_panel(); + break; + case 0x06: /* F6 - emulator speed */ + if(SHIFT_DOWN) { + halt2_printf("Shift-F6 pressed\n"); + } else { + adb_increment_speed(); + } + break; + case 0x07: /* F7 - fast disk emul */ + g_iwm.g_fast_disk_emul = !g_iwm.g_fast_disk_emul; + printf("g_fast_disk_emul is now %d\n", + g_iwm.g_fast_disk_emul); + break; +#endif + case 0x08: /* F8 - warp pointer */ + switch(g_adb.g_warp_pointer) + { + case WARP_NONE: + g_adb.g_warp_pointer=WARP_POINTER; + g_adb.g_hide_pointer = 1; + extern void x_recenter_hw_mouse(); + x_recenter_hw_mouse(); + printf("switching mouse to WARP_POINTER!\n"); + break; + /* + case WARP_POINTER: + // skip warp on non touch platform + if (g_driver.environment == ENV_TOUCH) + { + g_adb.g_warp_pointer=WARP_TOUCHSCREEN; + g_adb.g_hide_pointer = 0; + printf("switching mouse to WARP_TOUCHSCREEN!\n"); + break; + } + */ + default: // WARP_TOUCHSCREEN + g_adb.g_warp_pointer=WARP_NONE; + g_adb.g_hide_pointer = 0; + printf("switching mouse to WARP_NONE!\n"); + break; + } + x_hide_pointer(g_adb.g_hide_pointer); + + /* + g_adb.g_warp_pointer = !g_adb.g_warp_pointer; + if(g_adb.g_hide_pointer != g_adb.g_warp_pointer) { + g_adb.g_hide_pointer = g_adb.g_warp_pointer; + x_hide_pointer(g_adb.g_hide_pointer); + } + */ + + break; +#ifndef ACTIVEGS + case 0x09: /* F9 - swap paddles */ + if(SHIFT_DOWN) { + g_swap_paddles = !g_swap_paddles; + printf("Swap paddles is now: %d\n", + g_swap_paddles); + } else { + g_invert_paddles = !g_invert_paddles; + printf("Invert paddles is now: %d\n", + g_invert_paddles); + } + break; + case 0x0a: /* F10 - change a2vid paletter */ + change_a2vid_palette((g_video.g_a2vid_palette + 1) & 0xf); + break; + case 0x0b: /* F11 - full screen */ + g_adb.fullscreen = !g_adb.fullscreen; + x_full_screen(g_adb.fullscreen); + break; +#endif + } + + return; + } + /* Handle Keypad Joystick here partly...if keypad key pressed */ + /* while in Keypad Joystick mode, do not pass it on as a key press */ + if((ascii_and_type & 0xff00) == 0x1000) { + /* Keep track of keypad number keys being up or down even */ + /* if joystick mode isn't keypad. This avoid funny cases */ + /* if joystick mode is changed while a key is pressed */ + ascii = ascii_and_type & 0xff; + if(ascii > 0x30 && ascii <= 0x39) { + g_adb.g_keypad_key_is_down[ascii - 0x30] = !is_up; + } + if(g_joystick_type == JOYSTICK_TYPE_KEYPAD) { + /* If Joystick type is keypad, then do not let these */ + /* keypress pass on further, except for cmd/opt */ + if(ascii == 0x30) { + /* remap '0' to cmd */ + a2code = 0x37; + } else if(ascii == 0x2e || ascii == 0x2c) { + /* remap '.' and ',' to option */ + a2code = 0x3a; + } else { + /* Just ignore it in this mode */ + return; + } + } + } + + autopoll = 1; + if(g_adb.g_adb_mode & 1) { + /* autopoll is explicitly off */ + autopoll = 0; + } + if(g_adb.g_kbd_dev_addr != g_adb.g_kbd_ctl_addr) { + /* autopoll is off because ucontroller doesn't know kbd moved */ + autopoll = 0; + } + if(g_config_control_panel) { + /* always do autopoll */ + autopoll = 1; + } + + + if(is_up) { + if(!autopoll) { + /* no auto keys, generate SRQ! */ + adb_kbd_reg0_data(a2code, is_up); + } else { + adb_virtual_key_update(a2code, is_up); + } + } else { + if(!autopoll) { + /* no auto keys, generate SRQ! */ + adb_kbd_reg0_data(a2code, is_up); + } else { + /* was up, now down */ + adb_virtual_key_update(a2code, is_up); + } + } +} + +void +adb_virtual_key_update(int a2code, int is_up) +{ + int i; + int bitpos; + word32 mask; + + adb_printf("Virtual handle a2code: %02x, is_up: %d\n", a2code, is_up); + + if(a2code < 0 || a2code > 0x7f) { + halt_printf("a2code: %04x!\n", a2code); + return; + } + + i = (a2code >> 5) & 3; + bitpos = a2code & 0x1f; + mask = (1 << bitpos); + + if(is_up) { + if(g_adb.g_virtual_key_up[i] & mask) { + /* already up, do nothing */ + } else { + g_adb.g_virtual_key_up[i] |= mask; + adb_key_event(a2code, is_up); + } + } else { + if(g_adb.g_virtual_key_up[i] & mask) { + g_adb.g_virtual_key_up[i] &= (~mask); + adb_key_event(a2code, is_up); + } + } +} + +void +adb_all_keys_up() +{ + word32 mask; + int i, j; + + for(i = 0; i < 4; i++) { + for(j = 0; j < 32; j++) { + mask = 1 << j; + if((g_adb.g_virtual_key_up[i] & mask) == 0) { + /* create key-up event */ + adb_physical_key_update(i*32 + j, 1); + } + } + } +} + +void +adb_kbd_repeat_off() +{ + g_adb.g_key_down = 0; +} diff --git a/kegs/Src/adb.h b/kegs/Src/adb.h new file mode 100644 index 0000000..c2930f3 --- /dev/null +++ b/kegs/Src/adb.h @@ -0,0 +1,186 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +const char rcsid_adb_h[] = "@(#)$KmKId: adb.h,v 1.11 2004-10-13 23:30:33-04 kentd Exp $"; + +#include "defc.h" + +enum { + ADB_IDLE = 0, + ADB_IN_CMD, + ADB_SENDING_DATA, +}; + +#define ADB_C027_MOUSE_DATA 0x80 +#define ADB_C027_MOUSE_INT 0x40 +#define ADB_C027_DATA_VALID 0x20 +#define ADB_C027_DATA_INT 0x10 +#define ADB_C027_KBD_VALID 0x08 +#define ADB_C027_KBD_INT 0x04 +#define ADB_C027_MOUSE_COORD 0x02 +#define ADB_C027_CMD_FULL 0x01 + +#define ADB_C027_NEG_MASK ( ~ ( \ + ADB_C027_MOUSE_DATA | ADB_C027_DATA_VALID | \ + ADB_C027_KBD_VALID | ADB_C027_MOUSE_COORD | \ + ADB_C027_CMD_FULL)) + + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + + +STRUCT(Mouse_fifo) +{ + _ALIGNED(8) double dcycs; + int x; + int y; + int buttons; +} +XCODE_PRAGMA_PACK +; + +enum warpmode +{ + WARP_NONE = 0, + WARP_POINTER, + WARP_TOUCHSCREEN +}; + + +class s_adb : public serialized +{ +public: + int fullscreen ; + int halt_on_all_c027; + word32 g_adb_repeat_delay; + word32 g_adb_repeat_rate; + word32 g_adb_repeat_info; + word32 g_adb_char_set ; + word32 g_adb_layout_lang; + + word32 g_adb_interrupt_byte; + int g_adb_state; + + word32 g_adb_cmd ; + int g_adb_cmd_len; + int g_adb_cmd_so_far ; + word32 g_adb_cmd_data[16]; + +#define MAX_ADB_DATA_PEND 16 + + word32 g_adb_data[MAX_ADB_DATA_PEND]; + int g_adb_data_pending; + + word32 g_c027_val; + word32 g_c025_val; + + byte adb_memory[256]; + + word32 g_adb_mode ; /* mode set via set_modes, clear_modes */ + + enum warpmode g_warp_pointer; + int g_hide_pointer; + int g_unhide_pointer; + + int g_mouse_a2_x ; + int g_mouse_a2_y ; + int g_mouse_a2_button ; + int g_mouse_fifo_pos ; + int g_mouse_raw_x ; + int g_mouse_raw_y; + +#define ADB_MOUSE_FIFO 8 + + Mouse_fifo g_mouse_fifo[ADB_MOUSE_FIFO] ; + + int g_mouse_warp_x ; + int g_mouse_warp_y ; + + int g_adb_mouse_valid_data ; + int g_adb_mouse_coord ; + +#define MAX_KBD_BUF 8 + + int g_key_down ; + int g_hard_key_down ; + int g_a2code_down ; + int g_kbd_read_no_update ; + int g_kbd_chars_buffered ; + int g_kbd_buf[MAX_KBD_BUF]; + + word32 g_adb_repeat_vbl ; + + int g_kbd_dev_addr; /* ADB physical kbd addr */ + int g_mouse_dev_addr ; /* ADB physical mouse addr */ + + int g_kbd_ctl_addr; /* ADB microcontroller's kbd addr */ + int g_mouse_ctl_addr; /* ADB ucontroller's mouse addr*/ + /* above are ucontroller's VIEW of where mouse/kbd */ + /* are...if they are moved, mouse/keyboard funcs */ + /* should stop (c025, c000, c024, etc). */ + + word32 g_virtual_key_up[4]; /* bitmask of all possible 128 a2codes */ + /* indicates which keys are up=1 by bit */ + + int g_keypad_key_is_down[10] ;/* List from 0-9 of which keypad */ + /* keys are currently pressed */ + +#define MAX_ADB_KBD_REG3 16 + + int g_kbd_reg0_pos; + int g_kbd_reg0_data[MAX_ADB_KBD_REG3]; + int g_kbd_reg3_16bit ; /* also set in adb_reset()! */ + + + int g_adb_init; + word32 g_last_c027_read; // OG to monitor if mouse is being used! + + int g_simulate_space; // OG Mouse button can simulate space key + int g_need_to_decrement_fifo; + + s_adb() + { + init(); + } + void init() + { + INIT_SERIALIZED(); + + g_adb_repeat_delay = 45; + g_adb_repeat_rate = 3; + g_adb_repeat_info = 0x23; + g_adb_state = ADB_IDLE; + + g_adb_cmd = (word32)-1; + g_kbd_dev_addr = 2; /* ADB physical kbd addr */ + g_mouse_dev_addr = 3; /* ADB physical mouse addr */ + + g_kbd_ctl_addr = 2; /* ADB microcontroller's kbd addr */ + g_mouse_ctl_addr = 3; /* ADB ucontroller's mouse addr*/ + /* above are ucontroller's VIEW of where mouse/kbd */ + /* are...if they are moved, mouse/keyboard funcs */ + /* should stop (c025, c000, c024, etc). */ + + g_kbd_reg3_16bit = 0x602; /* also set in adb_reset()! */ + g_simulate_space = 1; // OG Mouse button can simulate space key + g_warp_pointer = WARP_NONE; + } + + DEFAULT_SERIALIZE_IN_OUT ; + +} +XCODE_PRAGMA_PACK +; + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +extern s_adb g_adb; diff --git a/kegs/Src/async_event.cpp b/kegs/Src/async_event.cpp new file mode 100644 index 0000000..3961f23 --- /dev/null +++ b/kegs/Src/async_event.cpp @@ -0,0 +1,208 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include +#include "defc.h" +#include "adb.h" +#include "async_event.h" +#include "sim65816.h" +#include "savestate.h" + +extern void x_check_system_input_events(); +extern void x_update_modifiers(word32); + + +s_async_event g_async_event; + +void reset_async_event() +{ + + g_async_event.max_event_key = 0; + g_async_event.cur_event_key = 0; + g_async_event.unstacking_events = 0; + + +} + +void add_event_delay() +{ + g_async_event.mac_events[g_async_event.max_event_key].type = DELAY; + g_async_event.max_event_key = (g_async_event.max_event_key+1)%MAX_MAC_EVENT_KEYS; + +} + +void add_event_key(int _key,int _isup) +{ + +// printf("ADDING %X (%d)\n",_key,_isup); +#ifdef MAC + // Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards) + if(_key >= 0x7b && _key <= 0x7e) { + _key = _key - 0x40; + } +#endif + +#ifdef ACTIVEGS + if (r_sim65816.get_state()==IN_PAUSE) + { + g_savestate.handleKey(_key,_isup); + return ; + } +#endif + + if (r_sim65816.get_state()!=RUNNING) return ; + + + g_async_event.mac_events[g_async_event.max_event_key].key = _key; + g_async_event.mac_events[g_async_event.max_event_key].isup = _isup; + g_async_event.mac_events[g_async_event.max_event_key].type = KEY; + + g_async_event.max_event_key = (g_async_event.max_event_key+1)%MAX_MAC_EVENT_KEYS; +} + +/* +void x_add_event_key(int _key, int _up) +{ + add_event_key(_key,_up); +} + */ + + +extern int is_mouse_used_by_host(); + +void simulate_space_event() +{ + if (g_adb.g_simulate_space) + { + // regarde si la souris a été lu depuis 1s => simule un appui barre espace + if (!is_mouse_used_by_host()) //g_last_c027_read < ( g_vbl_count - 60 ) ) + { + printf("Simulate KEY (%X)\n",g_adb.g_simulate_space); + add_event_key(g_adb.g_simulate_space,0); + add_event_key(g_adb.g_simulate_space,1); + } + } +} + +void add_event_mouse(int _x,int _y, int _state, int _button) +{ + + if (r_sim65816.get_state()!=RUNNING) return ; + + g_async_event.mac_events[g_async_event.max_event_key].x = _x; + g_async_event.mac_events[g_async_event.max_event_key].y = _y; + g_async_event.mac_events[g_async_event.max_event_key].state = _state; + g_async_event.mac_events[g_async_event.max_event_key].button = _button; + g_async_event.mac_events[g_async_event.max_event_key].type = MOUSE; + g_async_event.max_event_key = (g_async_event.max_event_key+1)%MAX_MAC_EVENT_KEYS; +} + +void add_event_modifier(unsigned int _mod) +{ + /* + static int lastmod = 0; + if (_mod != lastmod) + printf("newmod:%x\n",_mod); + lastmod = _mod; + */ + if (r_sim65816.get_state()!=RUNNING) return ; + + g_async_event.mac_events[g_async_event.max_event_key].mod = _mod; + g_async_event.mac_events[g_async_event.max_event_key].type = MODIFIERS; + g_async_event.max_event_key = (g_async_event.max_event_key+1)%MAX_MAC_EVENT_KEYS; +} + + + +void check_input_events() +{ + + x_check_system_input_events(); + + g_async_event.unstacking_events = 1; +#define MAX_STACK 100 + int nbstack = 0; + int stacks[MAX_STACK]; + while(g_async_event.cur_event_key!=g_async_event.max_event_key) + { + int i = g_async_event.cur_event_key; + switch(g_async_event.mac_events[i].type) + { + case DELAY: + // skip event + g_async_event.cur_event_key = (g_async_event.cur_event_key+1)%MAX_MAC_EVENT_KEYS; + g_async_event.unstacking_events = 0; + return; + + case MODIFIERS: + x_update_modifiers( g_async_event.mac_events[i].mod); + break; + case KEY: + { + // regarde si on a déjà pushé l'évement dans cette frame + int k = g_async_event.mac_events[i].key; + int delayed=0; + for(int s = 0;s0) // -1 means warp pointer + { + int s = g_async_event.mac_events[i].state & mac_events[i].button; + int nblastvbl = g_vbl_count - g_input_last_vbl; + if (nblastvbl<0) + { + printf("alert !!!"); + } + if ( nblastvbl <= 1 && s!= g_last_button_state ) + { + printf("delaying mouse event %d,%d (%d) (%d)\n",g_async_event.mac_events[i].x,mac_events[i].y,s,nblastvbl); + g_async_event.unstacking_events = 0; + + return; + } + g_input_last_vbl = g_vbl_count ; + g_last_button_state = s; + } + */ + + update_mouse( g_async_event.mac_events[i].x , + g_async_event.mac_events[i].y , + g_async_event.mac_events[i].state , + g_async_event.mac_events[i].button) ; + break; + } + g_async_event.cur_event_key = (g_async_event.cur_event_key+1)%MAX_MAC_EVENT_KEYS; + } + + g_async_event.unstacking_events = 0; + +} + diff --git a/kegs/Src/async_event.h b/kegs/Src/async_event.h new file mode 100644 index 0000000..ab62926 --- /dev/null +++ b/kegs/Src/async_event.h @@ -0,0 +1,57 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +enum event_type +{ + KEY,MOUSE,MODIFIERS,DELAY +}; + +#define MAX_MAC_EVENT_KEYS 1024 +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +typedef struct +{ + enum event_type type; + int key, isup; + int x,y,state,button; + unsigned int mod; + +}struct_event XCODE_PRAGMA_PACK; + + +class s_async_event : public serialized +{ +public: + + int max_event_key ; + int cur_event_key ; + int unstacking_events ; + + struct_event mac_events[MAX_MAC_EVENT_KEYS] ; + + s_async_event() + { + memset(this,0,sizeof(*this)); + } + + DEFAULT_SERIALIZE_IN_OUT ; + +} XCODE_PRAGMA_PACK; + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +extern void add_event_key(int _key,int _isup); +extern void add_event_mouse(int _x,int _y, int _state, int _button); +extern void add_event_modifier(unsigned int _mod); +extern void add_event_delay(); + +extern s_async_event g_async_event; diff --git a/kegs/Src/clock.cpp b/kegs/Src/clock.cpp new file mode 100644 index 0000000..d4f989a --- /dev/null +++ b/kegs/Src/clock.cpp @@ -0,0 +1,383 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include +#ifdef _WIN32 +# include +# include +#else +# include +#endif + +#include "clock.h" +#include "moremem.h" +#include "sim65816.h" + +s_clock g_clock; + +extern int Verbose; +//extern word32 g_vbl_count; // OG change int to word32 +//extern int g_rom_version; +extern int g_config_kegs_update_needed; + + +double +get_dtime() +{ +#ifndef _WIN32 + struct timeval tp1; + double dsec; + double dusec; +#endif + + /* Routine used to return actual system time as a double */ + /* No routine cares about the absolute value, only deltas--maybe */ + /* take advantage of that in future to increase usec accuracy */ +double dtime; +#ifdef _WIN32 + LARGE_INTEGER counter; + LARGE_INTEGER frequency; + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&frequency); + dtime = (double)counter.QuadPart/(double)frequency.QuadPart; +// dtime = timeGetTime() / 1000.0; +#else + + +# ifdef SOLARIS + gettimeofday(&tp1, (void *)0); +# else + gettimeofday(&tp1, (struct timezone *)0); +# endif + + dsec = (double)tp1.tv_sec; + dusec = (double)tp1.tv_usec; + + dtime = dsec + (dusec / (1000.0 * 1000.0)); +#endif + + return dtime; +} + +int +micro_sleep(double dtime) +{ +#ifndef _WIN32 + struct timeval Timer; + int ret; +#endif + + if(dtime <= 0.0) { + return 0; + } + if(dtime >= 1.0) { + halt_printf("micro_sleep called with %f!!\n", dtime); + return -1; + } + +#if 0 + printf("usleep: %f\n", dtime); +#endif + +#ifdef _WIN32 + Sleep((DWORD)(dtime * 1000)); +#else + Timer.tv_sec = 0; + Timer.tv_usec = (dtime * 1000000.0); + if( (ret = select(0, 0, 0, 0, &Timer)) < 0) { + fprintf(stderr, "micro_sleep (select) ret: %d, errno: %d\n", + ret, errno); + return -1; + } +#endif + return 0; +} + +void +clk_bram_zero() +{ + int i, j; + + /* zero out all bram */ + for(i = 0; i < 2; i++) { + for(j = 0; j < 256; j++) { + g_clock.g_bram[i][j] = 0; + } + } + g_clock.g_bram_ptr = &(g_clock.g_bram[0][0]); +} + +void +clk_bram_set(int bram_num, int offset, int val) +{ + g_clock.g_bram[bram_num][offset] = val; +} + + +extern void x_clk_setup_bram_version(); + +void +clk_setup_bram_version() +{ + x_clk_setup_bram_version(); +} + +void +clk_write_bram(FILE *fconf) +{ + int i, j, k; + + for(i = 0; i < 2; i++) { + fprintf(fconf, "\n"); + for(j = 0; j < 256; j += 16) { + fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j); + for(k = 0; k < 16; k++) { + fprintf(fconf, " %02x", g_clock.g_bram[i][j+k]); + } + fprintf(fconf, "\n"); + } + } +} + +void +update_cur_time() +{ + + time_t cur_time; + unsigned int secs, secs2; + + +#ifdef UNDER_CE // OG Not supported on WIndows CE + /* + SYSTEMTIME stime; + FILETIME ftime; + GetLocalTime(&stime); + SystemTimeToFileTime(&stime,&ftime); + cur_time = ftime.dwLowDateTime; + */ + cur_time = time(0); + + secs=0; + secs2=0; + +#else + struct tm *tm_ptr; + cur_time = time(0); + + /* Figure out the timezone (effectively) by diffing two times. */ + /* this is probably not right for a few hours around daylight savings*/ + /* time transition */ + secs2 = (unsigned int)mktime(gmtime(&cur_time)); + tm_ptr = localtime(&cur_time); + secs = (unsigned int)mktime(tm_ptr); + +#ifdef DRIVER_OSX + /* Mac OS X's mktime function modifies the tm_ptr passed in for */ + /* the CDT timezone and breaks this algorithm. So on a Mac, we */ + /* will use the tm_ptr->gmtoff member to correct the time */ + secs = secs + tm_ptr->tm_gmtoff; +#else + secs = (unsigned int)cur_time - (secs2 - secs); + + if(tm_ptr->tm_isdst) { + /* adjust for daylight savings time */ + secs += 3600; + } +#endif +#endif + /* add in secs to make date based on Apple Jan 1, 1904 instead of */ + /* Unix's Jan 1, 1970 */ + /* So add in 66 years and 17 leap year days (1904 is a leap year) */ + secs += ((66*365) + 17) * (24*3600); + + g_clock.g_clk_cur_time = secs; + + clk_printf("Update g_clock.g_clk_cur_time to %08x\n", g_clock.g_clk_cur_time); + g_clock.g_clk_next_vbl_update = g_sim65816.g_vbl_count + 5; +} + +/* clock_update called by sim65816 every VBL */ +void +clock_update() +{ + /* Nothing to do */ +} + +void +clock_update_if_needed() +{ + int diff; + + diff = g_clock.g_clk_next_vbl_update - g_sim65816.g_vbl_count; + if(diff < 0 || diff > 60) { + /* Been a while, re-read the clock */ + update_cur_time(); + } +} + +void +clock_write_c034(word32 val) +{ + g_moremem.g_c034_val = val & 0x7f; + if((val & 0x80) != 0) { + if((val & 0x20) == 0) { + printf("c034 write not last = 1\n"); + /* set_halt(1); */ + } + do_clock_data(); + } +} + + +void +do_clock_data() +{ + word32 mask; + int read; + int op; + + clk_printf("In do_clock_data, g_clock.g_clk_mode: %02x\n", g_clock.g_clk_mode); + + read = g_moremem.g_c034_val & 0x40; + switch(g_clock.g_clk_mode) { + case CLK_IDLE: + g_clock.g_clk_read = (g_moremem.g_c033_data >> 7) & 1; + g_clock.g_clk_reg1 = (g_moremem.g_c033_data >> 2) & 3; + op = (g_moremem.g_c033_data >> 4) & 7; + if(!read) { + /* write */ + switch(op) { + case 0x0: /* Read/write seconds register */ + g_clock.g_clk_mode = CLK_TIME; + clock_update_if_needed(); + break; + case 0x3: /* internal registers */ + g_clock.g_clk_mode = CLK_INTERNAL; + if(g_clock.g_clk_reg1 & 0x2) { + /* extend BRAM read */ + g_clock.g_clk_mode = CLK_BRAM2; + g_clock.g_clk_reg1 = (g_moremem.g_c033_data & 7) << 5; + } + break; + case 0x2: /* read/write ram 0x10-0x13 */ + g_clock.g_clk_mode = CLK_BRAM1; + g_clock.g_clk_reg1 += 0x10; + break; + case 0x4: /* read/write ram 0x00-0x0f */ + case 0x5: case 0x6: case 0x7: + g_clock.g_clk_mode = CLK_BRAM1; + g_clock.g_clk_reg1 = (g_moremem.g_c033_data >> 2) & 0xf; + break; + default: + halt_printf("Bad c033_data in CLK_IDLE: %02x\n", + g_moremem.g_c033_data); + } + } else { + printf("clk read from IDLE mode!\n"); + /* set_halt(1); */ + g_clock.g_clk_mode = CLK_IDLE; + } + break; + case CLK_BRAM2: + if(!read) { + /* get more bits of bram addr */ + if((g_moremem.g_c033_data & 0x83) == 0x00) { + /* more address bits */ + g_clock.g_clk_reg1 |= ((g_moremem.g_c033_data >> 2) & 0x1f); + g_clock.g_clk_mode = CLK_BRAM1; + } else { + halt_printf("CLK_BRAM2: c033_data: %02x!\n", + g_moremem.g_c033_data); + g_clock.g_clk_mode = CLK_IDLE; + } + } else { + halt_printf("CLK_BRAM2: clock read!\n"); + g_clock.g_clk_mode = CLK_IDLE; + } + break; + case CLK_BRAM1: + /* access battery ram addr g_clock.g_clk_reg1 */ + if(read) { + if(g_clock.g_clk_read) { + /* Yup, read */ + g_moremem.g_c033_data = g_clock.g_bram_ptr[g_clock.g_clk_reg1]; + clk_printf("Reading BRAM loc %02x: %02x\n", + g_clock.g_clk_reg1, g_moremem.g_c033_data); + } else { + halt_printf("CLK_BRAM1: said wr, now read\n"); + } + } else { + if(g_clock.g_clk_read) { + halt_printf("CLK_BRAM1: said rd, now write\n"); + } else { + /* Yup, write */ + clk_printf("Writing BRAM loc %02x with %02x\n",g_clock.g_clk_reg1, g_moremem.g_c033_data); + g_clock.g_bram_ptr[g_clock.g_clk_reg1] = g_moremem.g_c033_data; + g_config_kegs_update_needed = 1; + } + } + g_clock.g_clk_mode = CLK_IDLE; + break; + case CLK_TIME: + if(read) { + if(g_clock.g_clk_read == 0) { + halt_printf("Reading time, but in set mode!\n"); + } + g_moremem.g_c033_data = (g_clock.g_clk_cur_time >> (g_clock.g_clk_reg1 * 8)) & + 0xff; + clk_printf("Returning time byte %d: %02x\n", + g_clock.g_clk_reg1, g_moremem.g_c033_data); + } else { + /* Write */ + if(g_clock.g_clk_read) { + halt_printf("Write time, but in read mode!\n"); + } + clk_printf("Writing TIME loc %d with %02x\n", + g_clock.g_clk_reg1, g_moremem.g_c033_data); + mask = 0xff << (8 * g_clock.g_clk_reg1); + + g_clock.g_clk_cur_time = (g_clock.g_clk_cur_time & (~mask)) | + ((g_moremem.g_c033_data & 0xff) << (8 * g_clock.g_clk_reg1)); + } + g_clock.g_clk_mode = CLK_IDLE; + break; + case CLK_INTERNAL: + if(read) { + printf("Attempting to read internal reg %02x!\n", + g_clock.g_clk_reg1); + } else { + switch(g_clock.g_clk_reg1) { + case 0x0: /* test register */ + if(g_moremem.g_c033_data & 0xc0) { + printf("Writing test reg: %02x!\n", + g_moremem.g_c033_data); + /* set_halt(1); */ + } + break; + case 0x1: /* write protect reg */ + clk_printf("Writing clk wr_protect: %02x\n", + g_moremem.g_c033_data); + if(g_moremem.g_c033_data & 0x80) { + printf("Stop, wr clk wr_prot: %02x\n", + g_moremem.g_c033_data); + /* set_halt(1); */ + } + break; + default: + halt_printf("Writing int reg: %02x with %02x\n", + g_clock.g_clk_reg1, g_moremem.g_c033_data); + } + } + g_clock.g_clk_mode = CLK_IDLE; + break; + default: + halt_printf("clk mode: %d unknown!\n", g_clock.g_clk_mode); + g_clock.g_clk_mode = CLK_IDLE; + break; + } +} + diff --git a/kegs/Src/clock.h b/kegs/Src/clock.h new file mode 100644 index 0000000..48e07a2 --- /dev/null +++ b/kegs/Src/clock.h @@ -0,0 +1,78 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#define CLK_IDLE 1 +#define CLK_TIME 2 +#define CLK_INTERNAL 3 +#define CLK_BRAM1 4 +#define CLK_BRAM2 5 + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +class s_clock : public serialized +{ +public: + int g_clk_mode; + int g_clk_read; + int g_clk_reg1 ; + + byte g_bram[2][256]; + byte *g_bram_ptr ; + + word32 g_clk_cur_time ; + int g_clk_next_vbl_update ; + + s_clock() + { + INIT_SERIALIZED(); + + g_clk_mode = CLK_IDLE; + g_clk_cur_time = 0xa0000000; + g_bram_ptr = &(g_bram[0][0]); + } + +#define SERIALIZE_BRAM g_bram_ptr = (byte*)( (g_bram_ptr == &g_bram[0][0])?1:3 ); +#define UNSERIALIZE_BRAM g_bram_ptr = ((intptr_t)g_bram_ptr ==1) ? &g_bram[0][0] : &g_bram[1][0] + + + void in(serialize* _s) + { + byte* ptr = (byte*)_s->data; + int ssize = *(int*)ptr; + if (ssize!= sizeof(*this)) + ALIGNMENT_ERROR("clock",ssize,sizeof(*this)); + + ptr += sizeof(ssize); + + memcpy(this,ptr,sizeof(*this)); + UNSERIALIZE_BRAM ; + } + + int out(serialize* _s, int _fastalloc) + { + int ssize = sizeof(*this); + int size = ssize + sizeof(ssize); + _s->size = size; + _s->fastalloc = _fastalloc; + _s->data = (void*)x_malloc(size,_fastalloc); + byte* ptr = (byte*) _s->data; + memcpy(ptr,&ssize,sizeof(ssize)); + ptr+=sizeof(ssize); + SERIALIZE_BRAM; + memcpy(ptr,this,sizeof(*this)); + UNSERIALIZE_BRAM; + return size; + } + +} XCODE_PRAGMA_PACK; +#ifdef _WIN32 +#pragma pack(pop) +#endif +extern s_clock g_clock; diff --git a/kegs/Src/compile_time.cpp b/kegs/Src/compile_time.cpp new file mode 100644 index 0000000..7a5e877 --- /dev/null +++ b/kegs/Src/compile_time.cpp @@ -0,0 +1,8 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +char g_compile_time[] = "Compiled: " __DATE__ " " __TIME__ ; + diff --git a/kegs/Src/compression.cpp b/kegs/Src/compression.cpp new file mode 100644 index 0000000..b01f0ce --- /dev/null +++ b/kegs/Src/compression.cpp @@ -0,0 +1,305 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "savestate.h" +#include "compression.h" +#include "../../Libraries/zlib123/zlib.h" + +int rleencode(serialize* _data); + +s_compression g_compression; + + +int serialize::expand() +{ + if (!rledata) + { + // printf("cannot expand : no compressed data\n"); + return 0; + } + + if (data) + { + // printf("alreay expanded!"); + return 0; + } + + Bytef* p = (Bytef*)x_malloc(size,fastalloc); + uLongf dsize = size; + ::uncompress(p,&dsize,(const Bytef*)rledata,rlesize); + + // TODO ERROR CHECKING + data = p; + + return 1; +} + + +int serialize::releaseuncompressed() +{ + if (!rledata) + { + // printf("cannot release uncompressed : no compressed data!\n"); + return 0; + } + x_free(data,size,fastalloc); + data = NULL; + return 1; +} + +int serialize::compress() +{ + if (rledata) + { + // printf("already compressed\n"); + return 0; + } + + byte* tmp = (byte*)x_malloc(size,fastalloc); +// rlesize = rleencode(this); + +// double t = get_dtime(); + uLongf destsize = size; + ::compress2 (tmp,&destsize,(const Bytef*)data,size,Z_BEST_SPEED); + rlesize = destsize; +// double delay = get_dtime() - t; +// printf("compressed %d%% in %fs\n",(int)( (float)destsize*100/(float)size ),delay/1000); + + rledata = x_realloc(tmp,rlesize,size); + + releaseuncompressed(); + return 1; +} + +int s_compression::add_job(serialize* _s) +{ + for(int i=0;icompress(); + } + } + } + return 0; +} + +s_compression::~s_compression() +{ + for(int j=0;jsize; + char* ptr = (char*)_data->data; + char currChar = *ptr++; + size--; + + int compressedsize = 0; + + /* read input until there's nothing left */ + while (size) + { + charBuf[count]=currChar; + count++; + + if (count >= MIN_RUN) + { + int i; + + /* check for run charBuf[count - 1] .. charBuf[count - MIN_RUN]*/ + for (i = 2; i <= MIN_RUN; i++) + { + if (currChar != charBuf[count - i]) + { + /* no run */ + i = 0; + break; + } + } + + if (i != 0) + { + /* we have a run write out buffer before run*/ + int nextChar; + + if (count > MIN_RUN) + { + /* block size - 1 followed by contents */ + *out++ = count - MIN_RUN - 1; + compressedsize++; + + memcpy(out,charBuf,count - MIN_RUN); + out+= count - MIN_RUN; + compressedsize += count - MIN_RUN; + + } + + + /* determine run length (MIN_RUN so far) */ + count = MIN_RUN; + + while (size) + { + nextChar = *ptr++; + size--; + if (nextChar == currChar) + { + count++; + if (MAX_RUN == count) + { + /* run is at max length */ + break; + } + } + else + break; + } + + *out++ = (int)(MIN_RUN - 1) - (int)(count); + compressedsize++; + + *out++ = currChar; + compressedsize++; + + if ((size) && (count != MAX_RUN)) + { + /* make run breaker start of next buffer */ + charBuf[0] = nextChar; + count = 1; + } + else + { + /* file or max run ends in a run */ + count = 0; + } + } + } + + if (MAX_READ == count) + { + int i; + + *out++ = MAX_COPY - 1; + compressedsize++; + + memcpy(out,charBuf,MAX_COPY); + compressedsize+=MAX_COPY; + out+=MAX_COPY; + + /* start a new buffer */ + count = MAX_READ - MAX_COPY; + + /* copy excess to front of buffer */ + for (i = 0; i < count; i++) + { + charBuf[i] = charBuf[MAX_COPY + i]; + } + } + + if (size) + { + currChar = *ptr++; + size--; + } + } + + /* write out last buffer */ + if (0 != count) + { + if (count <= MAX_COPY) + { + /* write out entire copy buffer */ + *out++= count -1; + compressedsize++; + + memcpy(out,charBuf,count); + out += count; + compressedsize+=count; + } + else + { + /* we read more than the maximum for a single copy buffer */ + + *out++ = MAX_COPY - 1; + compressedsize++; + + memcpy(out,charBuf,MAX_COPY); + out+=MAX_COPY; + compressedsize+=MAX_COPY; + + /* write out remainder */ + count -= MAX_COPY; + + *out++ = count -1; + compressedsize++; + + memcpy(out,&charBuf[MAX_COPY],count); + out+=count; + compressedsize+=count; + } + } + + printf("compressed from %d to %d\n",_data->size,compressedsize); + return compressedsize; +} + diff --git a/kegs/Src/compression.h b/kegs/Src/compression.h new file mode 100644 index 0000000..d067c8d --- /dev/null +++ b/kegs/Src/compression.h @@ -0,0 +1,36 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#define MAX_JOB 32 + +void* x_realloc(void* ptr,int _newsize, int _formersize); +extern void* x_malloc(int size, int fastalloc); +extern void* x_free(void* ptr,int size, int fastalloc); + +extern int cacheSize; + +class serialize; + +class s_compression +{ + + serialize* jobs[MAX_JOB]; + +public: + s_compression() + { + memset(this,0,sizeof(*this)); + } + ~s_compression(); + + int add_job(serialize* _job); + int remove_job(serialize* _job); + int process_jobs(int _nbjob); +}; + +extern s_compression g_compression; \ No newline at end of file diff --git a/kegs/Src/config.h b/kegs/Src/config.h new file mode 100644 index 0000000..60f495f --- /dev/null +++ b/kegs/Src/config.h @@ -0,0 +1,82 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_C +const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.9 2004-11-12 23:10:28-05 kentd Exp $"; +#endif + +#include "iwm.h" + +#define CONF_BUF_LEN 1024 +#define COPY_BUF_SIZE 4096 +#define CFG_PRINTF_BUFSIZE 2048 + +#define CFG_PATH_MAX 1024 + +#define CFG_NUM_SHOWENTS 16 + +#define CFGTYPE_MENU 1 +#define CFGTYPE_INT 2 +#define CFGTYPE_DISK 3 +#define CFGTYPE_FUNC 4 +#define CFGTYPE_FILE 5 +/* CFGTYPE limited to just 4 bits: 0-15 */ + +/* Cfg_menu, Cfg_dirent and Cfg_listhdr are defined in defc.h */ + +STRUCT(Cfg_defval) { + Cfg_menu *menuptr; + int intval; + char *strval; +}; + +/* config.c */ +void config_init_menus(Cfg_menu *menuptr); +void config_init(void); +void cfg_exit(void); +void cfg_toggle_config_panel(void); +void cfg_text_screen_dump(void); +void config_vbl_update(int doit_3_persec); +void config_parse_option(char *buf, int pos, int len, int line); +void config_parse_bram(char *buf, int pos, int len); +void config_load_roms(void); +void config_parse_config_kegs_file(void); +Disk *cfg_get_dsk_from_slot_drive(int slot, int drive); +void config_generate_config_kegs_name(char *outstr, int maxlen, Disk *dsk, int with_extras); +void config_write_config_kegs_file(void); +void insert_disk(int slot, int drive, const char *name, int ejected, int force_size, const char *partition_name, int part_num); +void eject_named_disk(Disk *dsk, const char *name, const char *partition_name); +void eject_disk_by_num(int slot, int drive); +void eject_disk(Disk *dsk); +int cfg_get_fd_size(int fd); +int cfg_partition_read_block(int fd, void *buf, int blk, int blk_size); +int cfg_partition_find_by_name_or_num(int fd, const char *partnamestr, int part_num, Disk *dsk); +int cfg_partition_make_list(int fd); +int cfg_maybe_insert_disk(int slot, int drive, const char *namestr); +int cfg_stat(char *path, struct stat *sb); +void cfg_htab_vtab(int x, int y); +void cfg_home(void); +void cfg_cleol(void); +void cfg_putchar(int c); +void cfg_printf(const char *fmt, ...); +void cfg_print_num(int num, int max_len); +void cfg_get_disk_name(char *outstr, int maxlen, int type_ext, int with_extras); +void cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change); +void cfg_get_base_path(char *pathptr, const char *inptr, int go_up); +void cfg_file_init(void); +void cfg_free_alldirents(Cfg_listhdr *listhdrptr); +void cfg_file_add_dirent(Cfg_listhdr *listhdrptr, const char *nameptr, int is_dir, int size, int image_start, int part_num); +int cfg_dirent_sortfn(const void *obj1, const void *obj2); +int cfg_str_match(const char *str1, const char *str2, int len); +void cfg_file_readdir(const char *pathptr); +char *cfg_shorten_filename(const char *in_ptr, int maxlen); +void cfg_fix_topent(Cfg_listhdr *listhdrptr); +void cfg_file_draw(void); +void cfg_partition_selected(void); +void cfg_file_update_ptr(char *str); +void cfg_file_selected(void); +void cfg_file_handle_key(int key); +void config_control_panel(void); diff --git a/kegs/Src/config_generic.cpp b/kegs/Src/config_generic.cpp new file mode 100644 index 0000000..4369894 --- /dev/null +++ b/kegs/Src/config_generic.cpp @@ -0,0 +1,718 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "moremem.h" +#include "sim65816.h" +#include "iwm.h" +#include "config.h" +#include "driver.h" + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +//extern int g_rom_version; +//extern word32 g_mem_size_base; +extern byte *g_rom_fc_ff_ptr; +extern byte *g_rom_cards_ptr; +//extern word32 g_mem_size_exp; +//extern Iwm iwm; +///extern int Verbose; + +//extern int g_highest_smartport_unit; + +// was in config.cpp + +int g_config_control_panel = 0; +int g_config_kegs_update_needed = 0; +word32 g_cfg_vbl_count = 0; +int g_user_page2_shadow = 1; +int g_save_cur_a2_stat = 0; + +const byte g_rom_c600_rom01_diffs[256] = { + 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xe2, 0x00, + 0xd0, 0x50, 0x0f, 0x77, 0x5b, 0xb9, 0xc3, 0xb1, + 0xb1, 0xf8, 0xcb, 0x4e, 0xb8, 0x60, 0xc7, 0x2e, + 0xfc, 0xe0, 0xbf, 0x1f, 0x66, 0x37, 0x4a, 0x70, + 0x55, 0x2c, 0x3c, 0xfc, 0xc2, 0xa5, 0x08, 0x29, + 0xac, 0x21, 0xcc, 0x09, 0x55, 0x03, 0x17, 0x35, + 0x4e, 0xe2, 0x0c, 0xe9, 0x3f, 0x9d, 0xc2, 0x06, + 0x18, 0x88, 0x0d, 0x58, 0x57, 0x6d, 0x83, 0x8c, + 0x22, 0xd3, 0x4f, 0x0a, 0xe5, 0xb7, 0x9f, 0x7d, + 0x2c, 0x3e, 0xae, 0x7f, 0x24, 0x78, 0xfd, 0xd0, + 0xb5, 0xd6, 0xe5, 0x26, 0x85, 0x3d, 0x8d, 0xc9, + 0x79, 0x0c, 0x75, 0xec, 0x98, 0xcc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x35, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x6c, 0x44, 0xce, 0x4c, 0x01, 0x08, 0x00, 0x00 +}; + +extern void x_config_load_roms(); +extern void x_config_load_additional_roms(); + + + +void +config_load_roms() +{ + int more_than_8mb; + int changed_rom; + int i; + + // OG load roms + if (g_driver.x_config_load_roms==NULL) + x_fatal_exit("missing rom"); + + g_driver.x_config_load_roms(); + + memset(&g_rom_cards_ptr[0], 0, 256*16); + + if (g_sim65816.g_rom_version < 0) + { + // No need to + return ; + } + + /* initialize c600 rom to be diffs from the real ROM, to build-in */ + /* Apple II compatibility without distributing ROMs */ + for(i = 0; i < 256; i++) { + g_rom_cards_ptr[0x600 + i] = g_rom_fc_ff_ptr[0x3c600 + i] ^ + g_rom_c600_rom01_diffs[i]; + } + + if(g_sim65816.g_rom_version >= 3) { + /* some patches */ + g_rom_cards_ptr[0x61b] ^= 0x40; + g_rom_cards_ptr[0x61c] ^= 0x33; + g_rom_cards_ptr[0x632] ^= 0xc0; + g_rom_cards_ptr[0x633] ^= 0x33; + } + + + x_config_load_additional_roms(); + + more_than_8mb = (g_sim65816.g_mem_size_exp > 0x800000); + /* Only do the patch if users wants more than 8MB of expansion mem */ + + changed_rom = 0; + if(g_sim65816.g_rom_version == 1) { + /* make some patches to ROM 01 */ +#if 0 + /* 1: Patch ROM selftest to not do speed test */ + printf("Patching out speed test failures from ROM 01\n"); + g_rom_fc_ff_ptr[0x3785a] = 0x18; + changed_rom = 1; +#endif + +#if 0 + /* 2: Patch ROM selftests not to do tests 2,4 */ + /* 0 = skip, 1 = do it, test 1 is bit 0 of LSByte */ + g_rom_fc_ff_ptr[0x371e9] = 0xf5; + g_rom_fc_ff_ptr[0x371ea] = 0xff; + changed_rom = 1; +#endif + + + if(more_than_8mb) { + /* Geoff Weiss patch to use up to 14MB of RAM */ + g_rom_fc_ff_ptr[0x30302] = 0xdf; + g_rom_fc_ff_ptr[0x30314] = 0xdf; + g_rom_fc_ff_ptr[0x3031c] = 0x00; + changed_rom = 1; + } + + /* Patch ROM selftest to not do ROM cksum if any changes*/ + if(changed_rom) { + g_rom_fc_ff_ptr[0x37a06] = 0x18; + g_rom_fc_ff_ptr[0x37a07] = 0x18; + } + } else if(g_sim65816.g_rom_version == 3) { + /* patch ROM 03 */ + printf("Patching ROM 03 smartport bug\n"); + /* 1: Patch Smartport code to fix a stupid bug */ + /* that causes it to write the IWM status reg into c036, */ + /* which is the system speed reg...it's "safe" since */ + /* IWM status reg bit 4 must be 0 (7MHz)..., otherwise */ + /* it might have turned on shadowing in all banks! */ + g_rom_fc_ff_ptr[0x357c9] = 0x00; + changed_rom = 1; + +#if 0 + /* patch ROM 03 to not to speed test */ + /* skip fast speed test */ + g_rom_fc_ff_ptr[0x36ad7] = 0x18; + g_rom_fc_ff_ptr[0x36ad8] = 0x18; + changed_rom = 1; +#endif + +#if 0 + /* skip slow speed test */ + g_rom_fc_ff_ptr[0x36ae7] = 0x18; + g_rom_fc_ff_ptr[0x36ae8] = 0x6b; + changed_rom = 1; +#endif + +#if 0 + /* 4: Patch ROM 03 selftests not to do tests 1-4 */ + g_rom_fc_ff_ptr[0x364a9] = 0xf0; + g_rom_fc_ff_ptr[0x364aa] = 0xff; + changed_rom = 1; +#endif + + /* ROM tests are in ff/6403-642x, where 6403 = addr of */ + /* test 1, etc. */ + + if(more_than_8mb) { + /* Geoff Weiss patch to use up to 14MB of RAM */ + g_rom_fc_ff_ptr[0x30b] = 0xdf; + g_rom_fc_ff_ptr[0x31d] = 0xdf; + g_rom_fc_ff_ptr[0x325] = 0x00; + changed_rom = 1; + } + + if(changed_rom) { + /* patch ROM 03 selftest to not do ROM cksum */ + g_rom_fc_ff_ptr[0x36cb0] = 0x18; + g_rom_fc_ff_ptr[0x36cb1] = 0x18; + } + + } +} + + + +Disk * +cfg_get_dsk_from_slot_drive(int slot, int drive) +{ + Disk *dsk; + int max_drive; + + /* Get dsk */ + max_drive = 2; + switch(slot) { + case 5: + dsk = &(g_iwm.iwm.drive35[drive]); + break; + case 6: + dsk = &(g_iwm.iwm.drive525[drive]); + break; + default: + max_drive = MAX_C7_DISKS; + dsk = &(g_iwm.iwm.smartport[drive]); + break; + } + + if(drive >= max_drive) { + dsk -= drive; /* move back to drive 0 effectively */ + } + dsk->slot = slot; + dsk->disk = drive+1; + return dsk; +} + + +void +insert_disk(int slot, int drive, const char *name, int ejected, int force_size, + const char *partition_name, int part_num) +{ + byte buf_2img[512]; + Disk *dsk; + + +// char *part_ptr; + int size; +#if 0 +// char *name_ptr; + char *uncomp_ptr, *system_str; + int system_len; +#endif +// int part_len; + int cmp_o, cmp_p, cmp_dot; + int cmp_b, cmp_i, cmp_n; + int can_write; + int len; + int nibs; + int unix_pos; + size_t name_len; + int image_identified; + int exp_size; + int save_track; + int ret; + int tmp; + int i; + + + g_config_kegs_update_needed = 1; + + if((slot < 5) || (slot > 7)) { + fatal_printf("Invalid slot for inserting disk: %d\n", slot); + return; + } + if(drive < 0 || ((slot == 7) && (drive >= MAX_C7_DISKS)) || + ((slot < 7) && (drive > 1))) { + fatal_printf("Invalid drive for inserting disk: %d\n", drive); + return; + } + + dsk = cfg_get_dsk_from_slot_drive(slot, drive); + + // OG Do not insert same disk at same place + if (( dsk->name_ptr && name) && !strcmp(dsk->name_ptr,name)) return ; + +#if 0 + printf("Inserting disk %s (%s or %d) in slot %d, drive: %d\n", name, + partition_name, part_num, slot, drive); +#endif + + dsk->just_ejected = 0; + dsk->force_size = force_size; + + if(dsk->fd >= 0) { + eject_disk(dsk); + } + + // OG check for valid name first + if (!name) return ; + + /* Before opening, make sure no other mounted disk has this name */ + /* If so, unmount it */ + if(!ejected) { + for(i = 0; i < 2; i++) { + eject_named_disk(&g_iwm.iwm.drive525[i], name,partition_name); + eject_named_disk(&g_iwm.iwm.drive35[i], name, partition_name); + } + for(i = 0; i < MAX_C7_DISKS; i++) { + eject_named_disk(&g_iwm.iwm.smartport[i],name,partition_name); + } + } + + /* + if(dsk->name_ptr != 0) { + // free old name_ptr + free(dsk->name_ptr); + } + */ + + name_len = strlen(name); + strncpy(dsk->name_ptr,name,MAX_DISK_NAME); + /* + name_len = strlen(name); + name_ptr = (char *)malloc(name_len + 1); + strncpy(name_ptr, name, name_len + 1); + dsk->name_ptr = name_ptr; + */ + +// dsk->partition_name = 0; + dsk->partition_name[0] = 0; + + if(partition_name != 0) { + /* + part_len = strlen(partition_name) + 1; + part_ptr = (char *)malloc(part_len); + strncpy(part_ptr, partition_name, part_len); + dsk->partition_name = part_ptr; + */ + strncpy(dsk->partition_name,partition_name,MAX_DISK_NAME); + } + dsk->partition_num = part_num; + + iwm_printf("Opening up disk image named: %s\n", dsk->name_ptr); + + if(ejected) { + /* just get out of here */ + dsk->fd = -1; + return; + } + + dsk->fd = -1; + +#ifdef ACTIVEGSKARATEKA + can_write = 0; +#else + can_write = 1; +#endif + +//OG discard .GZ support +#if 0 + if((name_len > 3) && (strcmp(&name_ptr[name_len - 3], ".gz") == 0)) { + + /* it's gzip'ed, try to gunzip it, then unlink the */ + /* uncompressed file */ + + can_write = 0; + + uncomp_ptr = (char *)malloc(name_len + 1); + strncpy(uncomp_ptr, name_ptr, name_len + 1); + uncomp_ptr[name_len - 3] = 0; + + system_len = 2*name_len + 100; + system_str = (char *)malloc(system_len + 1); + snprintf(system_str, system_len, + "set -o noclobber;gunzip -c %c%s%c > %c%s%c", + 0x22, name_ptr, 0x22, + 0x22, uncomp_ptr, 0x22); + /* 0x22 are " to allow spaces in filenames */ + printf("I am uncompressing %s into %s for mounting\n", + name_ptr, uncomp_ptr); + ret = system(system_str); + if(ret == 0) { + /* successfully ran */ + dsk->fd = open(uncomp_ptr, O_RDONLY | O_BINARY, 0x1b6); + iwm_printf("Opening .gz file %s is fd: %d\n", + uncomp_ptr, dsk->fd); + + /* and, unlink the temporary file */ + (void)unlink(uncomp_ptr); + } + free(system_str); + free(uncomp_ptr); + /* Reduce name_len by 3 so that subsequent compares for .po */ + /* look at the correct chars */ + name_len -= 3; + } +#endif // OG + + if(dsk->fd < 0 && can_write) { + dsk->fd = open(dsk->name_ptr, O_RDWR | O_BINARY, 0x1b6); + } + + if(dsk->fd < 0 /*&& can_write*/) { + printf("Trying to open %s read-only, errno: %d\n", dsk->name_ptr, + errno); + dsk->fd = open(dsk->name_ptr, O_RDONLY | O_BINARY, 0x1b6); + can_write = 0; + } + + iwm_printf("open returned: %d\n", dsk->fd); + + if(dsk->fd < 0) { + fatal_printf("Disk image %s does not exist!\n", dsk->name_ptr); + return; + } + + if(can_write != 0) { + dsk->write_prot = 0; + dsk->write_through_to_unix = 1; + } else { + dsk->write_prot = 1; + dsk->write_through_to_unix = 0; + } + + save_track = dsk->cur_qtr_track; /* save arm position */ + dsk->image_type = DSK_TYPE_PRODOS; + dsk->image_start = 0; + + /* See if it is in 2IMG format */ + ret = read(dsk->fd, (char *)&buf_2img[0], 512); + size = force_size; + if(size <= 0) { + size = cfg_get_fd_size(dsk->fd) ; + } + + /* Try to guess that there is a Mac Binary header of 128 bytes */ + /* See if image size & 0xfff = 0x080 which indicates extra 128 bytes */ + if((size & 0xfff) == 0x080) { + printf("Assuming Mac Binary header on %s\n", dsk->name_ptr); + dsk->image_start += 0x80; + } + image_identified = 0; + if(buf_2img[0] == '2' && buf_2img[1] == 'I' && buf_2img[2] == 'M' && + buf_2img[3] == 'G') { + + // OG Put back Gilles Tschopp hack to deal with corrupted 2IMG files + size -= 64; + size = size & -0x1000; + + /* It's a 2IMG disk */ +#ifdef _DEBUG + printf("Image named %s is in 2IMG format\n", dsk->name_ptr); +#endif + image_identified = 1; + + if(buf_2img[12] == 0) { + printf("2IMG is in DOS 3.3 sector order\n"); + dsk->image_type = DSK_TYPE_DOS33; + } + if(buf_2img[19] & 0x80) { + /* disk is locked */ + printf("2IMG is write protected\n"); + dsk->write_prot = 1; + dsk->write_through_to_unix = 0; + } + if((buf_2img[17] & 1) && (dsk->image_type == DSK_TYPE_DOS33)) { + dsk->vol_num = buf_2img[16]; + printf("Setting DOS 3.3 vol num to %d\n", dsk->vol_num); + } + + // OG do not overwrite when 2mg size = 0 + int size2img = (buf_2img[31] << 24) + (buf_2img[30] << 16) + (buf_2img[29] << 8) + buf_2img[28]; + if (size2img) size = size2img; + else printf(".2MG has corrupted size - fixed.\n"); + + unix_pos = (buf_2img[27] << 24) + (buf_2img[26] << 16) + + (buf_2img[25] << 8) + buf_2img[24]; + // Some 2IMG archives have the size byte reversed + if(size == 0x800c00) { + // Byte reversed 0x0c8000 + size = 0x0c8000; + } + dsk->image_start = unix_pos; + dsk->image_size = size; + } + exp_size = 800*1024; + if(dsk->disk_525) { + exp_size = 140*1024; + } + if(!image_identified) { + /* See if it might be the Mac diskcopy format */ + tmp = (buf_2img[0x40] << 24) + (buf_2img[0x41] << 16) + + (buf_2img[0x42] << 8) + buf_2img[0x43]; + if((size >= (exp_size + 0x54)) && (tmp == exp_size)) { + /* It's diskcopy since data size field matches */ + printf("Image named %s is in Mac diskcopy format\n", + dsk->name_ptr); + image_identified = 1; + dsk->image_start += 0x54; + dsk->image_size = exp_size; + dsk->image_type = DSK_TYPE_PRODOS; /* ProDOS */ + } + } + if(!image_identified) { + /* Assume raw image */ + dsk->image_size = size; + dsk->image_type = DSK_TYPE_PRODOS; + if(dsk->disk_525) { + dsk->image_type = DSK_TYPE_DOS33; + + if(name_len >= 4) { + cmp_o = dsk->name_ptr[name_len-1]; + cmp_p = dsk->name_ptr[name_len-2]; + cmp_dot = dsk->name_ptr[name_len-3]; + if(cmp_dot == '.' && + (cmp_p == 'p' || cmp_p == 'P') && + (cmp_o == 'o' || cmp_o == 'O')) { + dsk->image_type = DSK_TYPE_PRODOS; + } + + cmp_b = dsk->name_ptr[name_len-1]; + cmp_i = dsk->name_ptr[name_len-2]; + cmp_n = dsk->name_ptr[name_len-3]; + cmp_dot = dsk->name_ptr[name_len-4]; + if(cmp_dot == '.' && + (cmp_n == 'n' || cmp_n == 'N') && + (cmp_i == 'i' || cmp_i == 'I') && + (cmp_b == 'b' || cmp_b == 'B')) { + dsk->image_type = DSK_TYPE_NIB; + dsk->write_prot = 0; // OG : Remove WriteProtect on .nib !!!! TO REACTIVATE !! + dsk->write_through_to_unix = 0; + } + } + } + } + + dsk->disk_dirty = 0; + dsk->nib_pos = 0; + dsk->trks = 0; + + if(dsk->smartport) { + g_iwm.g_highest_smartport_unit = MAX(dsk->drive,g_iwm.g_highest_smartport_unit); + +// OG Disabled partition support +#ifndef ACTIVEGS + if( (partition_name != NULL && *partition_name ) || part_num >= 0) { + ret = cfg_partition_find_by_name_or_num(dsk->fd, + partition_name, part_num, dsk); + printf("partition %s (num %d) mounted, wr_prot: %d\n", + partition_name, part_num, dsk->write_prot); + + if(ret < 0) { + close(dsk->fd); + dsk->fd = -1; + return; + } + } +#endif + iwm_printf("adding smartport device[%d], size:%08x, " + "img_sz:%08x\n", dsk->drive, dsk->trks[0].unix_len, + dsk->image_size); + } else if(dsk->disk_525) { + unix_pos = dsk->image_start; + size = dsk->image_size; + disk_set_num_tracks(dsk, 4*35); + len = 0x1000; + nibs = NIB_LEN_525; + if(dsk->image_type == DSK_TYPE_NIB) { + len = dsk->image_size / 35;; + nibs = len; + } + if(size != 35*len) { + fatal_printf("Disk 5.25 error: size is %d, not 140K. " + "Will try to mount anyway\n", size, 35*len); + } + for(i = 0; i < 35; i++) { + iwm_move_to_track(dsk, 4*i); + disk_unix_to_nib(dsk, 4*i, unix_pos, len, nibs); + unix_pos += len; + } + } else { + /* disk_35 */ + unix_pos = dsk->image_start; + size = dsk->image_size; + if(size != 800*1024) { + fatal_printf("Disk 3.5 error: size is %d, not 800K. " + "Will try to mount anyway\n", size); + } + disk_set_num_tracks(dsk, 2*80); + for(i = 0; i < 2*80; i++) { + iwm_move_to_track(dsk, i); + len = g_track_bytes_35[i >> 5]; + nibs = g_track_nibs_35[i >> 5]; + iwm_printf("Trk: %d.%d = unix: %08x, %04x, %04x\n", + i>>1, i & 1, unix_pos, len, nibs); + disk_unix_to_nib(dsk, i, unix_pos, len, nibs); + unix_pos += len; + + iwm_printf(" trk_len:%05x\n", dsk->trks[i].track_len); + } + } + + iwm_move_to_track(dsk, save_track); + + x_notify_disk_insertion(dsk->image_size,dsk->image_start,(dsk->image_type == DSK_TYPE_PRODOS),slot,drive); + +} + +void +eject_named_disk(Disk *dsk, const char *name, const char *partition_name) +{ + + if(dsk->fd < 0) { + return; + } + + /* If name matches, eject the disk! */ + if(!strcmp(dsk->name_ptr, name)) { + /* It matches, eject it */ + if((partition_name != 0) && (dsk->partition_name != 0)) { + /* If both have partitions, and they differ, then */ + /* don't eject. Otherwise, eject */ + if(strcmp(dsk->partition_name, partition_name) != 0) { + /* Don't eject */ + return; + } + } + eject_disk(dsk); + } +} + +void +eject_disk_by_num(int slot, int drive) +{ + Disk *dsk; + + dsk = cfg_get_dsk_from_slot_drive(slot, drive); + + eject_disk(dsk); +} + +void +eject_disk(Disk *dsk) +{ + int motor_on; + int i; + + if(dsk->fd < 0) { + return; + } + + g_config_kegs_update_needed = 1; + + motor_on = g_iwm.iwm.motor_on; + if(g_moremem.g_c031_disk35 & 0x40) { + motor_on = g_iwm.iwm.motor_on35; + } + if(motor_on) { + halt_printf("Try eject dsk:%s, but motor_on!\n", dsk->name_ptr); + } + + iwm_flush_disk_to_unix(dsk); + + printf("Ejecting disk: %s\n", dsk->name_ptr); + + /* Free all memory, close file */ + + /* free the tracks first */ + if(dsk->trks != 0) { + for(i = 0; i < dsk->num_tracks; i++) { + if(dsk->trks[i].nib_area) { + free(dsk->trks[i].nib_area); + } + dsk->trks[i].nib_area = 0; + dsk->trks[i].track_len = 0; + } + free(dsk->trks); + } + dsk->num_tracks = 0; + dsk->trks = 0; + + /* close file, clean up dsk struct */ + close(dsk->fd); + + dsk->image_start = 0; + dsk->image_size = 0; + dsk->nib_pos = 0; + dsk->disk_dirty = 0; + dsk->write_through_to_unix = 0; + dsk->write_prot = 1; + dsk->fd = -1; + dsk->just_ejected = 1; + + /* Leave name_ptr valid */ // OG WHY? + + /* + if (dsk->name_ptr) + { + free(dsk->name_ptr); + dsk->name_ptr = NULL; + } + */ + dsk->name_ptr[0]=0; +} + + +int +cfg_get_fd_size(int fd) +{ + struct stat stat_buf; + int ret; + + ret = fstat(fd, &stat_buf); + if(ret != 0) { + fprintf(stderr,"fstat returned %d on fd %d, errno: %d\n", + ret, fd, errno); + stat_buf.st_size = 0; + } + + return (int)stat_buf.st_size; +} diff --git a/kegs/Src/defc.h b/kegs/Src/defc.h new file mode 100644 index 0000000..1ac1570 --- /dev/null +++ b/kegs/Src/defc.h @@ -0,0 +1,502 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#ifdef INCLUDE_RCSID_C +const char rcsid_defc_h[] = "@(#)$KmKId: defc.h,v 1.100 2004-11-09 02:02:07-05 kentd Exp $"; +#endif + +#if !defined(VIDEO_SINGLEHLINE) && !defined(VIDEO_DOUBLEHLINE) +# define VIDEO_DOUBLEHLINE +#endif + +#if !defined(VIDEO_SINGLEVLINE) && !defined(VIDEO_DOUBLEVLINE) +# define VIDEO_DOUBLEVLINE +#endif + +#ifdef VIDEO_DOUBLEHLINE +# define VIDEO_HFACTOR 2 +#else +# define VIDEO_HFACTOR 1 +#endif + + +#ifdef VIDEO_DOUBLEVLINE +# define VIDEO_VFACTOR 2 +#else +# define VIDEO_VFACTOR 1 +#endif + +#include "defcomm.h" + +// OG redirect printf to console +#ifdef ACTIVEGS +#include +extern "C" int outputInfo(const char* format,...); +extern "C" int fOutputInfo(FILE*,const char* format,...); +#define printf outputInfo +#define fprintf fOutputInfo +#ifdef _DEBUG +#define debug_printf(X,...) outputInfo(X,## __VA_ARGS__) +#else +#define debug_printf(X,...) + +#endif +#endif + +#define STRUCT(a) typedef struct _ ## a a; struct _ ## a + +typedef unsigned char byte; +typedef unsigned short word16; +typedef unsigned int word32; +#if _MSC_VER +typedef unsigned __int64 word64; +#else +typedef unsigned long long word64; +#endif + +void U_STACK_TRACE(); + +/* 28MHz crystal, plus every 65th 1MHz cycle is stretched 140ns */ +#define CYCS_28_MHZ (28636360) +#define DCYCS_28_MHZ (1.0*CYCS_28_MHZ) +#define CYCS_3_5_MHZ (CYCS_28_MHZ/8) +#define DCYCS_1_MHZ ((DCYCS_28_MHZ/28.0)*(65.0*7/(65.0*7+1.0))) +#define CYCS_1_MHZ ((int)DCYCS_1_MHZ) + +/* #define DCYCS_IN_16MS_RAW (DCYCS_1_MHZ / 60.0) */ +#define DCYCS_IN_16MS_RAW (262.0 * 65.0) +/* Use precisely 17030 instead of forcing 60 Hz since this is the number of */ +/* 1MHz cycles per screen */ +#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW)) +#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS)) + +#ifdef KEGS_LITTLE_ENDIAN +# define BIGEND(a) ((((a) >> 24) & 0xff) + \ + (((a) >> 8) & 0xff00) + \ + ((((unsigned)a) << 8) & 0xff0000) + \ + ((((unsigned)a) << 24) & 0xff000000)) +# define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00)) +# define GET_BE_WORD32(a) (BIGEND(a)) +#else +# define BIGEND(a) (a) +# define GET_BE_WORD16(a) (a) +# define GET_BE_WORD32(a) (a) +#endif + +#define MAXNUM_HEX_PER_LINE 32 + +#ifdef __NeXT__ +# include +#endif + +#if !defined( _WIN32) && !defined(UNDER_CE) // OG +# include +# include +# include +#endif + + + +#include +#include +#include + +#include +#include +#include + +#ifndef UNDER_CE // OG CE SPecific +#include +#include +#include +#include +// OG Adding support for open +#ifdef WIN32 +#include +#endif + +#else +extern int errno; +extern int open(const char* name,int,...); +extern int read(int,char*,int); +extern int close(int); +extern int write( int fd, const void *buffer, unsigned int count ); +extern int lseek(int,int,int); +struct stat { int st_size; }; +extern int stat(const char* name, struct stat*); +extern int fstat(int, struct stat*); +#define O_RDWR 1 +#define O_BINARY 2 +#define O_RDONLY 4 +#define O_WRONLY 8 +#define O_CREAT 16 +#define O_TRUNC 32 +#define EAGAIN 11 +#define EINTR 4 + +#endif + + +#ifdef HPUX +# include /* for GET_ITIMER */ +#endif + +#ifdef SOLARIS +# include +#endif + + +#ifndef O_BINARY +/* work around some Windows junk */ +# define O_BINARY 0 +#endif + +STRUCT(Pc_log) { + double dcycs; + word32 dbank_kpc; + word32 instr; + word32 psr_acc; + word32 xreg_yreg; + word32 stack_direct; + word32 pad; +}; + +STRUCT(Data_log) { + double dcycs; + word32 addr; + word32 val; + word32 size; +}; + +#if defined(_MSC_VER) +#define _ALIGNED(x) __declspec(align(x)) +#else +#if defined(__GNUC__) +#define _ALIGNED(x) __attribute__ ((aligned(x))) +#endif +#endif + +#define PRAGMA_PACK_SIZE 4 +#ifdef WIN32 +# define XCODE_PRAGMA_PACK +#else +# define XCODE_PRAGMA_PACK __attribute__((aligned (PRAGMA_PACK_SIZE))) +#endif +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +STRUCT(Event) { + double dcycs; + int type; + Event *next; +} XCODE_PRAGMA_PACK; + +STRUCT(Fplus) { + double plus_1; + double plus_2; + double plus_3; + double plus_x_minus_1; +} XCODE_PRAGMA_PACK; + +STRUCT(Engine_reg) { + double fcycles; + word32 kpc; + word32 acc; + + word32 xreg; + word32 yreg; + + word32 stack; + word32 dbank; + + word32 direct; + word32 psr; + Fplus *fplus_ptr; +} XCODE_PRAGMA_PACK; + +STRUCT(Kimage) { + void *dev_handle; + void *dev_handle2; + byte *data_ptr; + int data_size; + int width_req; + int width_act; + int height; + int depth; + int mdepth; + int aux_info; +} XCODE_PRAGMA_PACK; + +typedef byte *Pg_info; +STRUCT(Page_info) { + Pg_info rd_wr; +} XCODE_PRAGMA_PACK; + +STRUCT(Cfg_menu) { + const char *str; + void *ptr; + const char *name_str; + void *defptr; + int cfgtype; +} XCODE_PRAGMA_PACK; + +STRUCT(Cfg_dirent) { + char *name; + int is_dir; + int size; + int image_start; + int part_num; +} XCODE_PRAGMA_PACK; + +STRUCT(Cfg_listhdr) { + Cfg_dirent *direntptr; + int max; + int last; + int invalid; + + int curent; + int topent; + + int num_to_show; +} XCODE_PRAGMA_PACK; + +STRUCT(Emustate_intlist) { + const char *str; + int *iptr; +} XCODE_PRAGMA_PACK; + +STRUCT(Emustate_dbllist) { + const char *str; + double *dptr; +} XCODE_PRAGMA_PACK; + +STRUCT(Emustate_word32list) { + const char *str; + word32 *wptr; +} XCODE_PRAGMA_PACK; + +#ifdef __LP64__ +# define PTR2WORD(a) ((unsigned long)(a)) +#else +# define PTR2WORD(a) ((unsigned int)(a)) +#endif + + + +#define C041_EN_25SEC_INTS 0x10 +#define C041_EN_VBL_INTS 0x08 +#define C041_EN_SWITCH_INTS 0x04 +#define C041_EN_MOVE_INTS 0x02 +#define C041_EN_MOUSE 0x01 + +/* WARNING: SCC1 and SCC0 interrupts must be in this order for scc.c */ +/* This order matches the SCC hardware */ +#define IRQ_PENDING_SCC1_ZEROCNT 0x00001 +#define IRQ_PENDING_SCC1_TX 0x00002 +#define IRQ_PENDING_SCC1_RX 0x00004 +#define IRQ_PENDING_SCC0_ZEROCNT 0x00008 +#define IRQ_PENDING_SCC0_TX 0x00010 +#define IRQ_PENDING_SCC0_RX 0x00020 +#define IRQ_PENDING_C023_SCAN 0x00100 +#define IRQ_PENDING_C023_1SEC 0x00200 +#define IRQ_PENDING_C046_25SEC 0x00400 +#define IRQ_PENDING_C046_VBL 0x00800 +#define IRQ_PENDING_ADB_KBD_SRQ 0x01000 +#define IRQ_PENDING_ADB_DATA 0x02000 +#define IRQ_PENDING_ADB_MOUSE 0x04000 +#define IRQ_PENDING_DOC 0x08000 + + +#define EXTRU(val, pos, len) \ + ( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \ + (((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) ) + +#define DEP1(val, pos, old_val) \ + (((old_val) & ~(1 << (31 - (pos))) ) | \ + ( ((val) & 1) << (31 - (pos))) ) + +#define set_halt(val) \ + if(val) { set_halt_act(val); } + +#define clear_halt() \ + clr_halt_act() + +#define GET_PAGE_INFO_RD(page) \ + (r_sim65816.page_info_rd_wr[page].rd_wr) + +#define GET_PAGE_INFO_WR(page) \ + (r_sim65816.page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr) + +#define SET_PAGE_INFO_RD(page,val) \ + r_sim65816.page_info_rd_wr[page].rd_wr = (Pg_info)val; + +#define SET_PAGE_INFO_WR(page,val) \ + r_sim65816.page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = (Pg_info)val; + +#define VERBOSE_DISK 0x001 +#define VERBOSE_IRQ 0x002 +#define VERBOSE_CLK 0x004 +#define VERBOSE_SHADOW 0x008 +#define VERBOSE_IWM 0x010 +#define VERBOSE_DOC 0x020 +#define VERBOSE_ADB 0x040 +#define VERBOSE_SCC 0x080 +#define VERBOSE_TEST 0x100 +#define VERBOSE_VIDEO 0x200 +#define VERBOSE_MAC 0x400 + +#if !defined(_DEBUG) || defined(NO_VERB) +# define DO_VERBOSE 0 +#else +# define DO_VERBOSE 1 +#endif + +#define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf +#define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf +#define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf +#define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf +#define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf +#define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf +#define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf +#define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf +#define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf +#define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf +#define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf + + +#define HALT_ON_SCAN_INT 0x001 +#define HALT_ON_IRQ 0x002 +#define HALT_ON_SHADOW_REG 0x004 +#define HALT_ON_C70D_WRITES 0x008 + +#define HALT_ON(a, msg) \ + if(g_sim65816.Halt_on & a) { \ + halt_printf(msg); \ + } + + +#ifndef MIN +# define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +# define MAX(a,b) (((a) < (b)) ? (b) : (a)) +#endif + +#define GET_ITIMER(dest) dest = get_itimer(); + +#include "protos.h" + +// OG Added interfaces to communicate with the emulator +void x_clk_setup_bram_version(); +void x_notify_disk_insertion(int _size, int _start, int _isprodos,int _slot, int _drive); +void x_notify_motor_status(int _motorOn,int _slot,int _drive, int _curtrack); +void x_notify_disk_ejection(int _slot,int _drive); +void x_refresh_video(); + +void x_exit(int _err); +void x_alert(const char* format,...); +void x_fatal_exit(const char* _str); + +enum refreshpanelenum +{ + PANEL_DISK = 1, + PANEL_RUNTIME = 2, + PANEL_PARAMS = 4, + PANEL_BOOT = 8, + PANEL_LOADED = 16, + PANEL_SPEED = 32, + PANEL_ALL = -1 +}; + +extern void x_refresh_panel(int _panel); + + +#include "compression.h" + +#ifdef DRIVER_ANDROID +#define ALIGNMENT_ERROR(_MODULE,_SIZE,_THISSIZE) \ +{ \ + char str[512]; \ + sprintf(str,"Alignment error in %s : got %d, this : %d",_MODULE,_SIZE,_THISSIZE); \ + x_fatal_exit(str); \ +} +#else +#define ALIGNMENT_ERROR(_MODULE,_SIZE,_THISSIZE) \ +{ \ + char str[512]; \ + sprintf(str,"Alignment error in %s : got %d, this : %ld",_MODULE,_SIZE,_THISSIZE); \ + x_fatal_exit(str); \ +} +#endif +class serialize +{ +public: + word32 size; + void* data; + int fastalloc; + int rlesize; + void* rledata; + int rletype; + serialize() + { + memset(this,0,sizeof(*this)); + + } + + void release(); + int compress(); + int expand(); + int releasecompressed(); + int releaseuncompressed(); + void save(const char* name,void*); + int load(const char*_name,void* _fileptr); +} XCODE_PRAGMA_PACK; + +class serialized +{ +public: + int _size; + serialized* _this; + void in(serialize* _s); + int out(serialize* _s, int _fastalloc); + +} XCODE_PRAGMA_PACK; + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +#define INIT_SERIALIZED() \ + memset(this,0,sizeof(*this)); \ + _size = sizeof(*this); \ + _this = this; + +#define DEFAULT_SERIALIZE_IN_OUT \ + void in(serialize* _s) \ + { \ + byte* ptr = (byte*)_s->data; \ + int ssize = *(int*)ptr; \ + if (ssize!= sizeof(*this)) \ + ALIGNMENT_ERROR("n/a",ssize,sizeof(*this)); \ + ptr += sizeof(ssize); \ + memcpy(this,ptr,sizeof(*this)); \ + } \ + int out(serialize* _s, int _fastalloc) \ + { \ + int ssize = sizeof(*this); \ + int size = ssize + sizeof(ssize); \ + _s->size = size; \ + _s->fastalloc = _fastalloc; \ + _s->data = (void*)x_malloc(size,_fastalloc); \ + byte* ptr = (byte*) _s->data; \ + memcpy(ptr,&ssize,sizeof(ssize)); \ + ptr+=sizeof(ssize); \ + memcpy(ptr,this,sizeof(*this)); \ + return size; \ + } diff --git a/kegs/Src/defcomm.h b/kegs/Src/defcomm.h new file mode 100644 index 0000000..8e247c9 --- /dev/null +++ b/kegs/Src/defcomm.h @@ -0,0 +1,189 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_C +const char rcsdif_defcomm_h[] = "@(#)$KmKId: defcomm.h,v 1.94 2004-10-13 21:53:44-04 kentd Exp $"; +#endif + +#if 0 +# define CHECK_BREAKPOINTS +#endif + +#define SHIFT_PER_CHANGE 3 +#define CHANGE_SHIFT (5 + SHIFT_PER_CHANGE) + +#define SLOW_MEM_CH_SIZE (0x10000 >> CHANGE_SHIFT) + +#define MAXNUM_HEX_PER_LINE 32 + +/* Different Joystick defines */ +#define JOYSTICK_MOUSE 1 +#define JOYSTICK_LINUX 2 +#define JOYSTICK_KEYPAD 3 +#define JOYSTICK_WIN32_1 4 +#define JOYSTICK_WIN32_2 5 + + +#define HALT_EVENT 0x10 +//#define HALT_WANTTOQUIT 0x20 // OG : added WANTTOQUIT event +#define HALT_WANTTOBRK 0x40 // OG : added WANTTOBRK event + +#define MAX_BREAK_POINTS 128 + +#define MAX_BP_INDEX 0x100 +#define MAX_BP_PER_INDEX 3 /* 4 word32s total = 16 bytes */ +#define SIZE_BREAKPT_ENTRY_BITS 4 /* 16 bytes = 4 bits */ + +/* Warning--next defines used by asm! */ +#define PAGE_INFO_PAD_SIZE 0x800 +#define PAGE_INFO_WR_OFFSET 0x10000+PAGE_INFO_PAD_SIZE + +#define BANK_IO_BIT 31 +#define BANK_SHADOW_BIT 30 +#define BANK_SHADOW2_BIT 29 +#define BANK_IO2_BIT 28 +#define BANK_BREAK_BIT 27 +#define BANK_BREAK (1 << (31 - BANK_BREAK_BIT)) +#define BANK_IO2_TMP (1 << (31 - BANK_IO2_BIT)) +#define BANK_IO_TMP (1 << (31 - BANK_IO_BIT)) +#define BANK_SHADOW (1 << (31 - BANK_SHADOW_BIT)) +#define BANK_SHADOW2 (1 << (31 - BANK_SHADOW2_BIT)) +#define SET_BANK_IO \ + (&g_dummy_memory1_ptr[BANK_IO_TMP | BANK_IO2_TMP]) + +#define BANK_BAD_MEM (&g_dummy_memory1_ptr[0xff]) + + +#define ENGINE_FCYCLES 0x00 +#define ENGINE_REG_KPC 0x08 +#define ENGINE_REG_ACC 0x0c +#define ENGINE_REG_XREG 0x10 +#define ENGINE_REG_YREG 0x14 +#define ENGINE_REG_STACK 0x18 +#define ENGINE_REG_DBANK 0x1c +#define ENGINE_REG_DIRECT 0x20 +#define ENGINE_REG_PSR 0x24 +#define ENGINE_FPLUS_PTR 0x28 + +#define LOG_PC_DCYCS 0x00 +#define LOG_PC_DBANK_KPC 0x08 +#define LOG_PC_INSTR 0x0c +#define LOG_PC_PSR_ACC 0x10 +#define LOG_PC_XREG_YREG 0x14 +#define LOG_PC_STACK_DIRECT 0x18 +#define LOG_PC_PAD 0x1c + +#define LOG_PC_SIZE 0x20 + + +#define FPLUS_PLUS_1 0x00 +#define FPLUS_PLUS_2 0x08 +#define FPLUS_PLUS_3 0x10 +#define FPLUS_PLUS_X_M1 0x18 + +#define RET_BREAK 0x1 +#define RET_COP 0x2 +#define RET_WDM 0x3 +#define RET_MVP 0x4 +#define RET_MVN 0x5 +#define RET_WAI 0x6 +#define RET_STP 0x7 +#define RET_ADD_DEC_8 0x8 +#define RET_ADD_DEC_16 0x9 +#define RET_C700 0xa +#define RET_C70A 0xb +#define RET_C70D 0xc +#define RET_IRQ 0xd + + +#define MODE_BORDER 0 +#define MODE_TEXT 1 +#define MODE_GR 2 +#define MODE_HGR 3 +#define MODE_SUPER_HIRES 4 + +#define BIT_ALL_STAT_TEXT 0 +#define BIT_ALL_STAT_VID80 1 +#define BIT_ALL_STAT_ST80 2 +#define BIT_ALL_STAT_COLOR_C021 3 +#define BIT_ALL_STAT_MIX_T_GR 4 +#define BIT_ALL_STAT_DIS_COLOR_DHIRES 5 /* special val, c029 */ +#define BIT_ALL_STAT_PAGE2 6 /* special val, statereg */ +#define BIT_ALL_STAT_SUPER_HIRES 7 /* special, c029 */ +#define BIT_ALL_STAT_HIRES 8 +#define BIT_ALL_STAT_ANNUNC3 9 +#define BIT_ALL_STAT_BG_COLOR 10 /* 4 bits */ +#define BIT_ALL_STAT_TEXT_COLOR 14 /* 4 bits */ + /* Text must be just above */ + /* bg to match c022 reg */ +#define BIT_ALL_STAT_ALTCHARSET 18 +#define BIT_ALL_STAT_FLASH_STATE 19 +#define BIT_ALL_STAT_A2VID_PALETTE 20 /* 4 bits */ + +#define ALL_STAT_SUPER_HIRES (1 << (BIT_ALL_STAT_SUPER_HIRES)) +#define ALL_STAT_TEXT (1 << (BIT_ALL_STAT_TEXT)) +#define ALL_STAT_VID80 (1 << (BIT_ALL_STAT_VID80)) +#define ALL_STAT_PAGE2 (1 << (BIT_ALL_STAT_PAGE2)) +#define ALL_STAT_ST80 (1 << (BIT_ALL_STAT_ST80)) +#define ALL_STAT_COLOR_C021 (1 << (BIT_ALL_STAT_COLOR_C021)) +#define ALL_STAT_DIS_COLOR_DHIRES (1 << (BIT_ALL_STAT_DIS_COLOR_DHIRES)) +#define ALL_STAT_MIX_T_GR (1 << (BIT_ALL_STAT_MIX_T_GR)) +#define ALL_STAT_HIRES (1 << (BIT_ALL_STAT_HIRES)) +#define ALL_STAT_ANNUNC3 (1 << (BIT_ALL_STAT_ANNUNC3)) +#define ALL_STAT_TEXT_COLOR (0xf << (BIT_ALL_STAT_TEXT_COLOR)) +#define ALL_STAT_BG_COLOR (0xf << (BIT_ALL_STAT_BG_COLOR)) +#define ALL_STAT_ALTCHARSET (1 << (BIT_ALL_STAT_ALTCHARSET)) +#define ALL_STAT_FLASH_STATE (1 << (BIT_ALL_STAT_FLASH_STATE)) +#define ALL_STAT_A2VID_PALETTE (0xf << (BIT_ALL_STAT_A2VID_PALETTE)) + +#ifdef VIDEO_DOUBLEHLINE + #define BORDER_WIDTH 32 +#else + #define BORDER_WIDTH 16 +#endif + + +/* BASE_MARGIN_BOTTOM+MARGIN_TOP must equal 62. There are 262 scan lines */ +/* at 60Hz (15.7KHz line rate) and so we just make 62 border lines */ + +#ifdef VIDEO_DOUBLEVLINE +# define BASE_MARGIN_TOP 32 +# define BASE_MARGIN_BOTTOM 30 +#else +# define BASE_MARGIN_TOP 16 +# define BASE_MARGIN_BOTTOM 15 //was 15 +#endif + +#define BASE_MARGIN_LEFT BORDER_WIDTH +#define BASE_MARGIN_RIGHT BORDER_WIDTH + +#ifdef VIDEO_DOUBLEHLINE +# define EFF_BORDER_WIDTH (BORDER_WIDTH + (640-560)/2) +# define A2_WINDOW_WIDTH 640 +#else +# define EFF_BORDER_WIDTH (BORDER_WIDTH + (320-280)/2) +# define A2_WINDOW_WIDTH 320 +#endif + +#ifdef VIDEO_DOUBLEVLINE +# define A2_WINDOW_HEIGHT 400 +#else +# define A2_WINDOW_HEIGHT (400/2) +#endif + +#define X_A2_WINDOW_WIDTH (A2_WINDOW_WIDTH + BASE_MARGIN_LEFT + \ + BASE_MARGIN_RIGHT) +#define X_A2_WINDOW_HEIGHT (A2_WINDOW_HEIGHT + BASE_MARGIN_TOP + \ + BASE_MARGIN_BOTTOM) + +#define MAX_STATUS_LINES 7 +#define STATUS_LINE_LENGTH 88 + +#define BASE_WINDOW_WIDTH (X_A2_WINDOW_WIDTH) + + +#define A2_BORDER_COLOR_NUM 0xfe + diff --git a/kegs/Src/defs.h b/kegs/Src/defs.h new file mode 100644 index 0000000..f35c42c --- /dev/null +++ b/kegs/Src/defs.h @@ -0,0 +1,59 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_S + .data + .export rcsdif_defs_h,data +rcsdif_defs_h + .stringz "@(#)$KmKId: defs.h,v 1.22 2002-11-19 03:10:38-05 kadickey Exp $" + .code +#endif + +#include "defcomm.h" + +link .reg %r2 +acc .reg %r3 +xreg .reg %r4 +yreg .reg %r5 +stack .reg %r6 +dbank .reg %r7 +direct .reg %r8 +neg .reg %r9 +zero .reg %r10 +psr .reg %r11 +kpc .reg %r12 +const_fd .reg %r13 +instr .reg %r14 +#if 0 +cycles .reg %r13 +kbank .reg %r14 +#endif + +page_info_ptr .reg %r15 +inst_tab_ptr .reg %r16 +fcycles_stop_ptr .reg %r17 +addr_latch .reg %r18 + +scratch1 .reg %r19 +scratch2 .reg %r20 +scratch3 .reg %r21 +scratch4 .reg %r22 +;instr .reg %r23 ; arg3 + +fcycles .reg %fr12 +fr_plus_1 .reg %fr13 +fr_plus_2 .reg %fr14 +fr_plus_3 .reg %fr15 +fr_plus_x_m1 .reg %fr16 +fcycles_stop .reg %fr17 +fcycles_last_dcycs .reg %fr18 + +ftmp1 .reg %fr4 +ftmp2 .reg %fr5 +fscr1 .reg %fr6 + +#define LDC(val,reg) ldil L%val,reg ! ldo R%val(reg),reg + diff --git a/kegs/Src/defs_instr.h b/kegs/Src/defs_instr.h new file mode 100644 index 0000000..5802553 --- /dev/null +++ b/kegs/Src/defs_instr.h @@ -0,0 +1,1621 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef ASM +# ifdef INCLUDE_RCSID_S + .data + .export rcsdif_defs_instr_h,data +rcsdif_defs_instr_h + .stringz "@(#)$KmKId: defs_instr.h,v 1.57 2004-01-10 15:49:14-05 kentd Exp $" + .code +# endif + +# ifdef ACC8 + .export defs_instr_start_8,data +defs_instr_start_8 .word 0 +# else + .export defs_instr_start_16,data +defs_instr_start_16 .word 0 +# endif /* ACC8*/ +#endif /* ASM */ + + +#undef GET_DLOC_X_IND_RD + +#ifdef ASM_INTEL +# ifdef ACC8 +# define GET_DLOC_X_IND_RD() \ + __asm mov esi,arg0 ; + ldb 1(scratch1),arg0 ! \ + GET_DLOC_X_IND_WR() ! \ + bl get_mem_long_8,link ! \ + nop +# else +# define GET_DLOC_X_IND_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_X_IND_WR() ! \ + bl get_mem_long_16,link ! \ + nop +# endif /* ACC8 */ +#else /* C*/ +# ifdef ACC8 +# define GET_DLOC_X_IND_RD() \ + GET_1BYTE_ARG; \ + GET_DLOC_X_IND_WR(); \ + GET_MEMORY8(arg, arg); +# else +# define GET_DLOC_X_IND_RD() \ + GET_1BYTE_ARG; \ + GET_DLOC_X_IND_WR(); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + +#undef GET_DISP8_S_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_DISP8_S_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_WR() ! \ + bl get_mem_b0_8,link ! \ + nop +# else +# define GET_DISP8_S_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_WR() ! \ + bl get_mem_b0_16,link ! \ + nop +# endif +#else /* C */ +# ifdef ACC8 +# define GET_DISP8_S_RD() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_WR(); \ + GET_MEMORY8(arg, arg); +# else +# define GET_DISP8_S_RD() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_WR(); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + + +#ifdef ASM +# define MUST_FIX \ + break +#endif + +#undef GET_DLOC_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_DLOC_RD() \ + ldb 1(scratch1),arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,addr_latch ! \ + extru addr_latch,23,16,arg3 ! \ + CYCLES_PLUS_1 ! \ + ldwx,s arg3(page_info_ptr),scratch2 ! \ + extru addr_latch,31,8,scratch4 ! \ + extru addr_latch,31,16,addr_latch ! \ + ldbx scratch4(scratch2),ret0 ! \ + extru,= scratch2,BANK_IO_BIT,1,0 ! \ + bl get_memory_iocheck_stub_asm,link ! \ + copy addr_latch,arg0 +# else +# define GET_DLOC_RD() \ + ldb 1(scratch1),arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_16,link ! \ + extru arg0,31,16,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define GET_DLOC_RD() \ + GET_1BYTE_ARG; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + GET_MEMORY8((direct + arg) & 0xffff, arg); +# else +# define GET_DLOC_RD() \ + GET_1BYTE_ARG; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + GET_MEMORY16((direct + arg) & 0xffff, arg, 1); +# endif +#endif + + +#undef GET_DLOC_L_IND_RD +#ifdef ASM +# ifdef ACC8 +# define GET_DLOC_L_IND_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_WR() ! \ + bl get_mem_long_8,link ! \ + nop +# else +# define GET_DLOC_L_IND_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_WR() ! \ + bl get_mem_long_16,link ! \ + nop +# endif +#else /* C */ +# ifdef ACC8 +# define GET_DLOC_L_IND_RD() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_WR(); \ + GET_MEMORY8(arg, arg); +# else +# define GET_DLOC_L_IND_RD() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_WR(); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + + +#undef GET_IMM_MEM + +#ifdef ASM +# ifdef ACC8 +# define GET_IMM_MEM() \ + ldb 1(scratch1),ret0 ! \ + INC_KPC_2 +# else +# define GET_IMM_MEM() \ + ldb 2(scratch1),scratch2 ! \ + INC_KPC_3 ! \ + ldb 1(scratch1),ret0 ! \ + CYCLES_PLUS_1 ! \ + dep scratch2,23,8,ret0 +# endif +#else +# ifdef ACC8 +# define GET_IMM_MEM() \ + GET_1BYTE_ARG; \ + INC_KPC_2; +# else +# define GET_IMM_MEM() \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + INC_KPC_3; +# endif +#endif + + +#undef GET_ABS_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_ABS_RD() \ + ldb 2(scratch1),arg3 ! \ + INC_KPC_3 ! \ + ldb 1(scratch1),addr_latch ! \ + CYCLES_PLUS_2 ! \ + dep dbank,23,24,arg3 ! \ + ldwx,s arg3(page_info_ptr),scratch2 ! \ + copy addr_latch,scratch4 ! \ + dep arg3,23,24,addr_latch ! \ + ldbx scratch4(scratch2),ret0 ! \ + extru,= scratch2,BANK_IO_BIT,1,0 ! \ + bl get_memory_iocheck_stub_asm,link ! \ + copy addr_latch,arg0 +# else +# define GET_ABS_RD() \ + ldb 1(scratch1),arg0 ! \ + CYCLES_PLUS_1 ! \ + ldb 2(scratch1),scratch2 ! \ + INC_KPC_3 ! \ + dep dbank,15,16,arg0 ! \ + bl get_mem_long_16,link ! \ + dep scratch2,23,8,arg0 +# endif +#else +# ifdef ACC8 +# define GET_ABS_RD() \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + GET_MEMORY8((dbank << 16) + arg, arg); \ + INC_KPC_3; +# else +# define GET_ABS_RD() \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + GET_MEMORY16((dbank << 16) + arg, arg, 0); \ + INC_KPC_3; +# endif +#endif + + +#undef GET_LONG_RD + + +#ifdef ASM +# ifdef ACC8 +# define GET_LONG_RD() \ + ldb 1(scratch1),arg0 ! \ + INC_KPC_4 ! \ + ldb 2(scratch1),scratch2 ! \ + CYCLES_PLUS_2 ! \ + ldb 3(scratch1),scratch1 ! \ + dep scratch2,23,8,arg0 ! \ + bl get_mem_long_8,link ! \ + dep scratch1,15,8,arg0 +# else +# define GET_LONG_RD() \ + ldb 1(scratch1),arg0 ! \ + INC_KPC_4 ! \ + ldb 2(scratch1),scratch2 ! \ + CYCLES_PLUS_2 ! \ + ldb 3(scratch1),scratch1 ! \ + dep scratch2,23,8,arg0 ! \ + bl get_mem_long_16,link ! \ + dep scratch1,15,8,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define GET_LONG_RD() \ + GET_3BYTE_ARG; \ + CYCLES_PLUS_2; \ + GET_MEMORY8(arg, arg); \ + INC_KPC_4; +# else +# define GET_LONG_RD() \ + GET_3BYTE_ARG; \ + CYCLES_PLUS_2; \ + GET_MEMORY16(arg, arg, 0); \ + INC_KPC_4; +# endif +#endif + + + +#undef GET_DLOC_IND_Y_RD + +#undef GET_DLOC_IND_Y_WR_SPECIAL2 + +#define GET_DLOC_IND_Y_WR_SPECIAL2() \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + dep dbank,15,8,ret0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + add yreg,ret0,arg0 /* don't change this instr */ + /* or add any after */ + /* to preserve ret0 & arg0 */ + + +#ifdef ASM +# ifdef ACC8 +# define GET_DLOC_IND_Y_RD() \ + ldb 1(scratch1),arg0 ! \ + INC_KPC_2 ! \ + GET_DLOC_IND_Y_WR_SPECIAL2() ! \ + xor arg0,ret0,scratch1 ! \ + extru,= psr,27,1,0 ! \ + extru,= scratch1,23,8,0 ! \ + CYCLES_PLUS_1 ! \ + bl get_mem_long_8,link ! \ + nop +# else +# define GET_DLOC_IND_Y_RD() \ + ldb 1(scratch1),arg0 ! \ + INC_KPC_2 ! \ + GET_DLOC_IND_Y_WR_SPECIAL2() ! \ + xor arg0,ret0,scratch1 ! \ + extru,= psr,27,1,0 ! \ + extru,= scratch1,23,8,0 ! \ + CYCLES_PLUS_1 ! \ + bl get_mem_long_16,link ! \ + nop +# endif +#else /* C */ +# ifdef ACC8 +# define GET_DLOC_IND_Y_RD() \ + GET_1BYTE_ARG; \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, tmp1); \ + tmp1 += (dbank << 16); \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + tmp2 = tmp1 + yreg; \ + if(((psr & 0x10) == 0) || ((tmp1 ^ tmp2) & 0xff00)) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + GET_MEMORY8(tmp2, arg); +# else +# define GET_DLOC_IND_Y_RD() \ + GET_1BYTE_ARG; \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, tmp1); \ + tmp1 += (dbank << 16); \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + tmp2 = tmp1 + yreg; \ + if(((psr & 0x10) == 0) || ((tmp1 ^ tmp2) & 0xff00)) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + GET_MEMORY16(tmp2, arg, 0); +# endif +#endif + + +#undef GET_DLOC_IND_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_DLOC_IND_RD() \ + ldb 1(scratch1),arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 ! \ + bl get_mem_long_8,link ! \ + dep dbank,15,16,arg0 +# else +# define GET_DLOC_IND_RD() \ + ldb 1(scratch1),arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 ! \ + bl get_mem_long_16,link ! \ + dep dbank,15,16,arg0 +# endif +#else +# ifdef ACC8 +# define GET_DLOC_IND_RD() \ + GET_1BYTE_ARG; \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, arg); \ + GET_MEMORY8((dbank << 16) + arg, arg); +# else +# define GET_DLOC_IND_RD() \ + GET_1BYTE_ARG; \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, arg); \ + GET_MEMORY16((dbank << 16) + arg, arg, 0); +# endif +#endif + + +#undef GET_DLOC_X_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_DLOC_X_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_INDEX_WR_A(xreg) ! \ + bl get_mem_b0_8,link ! \ + GET_DLOC_INDEX_WR_B(xreg) +# else +# define GET_DLOC_X_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_INDEX_WR_A(xreg) ! \ + bl get_mem_b0_16,link ! \ + GET_DLOC_INDEX_WR_B(xreg) +# endif +#else +# ifdef ACC8 +# define GET_DLOC_X_RD() \ + GET_1BYTE_ARG; \ + CYCLES_PLUS_1; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + arg = (arg + xreg + direct) & 0xffff; \ + if(psr & 0x100) { \ + if((direct & 0xff) == 0) { \ + arg = (direct & 0xff00) | (arg & 0xff); \ + } \ + } \ + GET_MEMORY8(arg & 0xffff, arg); +# else +# define GET_DLOC_X_RD() \ + GET_1BYTE_ARG; \ + CYCLES_PLUS_1; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + arg = (arg + xreg + direct) & 0xffff; \ + if(psr & 0x100) { \ + if((direct & 0xff) == 0) { \ + arg = (direct & 0xff00) | (arg & 0xff); \ + } \ + } \ + GET_MEMORY16(arg, arg, 1); +# endif +#endif + + +#undef GET_DISP8_S_IND_Y_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_DISP8_S_IND_Y_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_IND_Y_WR() ! \ + bl get_mem_long_8,link ! \ + nop +# else +# define GET_DISP8_S_IND_Y_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_IND_Y_WR() ! \ + bl get_mem_long_16,link ! \ + nop +# endif +#else +# ifdef ACC8 +# define GET_DISP8_S_IND_Y_RD() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_IND_Y_WR(); \ + GET_MEMORY8(arg, arg); +# else +# define GET_DISP8_S_IND_Y_RD() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_IND_Y_WR(); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + + +#undef GET_DLOC_L_IND_Y_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_DLOC_L_IND_Y_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_Y_WR() ! \ + bl get_mem_long_8,link ! \ + nop +# else +# define GET_DLOC_L_IND_Y_RD() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_Y_WR() ! \ + bl get_mem_long_16,link ! \ + nop +# endif +#else /* C */ +# ifdef ACC8 +# define GET_DLOC_L_IND_Y_RD() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_Y_WR(); \ + GET_MEMORY8(arg, arg); +# else +# define GET_DLOC_L_IND_Y_RD() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_Y_WR(); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + + +#undef GET_ABS_INDEX_ADDR_FOR_RD + +#ifdef ASM +/* to get cycle right: add 1 cycle */ +/* if (x is 16bit) || (carry into high byte), add another cycle */ +/* So, if x==16bit, add 1. If x==8bit then add 1 if carry */ +# define GET_ABS_INDEX_ADDR_FOR_RD(index_reg) \ + ldb 1(scratch1),ret0 ! \ + CYCLES_PLUS_1 ! \ + ldb 2(scratch1),scratch1 ! \ + dep dbank,15,16,ret0 ! \ + INC_KPC_3 ! \ + dep scratch1,23,8,ret0 ! \ + add ret0,index_reg,arg0 ! \ + xor arg0,ret0,scratch1 ! \ + extru,= psr,27,1,0 ! \ + extru,= scratch1,23,8,0 ! \ + CYCLES_PLUS_1 +#else /* C */ +# define GET_ABS_INDEX_ADDR_FOR_RD(index_reg) \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + INC_KPC_3; \ + tmp1 = (dbank << 16) + arg; \ + arg = tmp1 + index_reg; \ + if(((psr & 0x10) == 0) || ((tmp1 ^ arg) & 0xff00)) { \ + CYCLES_PLUS_1; \ + } +#endif + +#undef GET_ABS_Y_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_ABS_Y_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(yreg) ! \ + bl get_mem_long_8,link ! \ + extru arg0,31,24,arg0 +# else +# define GET_ABS_Y_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(yreg) ! \ + bl get_mem_long_16,link ! \ + extru arg0,31,24,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define GET_ABS_Y_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(yreg); \ + GET_MEMORY8(arg, arg); +# else +# define GET_ABS_Y_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(yreg); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + + + + +#undef GET_ABS_X_RD +#undef GET_ABS_X_RD_WR + +#ifdef ASM +# ifdef ACC8 +# define GET_ABS_X_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(xreg) ! \ + bl get_mem_long_8,link ! \ + extru arg0,31,24,arg0 + +# define GET_ABS_X_RD_WR() \ + ldb 1(scratch1),ret0 ! \ + INC_KPC_3 ! \ + ldb 2(scratch1),scratch1 ! \ + dep dbank,15,16,ret0 ! \ + CYCLES_PLUS_2 ! \ + dep scratch1,23,8,ret0 ! \ + add ret0,xreg,arg0 ! \ + bl get_mem_long_8,link ! \ + extru arg0,31,24,arg0 +# else +# define GET_ABS_X_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(xreg) ! \ + bl get_mem_long_16,link ! \ + extru arg0,31,24,arg0 + +# define GET_ABS_X_RD_WR() \ + ldb 1(scratch1),ret0 ! \ + INC_KPC_3 ! \ + ldb 2(scratch1),scratch1 ! \ + dep dbank,15,16,ret0 ! \ + CYCLES_PLUS_2 ! \ + dep scratch1,23,8,ret0 ! \ + add ret0,xreg,arg0 ! \ + bl get_mem_long_16,link ! \ + extru arg0,31,24,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define GET_ABS_X_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(xreg); \ + GET_MEMORY8(arg, arg); + +# define GET_ABS_X_RD_WR() \ + GET_2BYTE_ARG; \ + INC_KPC_3; \ + CYCLES_PLUS_2; \ + arg = (dbank << 16) + ((arg + xreg) & 0xffff); \ + GET_MEMORY8(arg, arg); +# else +# define GET_ABS_X_RD() \ + GET_ABS_INDEX_ADDR_FOR_RD(xreg); \ + GET_MEMORY16(arg, arg, 0); + +# define GET_ABS_X_RD_WR() \ + GET_2BYTE_ARG; \ + INC_KPC_3; \ + CYCLES_PLUS_2; \ + arg = (dbank << 16) + ((arg + xreg) & 0xffff); \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + + +#undef GET_LONG_X_RD + +#ifdef ASM +# ifdef ACC8 +# define GET_LONG_X_RD() \ + ldb 1(scratch1),ret0 ! \ + ldb 2(scratch1),scratch2 ! \ + CYCLES_PLUS_2 ! \ + ldb 3(scratch1),scratch1 ! \ + INC_KPC_4 ! \ + dep scratch2,23,8,ret0 ! \ + dep scratch1,15,8,ret0 ! \ + add ret0,xreg,arg0 ! \ + bl get_mem_long_8,link ! \ + extru arg0,31,24,arg0 +# else +# define GET_LONG_X_RD() \ + ldb 1(scratch1),ret0 ! \ + ldb 2(scratch1),scratch2 ! \ + CYCLES_PLUS_2 ! \ + ldb 3(scratch1),scratch1 ! \ + INC_KPC_4 ! \ + dep scratch2,23,8,ret0 ! \ + dep scratch1,15,8,ret0 ! \ + add ret0,xreg,arg0 ! \ + bl get_mem_long_16,link ! \ + extru arg0,31,24,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define GET_LONG_X_RD() \ + GET_3BYTE_ARG; \ + arg = (arg + xreg) & 0xffffff; \ + INC_KPC_4; \ + CYCLES_PLUS_2; \ + GET_MEMORY8(arg, arg); +# else +# define GET_LONG_X_RD() \ + GET_3BYTE_ARG; \ + arg = (arg + xreg) & 0xffffff; \ + INC_KPC_4; \ + CYCLES_PLUS_2; \ + GET_MEMORY16(arg, arg, 0); +# endif +#endif + +#undef SET_NEG_ZERO16 +#define SET_NEG_ZERO16(val) \ + zero = val; \ + neg = (val) >> 15; + +# define SET_NEG_ZERO8(val) \ + zero = val; \ + neg = (val) >> 7; + +#define SET_CARRY8(val) \ + psr = (psr & ~1) + (((val) >> 8) & 1); + +#define SET_CARRY16(val) \ + psr = (psr & ~1) + (((val) >> 16) & 1); + +#if 0 +# define NEGZERO8(val) SET_NEG_ZERO8(val) +#else +# define NEGZERO16(val) SET_NEG_ZERO16(val) +#endif + +#undef SET_INDEX_REG +#define SET_INDEX_REG(src, dest) \ + if(psr & 0x10) { \ + dest = (src) & 0xff; \ + SET_NEG_ZERO8(dest); \ + } else { \ + dest = (src) & 0xffff; \ + SET_NEG_ZERO16(dest); \ + } + +#define LD_INDEX_INST(index_reg, in_bank) \ + if(psr & 0x10) { \ + GET_MEMORY8(arg, arg); \ + } else { \ + GET_MEMORY16(arg, arg, in_bank);\ + } \ + SET_INDEX_REG(arg, index_reg); + +#define LDX_INST(in_bank) LD_INDEX_INST(xreg, in_bank) +#define LDY_INST(in_bank) LD_INDEX_INST(yreg, in_bank) + +#undef ORA_INST + +#ifdef ASM +# ifdef ACC8 +# define ORA_INST() \ + ldi 0xff,scratch1 ! \ + or acc,ret0,arg0 ! \ + and arg0,scratch1,zero ! \ + extru arg0,24,1,neg ! \ + b dispatch ! \ + dep arg0,31,8,acc +# else +# define ORA_INST() \ + zdepi -1,31,16,scratch1 ! \ + or acc,ret0,arg0 ! \ + and arg0,scratch1,zero ! \ + extru arg0,16,1,neg ! \ + b dispatch ! \ + dep arg0,31,16,acc +# endif +#else /* C */ +# ifdef ACC8 +# define ORA_INST() \ + tmp1 = (acc | arg) & 0xff; \ + acc = (acc & 0xff00) + tmp1; \ + SET_NEG_ZERO8(tmp1); +# else +# define ORA_INST() \ + acc = (acc | arg); \ + SET_NEG_ZERO16(acc); +# endif +#endif + +#undef AND_INST + +#ifdef ASM +# ifdef ACC8 +# define AND_INST() \ + ldi 0xff,scratch1 ! \ + and acc,ret0,arg0 ! \ + and arg0,scratch1,zero ! \ + extru arg0,24,1,neg ! \ + b dispatch ! \ + dep arg0,31,8,acc +# else +# define AND_INST() \ + zdepi -1,31,16,scratch1 ! \ + and acc,ret0,arg0 ! \ + and arg0,scratch1,zero ! \ + extru arg0,16,1,neg ! \ + b dispatch ! \ + dep arg0,31,16,acc +# endif +#else /* C */ +# ifdef ACC8 +# define AND_INST() \ + tmp1 = (acc & arg) & 0xff; \ + acc = (acc & 0xff00) + tmp1; \ + SET_NEG_ZERO8(tmp1); +# else +# define AND_INST() \ + acc = (acc & arg); \ + SET_NEG_ZERO16(acc); +# endif +#endif + +#undef EOR_INST + +#ifdef ASM +# ifdef ACC8 +# define EOR_INST() \ + ldi 0xff,scratch1 ! \ + xor acc,ret0,arg0 ! \ + and arg0,scratch1,zero ! \ + extru arg0,24,1,neg ! \ + b dispatch ! \ + dep arg0,31,8,acc +# else +# define EOR_INST() \ + zdepi -1,31,16,scratch1 ! \ + xor acc,ret0,arg0 ! \ + and arg0,scratch1,zero ! \ + extru arg0,16,1,neg ! \ + b dispatch ! \ + dep arg0,31,16,acc +# endif +#else /* C */ +# ifdef ACC8 +# define EOR_INST() \ + tmp1 = (acc ^ arg) & 0xff; \ + acc = (acc & 0xff00) + tmp1; \ + SET_NEG_ZERO8(tmp1); +# else +# define EOR_INST() \ + acc = (acc ^ arg); \ + SET_NEG_ZERO16(acc); +# endif +#endif + +# undef LDA_INST + +#ifdef ASM +# ifdef ACC8 +# define LDA_INST() \ + extru ret0,31,8,zero ! \ + extru ret0,24,1,neg ! \ + b dispatch ! \ + dep zero,31,8,acc +# else +# define LDA_INST() \ + extru ret0,31,16,zero ! \ + extru ret0,16,1,neg ! \ + b dispatch ! \ + dep zero,31,16,acc +# endif +#else /* C*/ +# ifdef ACC8 +# define LDA_INST() \ + acc = (acc & 0xff00) + (arg & 0xff); \ + SET_NEG_ZERO8(arg & 0xff); +# else +# define LDA_INST() \ + acc = (arg & 0xffff); \ + SET_NEG_ZERO16(acc); +# endif +#endif + +# undef ADC_INST + +#ifdef ASM +# ifdef ACC8 +# define ADC_INST() \ + b adc_binary_8 ! \ + extru acc,31,8,arg0 +# else +# define ADC_INST() \ + b adc_binary_16 ! \ + extru acc,31,16,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define ADC_INST() \ + tmp1 = do_adc_sbc8(acc & 0xff, arg & 0xff, psr, 0); \ + acc = (acc & 0xff00) + (tmp1 & 0xff); \ + psr = (tmp1 >> 16); \ + zero = !(psr & 0x2); \ + neg = (psr >> 7) & 1; +# else +# define ADC_INST() \ + tmp1 = do_adc_sbc16(acc, arg & 0xffff, psr, 0); \ + acc = (tmp1 & 0xffff); \ + psr = (tmp1 >> 16); \ + zero = !(psr & 0x2); \ + neg = (psr >> 7) & 1; +# endif +#endif + + +# undef SBC_INST + +#ifdef ASM +# ifdef ACC8 +# define SBC_INST() \ + uaddcm 0,ret0,ret0 ! \ + b sbc_binary_8 ! \ + extru acc,31,8,arg0 +# else +# define SBC_INST() \ + uaddcm 0,ret0,ret0 ! \ + b sbc_binary_16 ! \ + extru acc,31,16,arg0 +# endif +#else /* C */ +# ifdef ACC8 +# define SBC_INST() \ + tmp1 = do_adc_sbc8(acc & 0xff, arg & 0xff, psr, 1); \ + acc = (acc & 0xff00) + (tmp1 & 0xff); \ + psr = (tmp1 >> 16); \ + zero = !(psr & 0x2); \ + neg = (psr >> 7) & 1; +# else +# define SBC_INST() \ + tmp1 = do_adc_sbc16(acc, arg & 0xffff, psr, 1); \ + acc = (tmp1 & 0xffff); \ + psr = (tmp1 >> 16); \ + zero = !(psr & 0x2); \ + neg = (psr >> 7) & 1; +# endif +#endif + + +# undef CMP_INST + +#ifdef ASM +# ifdef ACC8 +# define CMP_INST() ! \ + extru acc,31,8,scratch1 ! \ + subi 0x100,ret0,ret0 ! \ + ldi 0xff,scratch2 ! \ + add ret0,scratch1,ret0 ! \ + extru ret0,23,1,scratch1 ! \ + and ret0,scratch2,zero ! \ + extru ret0,24,1,neg ! \ + b dispatch ! \ + dep scratch1,31,1,psr +# else +# define CMP_INST() ! \ + ldil l%0x10000,scratch3 ! \ + zdepi -1,31,16,scratch2 ! \ + sub scratch3,ret0,ret0 ! \ + add ret0,acc,ret0 ! \ + extru ret0,15,1,scratch1 ! \ + and ret0,scratch2,zero ! \ + extru ret0,16,1,neg ! \ + b dispatch ! \ + dep scratch1,31,1,psr +# endif +#else /* C */ +# ifdef ACC8 +# define CMP_INST() \ + arg = (acc & 0xff) + (0x100 - arg); \ + SET_CARRY8(arg); \ + arg = arg & 0xff; \ + SET_NEG_ZERO8(arg & 0xff); +# else +# define CMP_INST() \ + arg = (acc & 0xffff) + (0x10000 - arg); \ + SET_CARRY16(arg); \ + arg = arg & 0xffff; \ + SET_NEG_ZERO16(arg & 0xffff); +# endif +#endif + +# undef BIT_INST + +#ifdef ASM +# ifdef ACC8 +# define BIT_INST() \ + ldi 0xff,scratch1 ! \ + and acc,ret0,arg0 ! \ + extru ret0,24,1,neg ! \ + and arg0,scratch1,zero ! \ + extru ret0,25,1,scratch2 ! \ + b dispatch ! \ + dep scratch2,25,1,psr +# else +# define BIT_INST() \ + zdepi -1,31,16,scratch1 ! \ + and acc,ret0,arg0 ! \ + extru ret0,16,1,neg ! \ + and arg0,scratch1,zero ! \ + extru ret0,17,1,scratch2 ! \ + b dispatch ! \ + dep scratch2,25,1,psr +# endif +#else /* C */ +# ifdef ACC8 +# define BIT_INST() \ + neg = arg >> 7; \ + zero = (acc & arg & 0xff); \ + psr = (psr & (~0x40)) | (arg & 0x40); +# else +# define BIT_INST() \ + neg = arg >> 15; \ + zero = (acc & arg & 0xffff); \ + psr = (psr & (~0x40)) | ((arg >> 8) & 0x40); +# endif +#endif + +# undef STA_INST + +#ifdef ASM +# ifdef ACC8 +# define STA_INST() \ + extru acc,31,8,arg1 ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +# define STA_INST() \ + extru acc,31,16,arg1 ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C*/ +# ifdef ACC8 +# define STA_INST(in_bank) \ + SET_MEMORY8(arg, acc); +# else +# define STA_INST(in_bank) \ + SET_MEMORY16(arg, acc, in_bank); +# endif +#endif + + +#undef TSB_INST + +#ifdef ASM +# ifdef ACC8 +/* Uses addr_latch as full apple addr to write data to */ +# define TSB_INST() \ + or acc,ret0,arg1 ! \ + CYCLES_PLUS_1 ! \ + extru arg1,31,8,arg1 ! \ + and ret0,acc,zero ! \ + copy addr_latch,arg0 ! \ + extru zero,31,8,zero ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +/* Uses addr_latch as full apple addr to write data to */ +# define TSB_INST() \ + or acc,ret0,arg1 ! \ + CYCLES_PLUS_1 ! \ + extru arg1,31,16,arg1 ! \ + and ret0,acc,zero ! \ + copy addr_latch,arg0 ! \ + extru zero,31,16,zero ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C*/ +# ifdef ACC8 +# define TSB_INST(in_bank) \ + tmp1 = arg | acc; \ + CYCLES_PLUS_1; \ + zero = arg & acc; \ + SET_MEMORY8(addr_latch, tmp1); +# else +# define TSB_INST(in_bank) \ + tmp1 = arg | acc; \ + CYCLES_PLUS_1; \ + zero = arg & acc; \ + SET_MEMORY16(addr_latch, tmp1, in_bank); +# endif +#endif + + +#undef ASL_INST + +#ifdef ASM +# ifdef ACC8 +/* Uses addr_latch as full apple addr to write data to */ +# define ASL_INST() \ + ldi 0xff,scratch1 ! \ + copy addr_latch,arg0 ! \ + sh1add ret0,0,scratch3 ! \ + CYCLES_PLUS_1 ! \ + extru scratch3,24,1,neg ! \ + and scratch3,scratch1,zero ! \ + extru scratch3,23,1,scratch2 ! \ + copy zero,arg1 ! \ + dep scratch2,31,1,psr /* set carry */ ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +/* Uses addr_latch as full apple addr to write data to */ +# define ASL_INST() \ + zdepi -1,31,16,scratch1 ! \ + copy addr_latch,arg0 ! \ + sh1add ret0,0,scratch3 ! \ + CYCLES_PLUS_1 ! \ + extru scratch3,16,1,neg ! \ + and scratch3,scratch1,zero ! \ + extru scratch3,15,1,scratch2 ! \ + copy zero,arg1 ! \ + dep scratch2,31,1,psr /* set carry */ ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define ASL_INST(in_bank) \ + psr = (psr & 0x1fe) + ((arg >> 7) & 1); \ + tmp1 = (arg << 1) & 0xff; \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO8(tmp1); \ + SET_MEMORY8(addr_latch, tmp1); +# else +# define ASL_INST(in_bank) \ + psr = (psr & 0x1fe) + ((arg >> 15) & 1);\ + tmp1 = (arg << 1) & 0xffff; \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO16(tmp1); \ + SET_MEMORY16(addr_latch, tmp1, in_bank); +# endif +#endif + +# undef ROL_INST + +#ifdef ASM +# ifdef ACC8 +/* Uses addr_latch as full apple addr to write data to */ +# define ROL_INST() \ + extru psr,31,1,scratch2 ! \ + ldi 0xff,scratch1 ! \ + copy addr_latch,arg0 ! \ + sh1add ret0,scratch2,scratch3 ! \ + CYCLES_PLUS_1 ! \ + extru scratch3,24,1,neg ! \ + and scratch3,scratch1,zero ! \ + extru scratch3,23,1,scratch2 ! \ + copy zero,arg1 ! \ + dep scratch2,31,1,psr /* set carry */ ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +/* Uses addr_latch as full apple addr to write data to */ +# define ROL_INST() \ + extru psr,31,1,scratch2 ! \ + copy addr_latch,arg0 ! \ + zdepi -1,31,16,scratch1 ! \ + sh1add ret0,scratch2,scratch3 ! \ + CYCLES_PLUS_1 ! \ + extru scratch3,16,1,neg ! \ + and scratch3,scratch1,zero ! \ + extru scratch3,15,1,scratch2 ! \ + copy zero,arg1 ! \ + dep scratch2,31,1,psr /* set carry */ ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define ROL_INST(in_bank) \ + arg = (arg << 1) | (psr & 1); \ + SET_MEMORY8(addr_latch, arg); \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO8(arg & 0xff); \ + SET_CARRY8(arg); +# else +# define ROL_INST(in_bank) \ + arg = (arg << 1) | (psr & 1); \ + SET_MEMORY16(addr_latch, arg, in_bank); \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO16(arg & 0xffff); \ + SET_CARRY16(arg); +# endif +#endif + +# undef LSR_INST + +#ifdef ASM +# ifdef ACC8 +/* Uses addr_latch as full apple addr to write data to */ +# define LSR_INST() \ + copy addr_latch,arg0 ! \ + extru ret0,30,7,zero ! \ + CYCLES_PLUS_1 ! \ + ldi 0,neg ! \ + dep ret0,31,1,psr /* set carry */ ! \ + copy zero,arg1 ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +/* Uses addr_latch as full apple addr to write data to */ +# define LSR_INST() \ + copy addr_latch,arg0 ! \ + extru ret0,30,15,zero ! \ + CYCLES_PLUS_1 ! \ + ldi 0,neg ! \ + dep ret0,31,1,psr /* set carry */ ! \ + copy zero,arg1 ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define LSR_INST(in_bank) \ + SET_CARRY8(arg << 8); \ + arg = (arg >> 1) & 0x7f; \ + SET_MEMORY8(addr_latch, arg); \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO8(arg); +# else +# define LSR_INST(in_bank) \ + SET_CARRY16(arg << 16); \ + arg = (arg >> 1) & 0x7fff; \ + SET_MEMORY16(addr_latch, arg, in_bank); \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO16(arg); +# endif +#endif + + +# undef ROR_INST + +#ifdef ASM +# ifdef ACC8 +# define ROR_INST() ! \ + extru psr,31,1,neg ! \ + copy addr_latch,arg0 ! \ + extru ret0,30,7,zero ! \ + CYCLES_PLUS_1 ! \ + dep neg,24,1,zero ! \ + copy zero,arg1 ! \ + dep ret0,31,1,psr ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +# define ROR_INST() ! \ + extru psr,31,1,neg ! \ + copy addr_latch,arg0 ! \ + extru ret0,30,15,zero ! \ + CYCLES_PLUS_1 ! \ + dep neg,16,1,zero ! \ + copy zero,arg1 ! \ + dep ret0,31,1,psr ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define ROR_INST(in_bank) \ + tmp1 = psr & 1; \ + SET_CARRY8(arg << 8); \ + arg = ((arg >> 1) & 0x7f) | (tmp1 << 7); \ + SET_MEMORY8(addr_latch, arg); \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO8(arg); +# else +# define ROR_INST(in_bank) \ + tmp1 = psr & 1; \ + SET_CARRY16(arg << 16); \ + arg = ((arg >> 1) & 0x7fff) | (tmp1 << 15); \ + SET_MEMORY16(addr_latch, arg, in_bank); \ + CYCLES_PLUS_1; \ + SET_NEG_ZERO16(arg); +# endif +#endif + +# undef TRB_INST + +#ifdef ASM +# ifdef ACC8 +/* Uses addr_latch as full apple addr to write data to */ +# define TRB_INST() \ + andcm ret0,acc,arg1 ! \ + copy addr_latch,arg0 ! \ + and ret0,acc,zero ! \ + extru arg1,31,8,arg1 ! \ + CYCLES_PLUS_1 ! \ + extru zero,31,8,zero ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +/* Uses addr_latch as full apple addr to write data to */ +# define TRB_INST() \ + andcm ret0,acc,arg1 ! \ + CYCLES_PLUS_1 ! \ + extru arg1,31,16,arg1 ! \ + and ret0,acc,zero ! \ + copy addr_latch,arg0 ! \ + extru zero,31,16,zero ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define TRB_INST(in_bank) \ + arg = arg & 0xff; \ + tmp1 = arg & ~acc; \ + CYCLES_PLUS_1; \ + zero = arg & acc; \ + SET_MEMORY8(addr_latch, tmp1); +# else +# define TRB_INST(in_bank) \ + tmp1 = arg & ~acc; \ + CYCLES_PLUS_1; \ + zero = arg & acc; \ + SET_MEMORY16(addr_latch, tmp1, in_bank); +# endif +#endif + +# undef DEC_INST + +#ifdef ASM +# ifdef ACC8 +# define DEC_INST() ! \ + addi -1,ret0,ret0 ! \ + copy addr_latch,arg0 ! \ + extru ret0,24,1,neg ! \ + CYCLES_PLUS_1 ! \ + extru ret0,31,8,zero ! \ + ldil l%dispatch,link ! \ + copy zero,arg1 ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +# define DEC_INST() ! \ + addi -1,ret0,ret0 ! \ + copy addr_latch,arg0 ! \ + extru ret0,16,1,neg ! \ + CYCLES_PLUS_1 ! \ + extru ret0,31,16,zero ! \ + ldil l%dispatch,link ! \ + copy zero,arg1 ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define DEC_INST(in_bank) \ + CYCLES_PLUS_1; \ + arg = (arg - 1) & 0xff; \ + SET_MEMORY8(addr_latch, arg); \ + SET_NEG_ZERO8(arg); +# else +# define DEC_INST(in_bank) \ + CYCLES_PLUS_1; \ + arg = (arg - 1) & 0xffff; \ + SET_MEMORY16(addr_latch, arg, in_bank); \ + SET_NEG_ZERO16(arg); +# endif +#endif + + +# undef INC_INST + +#ifdef ASM +# ifdef ACC8 +# define INC_INST() ! \ + addi 1,ret0,ret0 ! \ + copy addr_latch,arg0 ! \ + extru ret0,24,1,neg ! \ + CYCLES_PLUS_1 ! \ + extru ret0,31,8,zero ! \ + ldil l%dispatch,link ! \ + copy zero,arg1 ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +# define INC_INST() ! \ + addi 1,ret0,ret0 ! \ + copy addr_latch,arg0 ! \ + extru ret0,16,1,neg ! \ + CYCLES_PLUS_1 ! \ + extru ret0,31,16,zero ! \ + ldil l%dispatch,link ! \ + copy zero,arg1 ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define INC_INST(in_bank) \ + CYCLES_PLUS_1; \ + arg = (arg + 1) & 0xff; \ + SET_MEMORY8(addr_latch, arg); \ + SET_NEG_ZERO8(arg); +# else +# define INC_INST(in_bank) \ + CYCLES_PLUS_1; \ + arg = (arg + 1) & 0xffff; \ + SET_MEMORY16(addr_latch, arg, in_bank); \ + SET_NEG_ZERO16(arg); +# endif +#endif + +# undef STZ_INST + +#ifdef ASM +# ifdef ACC8 +# define STZ_INST() \ + ldi 0,arg1 ! \ + ldil l%dispatch,link ! \ + b set_mem_long_8 ! \ + ldo r%dispatch(link),link +# else +# define STZ_INST() \ + ldi 0,arg1 ! \ + ldil l%dispatch,link ! \ + b set_mem_long_16 ! \ + ldo r%dispatch(link),link +# endif +#else /* C */ +# ifdef ACC8 +# define STZ_INST(in_bank) \ + SET_MEMORY8(arg, 0); +# else +# define STZ_INST(in_bank) \ + SET_MEMORY16(arg, 0, in_bank); +# endif +#endif + + +#undef COND_BR1 +#undef COND_BR2 +#undef COND_BR_UNTAKEN + +#ifdef ASM +# define COND_BR1 \ + ldb 1(scratch1),arg0 + +/* be careful about modifying kpc as first instr of COND_Br2 since it */ +/* is in the delay slot of a branch! */ +# define COND_BR2 \ + addi 2,kpc,scratch3 ! \ + ldi 0x100,scratch4 ! \ + extrs arg0,31,8,ret0 ! \ + and scratch4,psr,scratch4 ! \ + add scratch3,ret0,ret0 ! \ + CYCLES_PLUS_1 ! \ + xor scratch3,ret0,scratch3 ! \ + and,= scratch4,scratch3,0 ! \ + CYCLES_PLUS_1 ! \ + b dispatch ! \ + dep ret0,31,16,kpc + + +# define COND_BR_UNTAKEN \ + b dispatch ! \ + INC_KPC_2 +#else /* C */ +#undef BRANCH_DISP8 +# define BRANCH_DISP8(cond) \ + GET_1BYTE_ARG; \ + tmp2 = kpc & 0xff0000; \ + kpc += 2; \ + tmp1 = kpc; \ + if(cond) { \ + kpc = kpc + arg - ((arg & 0x80) << 1); \ + CYCLES_PLUS_1; \ + if((tmp1 ^ kpc) & psr & 0x100) { \ + CYCLES_PLUS_1; \ + } \ + } \ + kpc = tmp2 + (kpc & 0xffff); +#endif + +#undef STY_INST +#undef STX_INST + +#ifdef ASM +# define STY_INST() \ + ldil l%dispatch,link ! \ + b set_mem_yreg ! \ + ldo r%dispatch(link),link + +# define STX_INST() \ + ldil l%dispatch,link ! \ + b set_mem_xreg ! \ + ldo r%dispatch(link),link +#else /* C */ +# define STY_INST(in_bank) \ + if(psr & 0x10) { \ + SET_MEMORY8(arg, yreg); \ + } else { \ + SET_MEMORY16(arg, yreg, in_bank);\ + } +# define STX_INST(in_bank) \ + if(psr & 0x10) { \ + SET_MEMORY8(arg, xreg); \ + } else { \ + SET_MEMORY16(arg, xreg, in_bank);\ + } +#endif + +#ifndef ASM +#undef C_LDX_ABS_Y +# define C_LDX_ABS_Y() \ + GET_ABS_INDEX_ADDR_FOR_RD(yreg); \ + LDX_INST(0); +#undef C_LDY_ABS_X +# define C_LDY_ABS_X() \ + GET_ABS_INDEX_ADDR_FOR_RD(xreg); \ + LDY_INST(0); +#undef C_LDX_ABS +# define C_LDX_ABS() \ + GET_ABS_ADDR(); \ + LDX_INST(0); +#undef C_LDY_ABS +# define C_LDY_ABS() \ + GET_ABS_ADDR(); \ + LDY_INST(0); +#undef C_LDX_DLOC +# define C_LDX_DLOC() \ + GET_DLOC_ADDR(); \ + LDX_INST(1); +#undef C_LDY_DLOC +# define C_LDY_DLOC() \ + GET_DLOC_ADDR(); \ + LDY_INST(1); +#undef C_LDY_DLOC_X +# define C_LDY_DLOC_X() \ + GET_DLOC_X_ADDR(); \ + LDY_INST(1); +#undef C_LDX_DLOC_Y +# define C_LDX_DLOC_Y() \ + GET_DLOC_Y_ADDR(); \ + LDX_INST(1); + +# define CP_INDEX_VAL(index_reg) \ + arg = 0x100 - arg + index_reg; \ + if((psr & 0x10) == 0) { \ + arg += 0xff00; \ + SET_NEG_ZERO16(arg & 0xffff); \ + SET_CARRY16(arg); \ + } else { \ + SET_NEG_ZERO8(arg & 0xff);\ + SET_CARRY8(arg); \ + } + +# define CP_INDEX_LOAD(index_reg, in_bank) \ + if((psr & 0x10) != 0) { \ + GET_MEMORY8(arg, arg); \ + } else { \ + GET_MEMORY16(arg, arg, in_bank);\ + } \ + CP_INDEX_VAL(index_reg) + +# define CPX_INST(in_bank) \ + CP_INDEX_LOAD(xreg, in_bank); + +# define CPY_INST(in_bank) \ + CP_INDEX_LOAD(yreg, in_bank); +#undef C_CPX_IMM +# define C_CPX_IMM() \ + INC_KPC_2; \ + if((psr & 0x10) == 0) { \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + INC_KPC_1; \ + } else { \ + GET_1BYTE_ARG; \ + } \ + CP_INDEX_VAL(xreg); +#undef C_CPY_IMM +# define C_CPY_IMM() \ + INC_KPC_2; \ + if((psr & 0x10) == 0) { \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + INC_KPC_1; \ + } else { \ + GET_1BYTE_ARG; \ + } \ + CP_INDEX_VAL(yreg); +#undef C_CPX_DLOC +# define C_CPX_DLOC() \ + GET_DLOC_ADDR(); \ + CPX_INST(1); +#undef C_CPY_DLOC +# define C_CPY_DLOC() \ + GET_DLOC_ADDR(); \ + CPY_INST(1); +#undef C_CPX_ABS +# define C_CPX_ABS() \ + GET_ABS_ADDR(); \ + CPX_INST(0); +#undef C_CPY_ABS +# define C_CPY_ABS() \ + GET_ABS_ADDR(); \ + CPY_INST(0); + +#endif + + + + +/* This is here to make sure all the macros expand to no instrs */ +/* if defs_instr_end_8 - start != 0, then something did expand */ + +#ifdef ASM +# ifdef ACC8 + .export defs_instr_end_8,data +defs_instr_end_8 .word 0 +# else + .export defs_instr_end_16,data +defs_instr_end_16 .word 0 +# endif +#endif diff --git a/kegs/Src/dis.cpp b/kegs/Src/dis.cpp new file mode 100644 index 0000000..3ba8c50 --- /dev/null +++ b/kegs/Src/dis.cpp @@ -0,0 +1,1227 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include +#include "defc.h" +#include + +#include "disas.h" +#include "adb.h" +#include "moremem.h" +#include "sim65816.h" +#include "iwm.h" +#include "protos_engine_c.h" + +#define LINE_SIZE 160 + +extern byte *g_memory_ptr; + + +extern int g_config_control_panel; + + +int g_num_breakpoints = 0; + +struct_breakpoint g_breakpts[MAX_BREAK_POINTS]; + + +#define W_BUF_LEN 128 +char w_buff[W_BUF_LEN]; + +int g_stepping = 0; + +word32 list_kpc; +int hex_line_len; +word32 a1,a2,a3; +word32 g_a4, g_a4bank; +int a1bank, a2bank, a3bank; +char *line_ptr; +int mode,old_mode; +int got_num; + +// OG replaced by HALT_WANTTOQUIT +//int g_quit_sim_now = 0; + +int +get_num() +{ + int tmp1; + + a2 = 0; + got_num = 0; + while(1) { + if(mode == 0 && got_num != 0) { +/* + printf("In getnum, mode =0, setting a1,a3 = a2\n"); + printf("a2: %x\n", a2); +*/ + a3 = a2; + a3bank = a2bank; + a1 = a2; + a1bank = a2bank; + } + tmp1 = *line_ptr++ & 0x7f; + if(tmp1 >= '0' && tmp1 <= '9') { + a2 = (a2 << 4) + tmp1 - '0'; + got_num = 1; + continue; + } + if(tmp1 >= 'a' && tmp1 <= 'f') { + a2 = (a2 << 4) + tmp1 - 'a' + 10; + got_num = 1; + continue; + } + if(tmp1 == '/') { + a2bank = a2; + a2 = 0; + continue; + } + return tmp1; + } +} + +void +debugger_help() +{ + printf("KEGS Debugger help (courtesy Fredric Devernay\n"); + printf("General command syntax: [bank]/[address][command]\n"); + printf("e.g. 'e1/0010B' to set a breakpoint at the interrupt jump pt\n"); + printf("Enter all addresses using lower-case\n"); + printf("As with the IIgs monitor, you can omit the bank number after\n"); + printf("having set it: 'e1/0010B' followed by '14B' will set\n"); + printf("breakpoints at e1/0010 and e1/0014\n"); + printf("\n"); + printf("g Go\n"); + printf("[bank]/[addr]g Go from [bank]/[address]\n"); + printf("s Step one instruction\n"); + printf("[bank]/[addr]s Step one instr at [bank]/[address]\n"); + printf("[bank]/[addr]B Set breakpoint at [bank]/[address]\n"); + printf("B Show all breakpoints\n"); + printf("[bank]/[addr]D Delete breakpoint at [bank]/[address]\n"); + printf("[bank]/[addr1].[addr2] View memory\n"); + printf("[bank]/[addr]L Disassemble memory\n"); + + printf("P Dump the trace to 'pc_log_out'\n"); + printf("Z Dump SCC state\n"); + printf("I Dump IWM state\n"); + printf("[drive].[track]I Dump IWM state\n"); + printf("E Dump Ensoniq state\n"); + printf("[osc]E Dump oscillator [osc] state\n"); + printf("R Dump dtime array and events\n"); + printf("T Show toolbox log\n"); + printf("[bank]/[addr]T Dump tools using ptr [bank]/[addr]\n"); + printf(" as 'tool_set_info'\n"); + printf("[mode]V XOR verbose with 1=DISK, 2=IRQ,\n"); + printf(" 4=CLK,8=SHADOW,10=IWM,20=DOC,\n"); + printf(" 40=ABD,80=SCC, 100=TEST, 200=VIDEO\n"); + printf("[mode]H XOR halt_on with 1=SCAN_INT,\n"); + printf(" 2=IRQ, 4=SHADOW_REG, 8=C70D_WRITES\n"); + printf("r Reset\n"); + printf("[0/1]=m Changes m bit for l listings\n"); + printf("[0/1]=x Changes x bit for l listings\n"); + printf("[t]=z Stops at absolute time t (obsolete)\n"); + printf("S show_bankptr_bank0 & smartport errs\n"); + printf("P show_pmhz\n"); + printf("A show_a2_line_stuff show_adb_log\n"); + printf("Ctrl-e Dump registers\n"); + printf("[bank]/[addr1].[addr2]us[file] Save mem area to [file]\n"); + printf("[bank]/[addr1].[addr2]ul[file] Load mem area from [file]\n"); + printf("v Show video information\n"); + printf("q Exit Debugger (and KEGS)\n"); +} + +void +do_debug_intfc() +{ + char linebuf[LINE_SIZE]; + int slot_drive; + int track; + int osc; + int done; + int ret_val; + + g_config_control_panel = 1; + + hex_line_len = 0x10; + a1 = 0; a2 = 0; a3 = 0; g_a4 = 0; + a1bank = 0; a2bank = 0; a3bank = 0; g_a4bank = 0; + list_kpc = g_sim65816.engine.kpc; + g_stepping = 0; + mode = 0; old_mode = 0; + done = 0; + g_sim65816.stop_run_at = -1; + + x_auto_repeat_on(0); + g_adb.fullscreen = 0; + x_full_screen(0); + + // OG use HALT_WANTTOQUIT instead of g_quit_sim_now + if (r_sim65816.should_emulator_terminate()) //g_sim65816.halt_sim&HALT_WANTTOQUIT) + { + printf("Exiting immediately\n"); + return; + } + + + printf("Type 'h' for help\n"); + + while(!done) { + printf("> "); fflush(stdout); + if(read_line(linebuf,LINE_SIZE-1) <= 0) { + done = 1; + continue; + } + line_ptr = linebuf; + +/* + printf("input line: :%s:\n", linebuf); + printf("mode: %d\n", mode); +*/ + mode = 0; + + while(*line_ptr != 0) { + ret_val = get_num(); +/* + printf("ret_val: %x, got_num= %d\n", ret_val, + got_num); +*/ + old_mode = mode; + mode = 0; + switch(ret_val) { + case 'h': + debugger_help(); + break; + case 'R': + show_dtime_array(); + show_all_events(); + break; + case 'I': + slot_drive = -1; + track = -1; + if(got_num) { + if(old_mode == '.') { + slot_drive = a1; + } + track = a2; + } + iwm_show_track(slot_drive, track); + iwm_show_stats(); + break; + case 'E': + osc = -1; + if(got_num) { + osc = a2; + } + doc_show_ensoniq_state(osc); + break; + case 'T': + if(got_num) { + show_toolset_tables(a2bank, a2); + } else { + show_toolbox_log(); + } + break; + case 'v': + if(got_num) { + dis_do_compare(); + } else { + video_show_debug_info(); + } + break; + case 'V': + printf("g_moremem.g_irq_pending: %05x\n", g_moremem.g_irq_pending); + printf("Setting g_sim65816.Verbose ^= %04x\n", a1); + Verbose ^= a1; + printf("Verbose is now: %04x\n", Verbose); + break; + case 'H': + printf("Setting g_sim65816.Halt_on ^= %04x\n", a1); + g_sim65816.Halt_on ^= a1; + printf("Halt_on is now: %04x\n", g_sim65816.Halt_on); + break; + case 'r': + do_reset(); + list_kpc = g_sim65816.engine.kpc; + break; + case 'm': + if(old_mode == '=') { + if(!a1) { + g_sim65816.engine.psr &= ~0x20; + } else { + g_sim65816.engine.psr |= 0x20; + } + if(g_sim65816.engine.psr & 0x100) { + g_sim65816.engine.psr |= 0x30; + } + } else { + dis_do_memmove(); + } + break; + case 'p': + dis_do_pattern_search(); + break; + case 'x': + if(old_mode == '=') { + if(!a1) { + g_sim65816.engine.psr &= ~0x10; + } else { + g_sim65816.engine.psr |= 0x10; + } + if(g_sim65816.engine.psr & 0x100) { + g_sim65816.engine.psr |= 0x30; + } + } + break; + case 'z': + if(old_mode == '=') { + g_sim65816.stop_run_at = a1; + printf("Calling add_event for t:%08x\n", + a1); + add_event_stop((double)a1); + printf("set g_sim65816.stop_run_at = %x\n", a1); + } + break; + case 'l': case 'L': + do_debug_list(); + break; + case 'Z': + show_scc_log(); + show_scc_state(); + break; + case 'S': + show_bankptrs_bank0rdwr(); + smartport_error(); + break; + case 'C': + x_show_color_array(); + break; + case 'P': + show_pc_log(); + break; + case 'M': + show_pmhz(); + break; + case 'A': + show_a2_line_stuff(); + show_adb_log(); + break; + case 's': + g_stepping = 1; + if(got_num) { + g_sim65816.engine.kpc = (a2bank<<16) + (a2&0xffff); + } + mode = 's'; + list_kpc = g_sim65816.engine.kpc; + break; + case 'B': + if(got_num) { + printf("got_num: %d, a2bank: %x, a2: %x\n", got_num, a2bank, a2); + set_bp((a2bank << 16) + a2,BRK_ALL,NULL,NULL); + } else { + show_bp(); + } + break; + case 'D': + if(got_num) { + printf("got_num: %d, a2bank: %x, a2: %x\n", got_num, a2bank, a2); + delete_bp((a2bank << 16) + a2); + } + break; + case 'g': + case 'G': + printf("Going..\n"); + g_stepping = 0; + if(got_num) { + g_sim65816.engine.kpc = (a2bank<<16) + (a2&0xffff); + } + if(ret_val == 'G' && g_sim65816.g_testing_enabled) { + do_gen_test(got_num, a2); + } else { + do_go(); + } + list_kpc = g_sim65816.engine.kpc; + break; + case 'q': + case 'Q': + printf("Exiting debugger\n"); + return; + break; + case 'u': + printf("Unix commands\n"); + do_debug_unix(); + break; + case ':': case '.': + case '+': case '-': + case '=': case ',': + mode = ret_val; + printf("Setting mode = %x\n", mode); + break; + case ' ': case '\t': + if(!got_num) { + mode = old_mode; + break; + } + do_blank(); + break; + case '<': + g_a4 = a2; + g_a4bank = a2bank; + break; + case 0x05: /* ctrl-e */ + show_regs(); + break; + case '\n': + *line_ptr = 0; + if(old_mode == 's') { + do_blank(); + break; + } + if(line_ptr == &linebuf[1]) { + a2 = a1 | (hex_line_len - 1); + show_hex_mem(a1bank,a1,a2bank,a2, -1); + a1 = a2 + 1; + } else { + if(got_num == 1 || mode == 's') { + do_blank(); + } + } + break; + case 'w': + read_line(w_buff, W_BUF_LEN); + break; + default: + printf("\nUnrecognized command: %s\n",linebuf); + *line_ptr = 0; + break; + } + } + + } + printf("Console closed.\n"); + +} + +word32 +dis_get_memory_ptr(word32 addr) +{ + word32 tmp1, tmp2, tmp3; + + tmp1 = get_memory_c(addr, 0); + tmp2 = get_memory_c(addr + 1, 0); + tmp3 = get_memory_c(addr + 2, 0); + + return (tmp3 << 16) + (tmp2 << 8) + tmp1; +} + +void +show_one_toolset(FILE *toolfile, int toolnum, word32 addr) +{ + word32 rout_addr; + int num_routs; + int i; + + num_routs = dis_get_memory_ptr(addr); + fprintf(toolfile, "Tool 0x%02x, table: 0x%06x, num_routs:%03x\n", + toolnum, addr, num_routs); + + for(i = 1; i < num_routs; i++) { + rout_addr = dis_get_memory_ptr(addr + 4*i); + fprintf(toolfile, "%06x = %02x%02x\n", rout_addr, i, toolnum); + } +} + +void +show_toolset_tables(word32 a2bank, word32 addr) +{ + FILE *toolfile; + word32 tool_addr; + int num_tools; + int i; + + addr = (a2bank << 16) + (addr & 0xffff); + + toolfile = fopen("tool_set_info", "w"); + if(toolfile == 0) { + fprintf(stderr, "fopen of tool_set_info failed: %d\n", errno); + x_exit(2); + } + + num_tools = dis_get_memory_ptr(addr); + fprintf(toolfile, "There are 0x%02x tools using ptr at %06x\n", + num_tools, addr); + + for(i = 1; i < num_tools; i++) { + tool_addr = dis_get_memory_ptr(addr + 4*i); + show_one_toolset(toolfile, i, tool_addr); + } + + fclose(toolfile); +} + + +#ifndef TEST65 +void +do_gen_test(int got_num, int base_seed) +{ + /* dummy */ +} +#endif + +void +set_bp(word32 _addr,enum mode_breakpoint _mode, const char* _patch, const char* _check) +{ + int count; + + //printf("About to set BP at %06x\n", _addr); + count = g_num_breakpoints; + if(count >= MAX_BREAK_POINTS) { + printf("Too many (0x%02x) breakpoints set!\n", count); + return; + } + + g_breakpts[count].addr = _addr; + g_breakpts[count].mode = _mode; + g_breakpts[count].patch = _patch; + g_breakpts[count].check = _check; + g_num_breakpoints = count + 1; + fixup_brks(); +} + +void +show_bp() +{ + int i; + + printf("Showing breakpoints set\n"); + for(i = 0; i < g_num_breakpoints; i++) + { + printf("bp:%02x: %06x ", i, g_breakpts[i].addr); + if (g_breakpts[i].mode&BRK_READ) + printf("R"); + if (g_breakpts[i].mode&BRK_WRITE) + printf("W"); + if (g_breakpts[i].mode&BRK_X) + printf("X"); + if (g_breakpts[i].mode&BRK_PATCH) + printf("P"); + if (g_breakpts[i].mode&BRK_STOP) + printf("B"); + if (g_breakpts[i].mode&BRK_SLOWSPEED) + printf("S"); + if (g_breakpts[i].mode&BRK_DEFAULTSPEED) + printf("D"); + if (g_breakpts[i].mode&BRK_MESSAGE) + printf("M:%s",g_breakpts[i].patch); + + if (g_breakpts[i].check && g_breakpts[i].check[0]) + printf(" *"); + + printf("\n"); + } +} + +void +delete_bp(word32 addr) +{ + int count; + int hit; + int i; + + printf("About to delete BP at %06x\n", addr); + count = g_num_breakpoints; + + hit = -1; + for(i = 0; i < count; i++) { + if(g_breakpts[i].addr == addr) { + hit = i; + break; + } + } + + if(hit < 0) { + printf("Breakpoint not found!\n"); + } else { + printf("Deleting brkpoint #0x%02x\n", hit); + for(i = hit+1; i < count; i++) { + g_breakpts[i-1] = g_breakpts[i]; + } + g_num_breakpoints = count - 1; + setup_pageinfo(); + } + + show_bp(); +} + +void +do_blank() +{ + int tmp, i; + + switch(old_mode) { + case 's': + tmp = a2; + if(tmp == 0) tmp = 1; + g_sim65816.enter_debug = 0; + for(i = 0; i < tmp; i++) { + g_stepping = 1; + do_step(); + if(g_sim65816.enter_debug || g_sim65816.halt_sim != 0) { + if(g_sim65816.halt_sim != HALT_EVENT) { + break; + } + } + } + list_kpc = g_sim65816.engine.kpc; + /* video_update_through_line(262); */ + break; + case ':': + set_memory_c(((a3bank << 16) + a3), a2, 0); + a3++; + mode = old_mode; + break; + case '.': + case 0: + xam_mem(-1); + break; + case ',': + xam_mem(16); + break; + case '+': + printf("%x\n", a1 + a2); + break; + case '-': + printf("%x\n", a1 - a2); + break; + default: + printf("Unknown mode at space: %d\n", old_mode); + break; + } +} + +void +do_go() +{ + + #ifdef ACTIVEGS + { + extern void disableConsole(); + disableConsole(); + } + #endif + + /* also called by do_step */ + + g_config_control_panel = 0; + clear_halt(); + + run_prog(); + show_regs(); + g_config_control_panel = 1; +} + +void +do_step() +{ + int size; + int size_mem_imm, size_x_imm; + + do_go(); + + size_mem_imm = 2; + if(g_sim65816.engine.psr & 0x20) { + size_mem_imm = 1; + } + size_x_imm = 2; + if(g_sim65816.engine.psr & 0x10) { + size_x_imm = 1; + } + size = do_dis(stdout, g_sim65816.engine.kpc, size_mem_imm, size_x_imm, 0, 0); +} + +void +xam_mem(int count) +{ + show_hex_mem(a1bank, a1, a2bank, a2, count); + a1 = a2 + 1; +} + +void +show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count) +{ + char ascii[MAXNUM_HEX_PER_LINE]; + word32 i; + int val, offset; + + if(count < 0) { + count = 16 - (start & 0xf); + } + + offset = 0; + ascii[0] = 0; + printf("Showing hex mem: bank: %x, start: %x, end: %x\n", + startbank, start, end); + for(i = start; i <= end; i++) { + if( (i==start) || (count == 16) ) { + printf("%04x:",i); + } + printf(" %02x", get_memory_c((startbank <<16) + i, 0)); + val = get_memory_c((startbank << 16) + i, 0) & 0x7f; + if(val < 32 || val >= 0x7f) { + val = '.'; + } + ascii[offset++] = val; + ascii[offset] = 0; + count--; + if(count <= 0) { + printf(" %s\n", ascii); + offset = 0; + ascii[0] = 0; + count = 16; + } + } + if(offset > 0) { + printf(" %s\n", ascii); + } +} + + +int +read_line(char *buf, int len) +{ + int space_left; + int ret; +#ifndef _WIN32 + int flags, flags_save; + + /* Unix */ + flags = fcntl(0, F_GETFL, 0); + flags_save = flags; + if(flags == -1) { + return 0; + } + ret = fcntl(0, F_SETFL, flags | O_NONBLOCK); + if(ret == -1) { + return 0; + } +#endif + space_left = len; + + buf[0] = 0; + ret = 0; + while(space_left > 0) { +#ifdef _WIN32 + ret = win_nonblock_read_stdin(0, buf, 1); +#else + /* Unix */ + ret = read(0, buf, 1); +#endif + if(ret <= 0) { + micro_sleep(15.0/60.0); + if(errno == EAGAIN) { + /* it would block, so no chars--do update */ + video_update(); + ret = 0; + continue; + } + printf("read ret %d, errno: %d\n", ret, errno); + if(errno == EAGAIN || errno == EINTR) { + ret = 0; + continue; + } + break; + } + space_left -= ret; + if(buf[ret-1] == 0x0a) { + break; + } + buf = &buf[ret]; + } +#ifndef _WIN32 + (void)fcntl(0, F_SETFL, flags_save); +#endif + + return (len-space_left); +} + +void +do_debug_list() +{ + int i; + int size; + int size_mem_imm, size_x_imm; + + if(got_num) { + list_kpc = (a2bank << 16) + (a2 & 0xffff); + } + printf("%d=m %d=x %d=LCBANK\n", (g_sim65816.engine.psr >> 5)&1, + (g_sim65816.engine.psr >> 4) & 1, (g_moremem.g_c068_statereg & 0x4) >> 2); + + size_mem_imm = 2; + if(g_sim65816.engine.psr & 0x20) { + size_mem_imm = 1; + } + size_x_imm = 2; + if(g_sim65816.engine.psr & 0x10) { + size_x_imm = 1; + } + for(i=0;i<20;i++) { + size = do_dis(stdout, list_kpc, size_mem_imm, + size_x_imm, 0, 0); + list_kpc += size; + } +} + +void +dis_do_memmove() +{ + word32 val; + + printf("Memory move from %02x/%04x.%04x to %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4); + while(a1 <= (a2 & 0xffff)) { + val = get_memory_c((a1bank << 16) + a1, 0); + set_memory_c((g_a4bank << 16) + g_a4, val, 0); + a1++; + g_a4++; + } + a1 = a1 & 0xffff; + g_a4 = g_a4 & 0xffff; +} + +void +dis_do_pattern_search() +{ + printf("Memory pattern search for %04x in %02x/%04x.%04x\n", g_a4, a1bank, a1, a2); +} + +void +dis_do_compare() +{ + word32 val1, val2; + + printf("Memory Compare from %02x/%04x.%04x with %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4); + while(a1 <= (a2 & 0xffff)) { + val1 = get_memory_c((a1bank << 16) + a1, 0); + val2 = get_memory_c((g_a4bank << 16) + g_a4, 0); + if(val1 != val2) { + printf("%02x/%04x: %02x vs %02x\n", a1bank, a1, val1, val2); + } + a1++; + g_a4++; + } + a1 = a1 & 0xffff; + g_a4 = g_a4 & 0xffff; +} + +void +do_debug_unix() +{ + char localbuf[LINE_SIZE]; + word32 offset, len; + int fd, ret; + int load, save; + int i; + + load = 0; save = 0; + switch(*line_ptr++) { + case 'l': case 'L': + printf("Loading.."); + load = 1; + break; + case 's': case 'S': + printf("Saving..."); + save = 1; + break; + default: + printf("Unknown unix command: %c\n", *(line_ptr-1)); + *line_ptr = 0; + return; + } + while(*line_ptr == ' ' || *line_ptr == '\t') { + line_ptr++; + } + i = 0; + while(i < LINE_SIZE) { + localbuf[i++] = *line_ptr++; + if(*line_ptr==' ' || *line_ptr=='\t' || *line_ptr == '\n') { + break; + } + } + localbuf[i] = 0; + + + printf("About to open: %s,len: %d\n", localbuf, (int)strlen(localbuf)); + if(load) { + fd = open(localbuf,O_RDONLY | O_BINARY); + } else { + fd = open(localbuf,O_WRONLY | O_CREAT | O_BINARY, 0x1b6); + } + if(fd < 0) { + printf("Open %s failed: %d\n", localbuf, fd); + printf("errno: %d\n", errno); + return; + } + if(load) { + offset = a1 & 0xffff; + len = 0x20000 - offset; + } else { + if(old_mode == '.') { + len = a2 - a1 + 1; + } else { + len = 0x100; + } + } + if(load) { + if(a1bank >= 0xe0 && a1bank < 0xe2) { + ret = read(fd,(char*)&g_slow_memory_ptr[((a1bank & 1)<<16)+a1],len); + } else { + ret = read(fd,(char*)&g_memory_ptr[(a1bank << 16) + a1],len); + } + } else { + if(a1bank >= 0xe0 && a1bank < 0xe2) { + ret = write(fd,(char*)&g_slow_memory_ptr[((a1bank & 1)<<16)+a1],len); + } else { + ret = write(fd,(char*)&g_memory_ptr[(a1bank << 16) + a1],len); + } + } + printf("Read/write: addr %06x for %04x bytes, ret: %x bytes\n", + (a1bank << 16) + a1, len, ret); + if(ret < 0) { + printf("errno: %d\n", errno); + } + a1 = a1 + ret; +} + +void +do_debug_load() +{ + printf("Sorry, can't load now\n"); +} + + +int +do_dis(FILE *outfile, word32 kpc, int accsize, int xsize, + int op_provided, word32 instr) +{ + char buffer[150]; + const char *out; + int args, type; + int opcode; + word32 val; + word32 oldkpc; + word32 dtype; + int signed_val; + + oldkpc = kpc; + if(op_provided) { + opcode = (instr >> 24) & 0xff; + } else { + opcode = (int)get_memory_c(kpc, 0) & 0xff; + } + + kpc++; + + dtype = disas_types[opcode]; + out = disas_opcodes[opcode]; + type = dtype & 0xff; + args = dtype >> 8; + + if(args > 3) { + if(args == 4) { + args = accsize; + } else if(args == 5) { + args = xsize; + } + } + + val = -1; + switch(args) { + case 0: + val = 0; + break; + case 1: + if(op_provided) { + val = instr & 0xff; + } else { + val = get_memory_c(kpc, 0); + } + break; + case 2: + if(op_provided) { + val = instr & 0xffff; + } else { + val = get_memory16_c(kpc, 0); + } + break; + case 3: + if(op_provided) { + val = instr & 0xffffff; + } else { + val = get_memory24_c(kpc, 0); + } + break; + default: + fprintf(stderr, "args out of rang: %d, opcode: %08x\n", + args, opcode); + break; + } + kpc += args; + + if(!op_provided) { + instr = (opcode << 24) | (val & 0xffffff); + } + + switch(type) { + case ABS: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSX: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x,X",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSY: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x,Y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSLONG: + if(args != 3) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%06x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSIND: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%04x)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSXIND: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%04x,X)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case IMPLY: + if(args != 0) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s",out); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ACCUM: + if(args != 0) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s",out); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case IMMED: + if(args == 1) { + sprintf(buffer,"%s\t#$%02x",out,val); + } else if(args == 2) { + sprintf(buffer,"%s\t#$%04x",out,val); + } else { + printf("arg # mismatch for opcode %x\n", opcode); + } + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case JUST8: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOC: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCX: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,X",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,Y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case LONG: + if(args != 3) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%06x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case LONGX: + if(args != 3) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%06x,X",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCIND: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCINDY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x),Y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCXIND: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x,X)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCBRAK: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t[$%02x]",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCBRAKY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t[$%02x],y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP8: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + signed_val = (signed char)val; + sprintf(buffer,"%s\t$%04x",out, + (word32)(kpc+(signed_val)) & 0xffff); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP8S: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,S",out,(word32)(byte)(val)); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP8SINDY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x,S),Y",out,(word32)(byte)(val)); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP16: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x", out, + (word32)(kpc+(signed)(word16)(val)) & 0xffff); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case MVPMVN: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,$%02x",out,val&0xff,val>>8); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case SEPVAL: + case REPVAL: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t#$%02x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + default: + printf("argument type: %d unexpected\n", type); + break; + } + + return(args+1); +} + +void +show_line(FILE *outfile, word32 kaddr, word32 operand, int size, + char *string) +{ + int i; + int opcode; + +// fprintf(outfile, "%02x/%04x: ", kaddr >> 16, kaddr & 0xffff); + printf("%02x/%04x: ", kaddr >> 16, kaddr & 0xffff); + + opcode = (operand >> 24) & 0xff; +// fprintf(outfile,"%02x ", opcode); + printf("%02x ", opcode); + + for(i=1;i> 8; + } + for(;i<5;i++) { + // fprintf(outfile, " "); + printf(" "); + } + //fprintf(outfile,"%s\n", string); + printf("%s\n", string); + +} + +void +halt_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +#ifdef _DEBUG +// set_halt(HALT_WANTTOBRK); +#endif + set_halt(1); +} + +void +halt2_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + set_halt(2); +} + diff --git a/kegs/Src/disas.h b/kegs/Src/disas.h new file mode 100644 index 0000000..dc61580 --- /dev/null +++ b/kegs/Src/disas.h @@ -0,0 +1,204 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +enum { + ABS = 1, + ABSX, + ABSY, + ABSLONG, + ABSIND, + ABSXIND, + IMPLY, + ACCUM, + IMMED, + JUST8, + DLOC, + DLOCX, + DLOCY, + LONG, + LONGX, + DLOCIND, + DLOCINDY, + DLOCXIND, + DLOCBRAK, + DLOCBRAKY, + DISP8, + DISP8S, + DISP8SINDY, + DISP16, + MVPMVN, + REPVAL, + SEPVAL +}; + + +const char * const disas_opcodes[256] = { + "BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", /* 00-07 */ + "PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", /* 08-0f */ + "BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", /* 10-17 */ + "CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", /* 18-1f */ + "JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", /* 20-27 */ + "PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", /* 28-2f */ + "BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", /* 30-37 */ + "SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", /* 38-3f */ + "RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR", /* 40-47 */ + "PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", /* 48-4f */ + "BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", /* 50-57 */ + "CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR", /* 58-5f */ + "RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", /* 60-67 */ + "PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", /* 68-6f */ + "BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", /* 70-77 */ + "SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", /* 78-7f */ + "BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", /* 80-87 */ + "DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", /* 88-8f */ + "BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", /* 90-97 */ + "TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", /* 98-9f */ + "LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", /* a0-a7 */ + "TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", /* a8-af */ + "BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", /* b0-b7 */ + "CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", /* b8-bf */ + "CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", /* c0-c7 */ + "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", /* c8-cf */ + "BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", /* d0-d7 */ + "CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", /* d8-df */ + "CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", /* e0-e7 */ + "INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", /* e8-ef */ + "BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", /* f0-f7 */ + "SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC", /* f8-ff */ +}; + + +const word32 disas_types[256] = { + JUST8+0x100, DLOCXIND+0x100, /* 00-01 */ + JUST8+0x100, DISP8S+0x100, /* 02-03 */ + DLOC+0x100, DLOC+0x100, /* 04-05 */ + DLOC+0x100, DLOCBRAK+0x100, /* 06-07 */ + IMPLY+0x000, IMMED+0x400, /* 08-9 */ + ACCUM+0x000, IMPLY+0x000, /* 0a-b */ + ABS+0x200, ABS+0x200, /* c-d */ + ABS+0x200, LONG+0x300, /* e-f */ + DISP8+0x100, DLOCINDY+0x100, /* 10-11 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 12-13 */ + DLOC+0x100, DLOCX+0x100, /* 14-15 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 16-17 */ + IMPLY+0x000, ABSY+0x200, /* 18-19 */ + ACCUM+0x000, IMPLY+0x000, /* 1a-1b */ + ABS+0x200, ABSX+0x200, /* 1c-1d */ + ABSX+0x200, LONGX+0x300, /* 1e-1f */ + ABS+0x200, DLOCXIND+0x100, /* 20-21 */ + ABSLONG+0x300, DISP8S+0x100, /* 22-23 */ + DLOC+0x100, DLOC+0x100, /* 24-25 */ + DLOC+0x100, DLOCBRAK+0x100, /* 26-27 */ + IMPLY+0x000, IMMED+0x400, /* 28-29 */ + ACCUM+0x000, IMPLY+0x000, /* 2a-2b */ + ABS+0x200, ABS+0x200, /* 2c-2d */ + ABS+0x200, LONG+0x300, /* 2e-2f */ + DISP8+0x100, DLOCINDY+0x100, /* 30-31 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 32-33 */ + DLOCX+0x100, DLOCX+0x100, /* 34-35 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 36-37 */ + IMPLY+0x000, ABSY+0x200, /* 38-39 */ + ACCUM+0x000, IMPLY+0x000, /* 3a-3b */ + ABSX+0x200, ABSX+0x200, /* 3c-3d */ + ABSX+0x200, LONGX+0x300, /* 3e-3f */ + IMPLY+0x000, DLOCXIND+0x100, /* 40-41 */ + JUST8+0x100, DISP8S+0x100, /* 42-43 */ + MVPMVN+0x200, DLOC+0x100, /* 44-45 */ + DLOC+0x100, DLOCBRAK+0x100, /* 46-47 */ + IMPLY+0x000, IMMED+0x400, /* 48-49 */ + ACCUM+0x000, IMPLY+0x000, /* 4a-4b */ + ABS+0x200, ABS+0x200, /* 4c-4d */ + ABS+0x200, LONG+0x300, /* 4e-4f */ + DISP8+0x100, DLOCINDY+0x100, /* 50-51 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 52-53 */ + MVPMVN+0x200, DLOCX+0x100, /* 54-55 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 56-57 */ + IMPLY+0x000, ABSY+0x200, /* 58-59 */ + IMPLY+0x000, IMPLY+0x000, /* 5a-5b */ + LONG+0x300, ABSX+0x200, /* 5c-5d */ + ABSX+0x200, LONGX+0x300, /* 5e-5f */ + IMPLY+0x000, DLOCXIND+0x100, /* 60-61 */ + DISP16+0x200, DISP8S+0x100, /* 62-63 */ + DLOC+0x100, DLOC+0x100, /* 64-65 */ + DLOC+0x100, DLOCBRAK+0x100, /* 66-67 */ + IMPLY+0x000, IMMED+0x400, /* 68-69 */ + ACCUM+0x000, IMPLY+0x000, /* 6a-6b */ + ABSIND+0x200, ABS+0x200, /* 6c-6d */ + ABS+0x200, LONG+0x300, /* 6e-6f */ + DISP8+0x100, DLOCINDY+0x100, /* 70-71 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 72-73 */ + DLOCX+0x100, DLOCX+0x100, /* 74-75 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 76-77 */ + IMPLY+0x000, ABSY+0x200, /* 78-79 */ + IMPLY+0x000, IMPLY+0x000, /* 7a-7b */ + ABSXIND+0x200, ABSX+0x200, /* 7c-7d */ + ABSX+0x200, LONGX+0x300, /* 7e-7f */ + DISP8+0x100, DLOCXIND+0x100, /* 80-81 */ + DISP16+0x200, DISP8S+0x100, /* 82-83 */ + DLOC+0x100, DLOC+0x100, /* 84-85 */ + DLOC+0x100, DLOCBRAK+0x100, /* 86-87 */ + IMPLY+0x000, IMMED+0x400, /* 88-89 */ + IMPLY+0x000, IMPLY+0x000, /* 8a-8b */ + ABS+0x200, ABS+0x200, /* 8c-8d */ + ABS+0x200, LONG+0x300, /* 8e-8f */ + DISP8+0x100, DLOCINDY+0x100, /* 90-91 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 92-93 */ + DLOCX+0x100, DLOCX+0x100, /* 94-95 */ + DLOCY+0x100, DLOCBRAKY+0x100, /* 96-97 */ + IMPLY+0x000, ABSY+0x200, /* 98-99 */ + IMPLY+0x000, IMPLY+0x000, /* 9a-9b */ + ABS+0x200, ABSX+0x200, /* 9c-9d */ + ABSX+0x200, LONGX+0x300, /* 9e-9f */ + IMMED+0x500, DLOCXIND+0x100, /* a0-a1 */ + IMMED+0x500, DISP8S+0x100, /* a2-a3 */ + DLOC+0x100, DLOC+0x100, /* a4-a5 */ + DLOC+0x100, DLOCBRAK+0x100, /* a6-a7 */ + IMPLY+0x000, IMMED+0x400, /* a8-a9 */ + IMPLY+0x000, IMPLY+0x000, /* aa-ab */ + ABS+0x200, ABS+0x200, /* ac-ad */ + ABS+0x200, LONG+0x300, /* ae-af */ + DISP8+0x100, DLOCINDY+0x100, /* b0-b1 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* b2-b3 */ + DLOCX+0x100, DLOCX+0x100, /* b4-b5 */ + DLOCY+0x100, DLOCBRAKY+0x100, /* b6-b7 */ + IMPLY+0x000, ABSY+0x200, /* b8-b9 */ + IMPLY+0x000, IMPLY+0x000, /* ba-bb */ + ABSX+0x200, ABSX+0x200, /* bc-bd */ + ABSY+0x200, LONGX+0x300, /* be-bf */ + IMMED+0x500, DLOCXIND+0x100, /* c0-c1 */ + REPVAL+0x100, DISP8S+0x100, /* c2-c3 */ + DLOC+0x100, DLOC+0x100, /* c4-c5 */ + DLOC+0x100, DLOCBRAK+0x100, /* c6-c7 */ + IMPLY+0x000, IMMED+0x400, /* c8-c9 */ + IMPLY+0x000, IMPLY+0x000, /* ca-cb */ + ABS+0x200, ABS+0x200, /* cc-cd */ + ABS+0x200, LONG+0x300, /* ce-cf */ + DISP8+0x100, DLOCINDY+0x100, /* d0-d1 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* d2-d3 */ + DLOC+0x100, DLOCX+0x100, /* d4-d5 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* d6-d7 */ + IMPLY+0x000, ABSY+0x200, /* d8-d9 */ + IMPLY+0x000, IMPLY+0x000, /* da-db */ + ABSIND+0x200, ABSX+0x200, /* dc-dd */ + ABSX+0x200, LONGX+0x300, /* de-df */ + IMMED+0x500, DLOCXIND+0x100, /* e0-e1 */ + SEPVAL+0x100, DISP8S+0x100, /* e2-e3 */ + DLOC+0x100, DLOC+0x100, /* e4-e5 */ + DLOC+0x100, DLOCBRAK+0x100, /* e6-e7 */ + IMPLY+0x000, IMMED+0x400, /* e8-e9 */ + IMPLY+0x000, IMPLY+0x000, /* ea-eb */ + ABS+0x200, ABS+0x200, /* ec-ed */ + ABS+0x200, LONG+0x300, /* ee-ef */ + DISP8+0x100, DLOCINDY+0x100, /* f0-f1 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* f2-f3 */ + IMMED+0x200, DLOCX+0x100, /* f4-f5 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* f6-f7 */ + IMPLY+0x000, ABSY+0x200, /* f8-f9 */ + IMPLY+0x000, IMPLY+0x000, /* fa-fb */ + ABSXIND+0x200, ABSX+0x200, /* fc-fd */ + ABSX+0x200, LONGX+0x300, /* fe-ff */ +}; + diff --git a/kegs/Src/driver.cpp b/kegs/Src/driver.cpp new file mode 100644 index 0000000..9151748 --- /dev/null +++ b/kegs/Src/driver.cpp @@ -0,0 +1,15 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "driver.h" + +s_driver g_driver; + +void s_driver::init(void (*_driver)()) +{ + if (_driver!=NULL) + _driver(); +} \ No newline at end of file diff --git a/kegs/Src/driver.h b/kegs/Src/driver.h new file mode 100644 index 0000000..ee12780 --- /dev/null +++ b/kegs/Src/driver.h @@ -0,0 +1,62 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" + +enum ui_msg +{ + LOADING_ON=1304, + LOADING_OFF, + REFRESH_STATUS, + SHOW_CURSOR +}; + +enum { + PLATFORM_WINDOWS = 100, + PLATFORM_MACOSX, + PLATFORM_IOS, + PLATFORM_ANDROID }; + + +enum { + ENV_DESKTOP = 2000, + ENV_TOUCH, + ENV_BROWSER }; + + + + + +struct s_driver +{ + int platform ; + int environment; + char activegsxml[1024]; + void (*x_config_load_roms)(); + void (*x_post_event)(const char* _msg); + int (*x_handle_fkey)(int _key); + void (*x_handle_state)(); + void (*x_handle_state_on_paint)(float _width,float _height); + void (*x_apply_default_options)(void*); + void (*x_fixed_memory_ptr)(); + void (*x_notify_eject)(); + + + s_driver() + { + memset(this,0,sizeof(*this)); + } + + void init(void (*_driver)()); + void setLaunchXML(const char* _xml){ + if (_xml!=NULL) + strcpy(activegsxml,_xml); + else + activegsxml[0] = 0; + } +}; + +extern s_driver g_driver; \ No newline at end of file diff --git a/kegs/Src/engine_c.cpp b/kegs/Src/engine_c.cpp new file mode 100644 index 0000000..2730deb --- /dev/null +++ b/kegs/Src/engine_c.cpp @@ -0,0 +1,1155 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "protos_engine_c.h" +#include "moremem.h" +#include "sim65816.h" +#include "iwm.h" +#include "video.h" +#include "driver.h" +#if 0 +# define LOG_PC +/* define FCYCS_PTR_FCYCLES_ROUND_SLOW to get accurate 1MHz write to slow mem*/ +/* this might help joystick emulation in some Apple //gs games like */ +/* Madness */ +# define FCYCS_PTR_FCYCLES_ROUND_SLOW FCYCLES_ROUND; *fcycs_ptr = fcycles; +#endif + +#ifndef FCYCS_PTR_FCYCLES_ROUND_SLOW +# define FCYCS_PTR_FCYCLES_ROUND_SLOW +#endif + +/* +extern int halt_sim; +extern int g_code_red; +extern int g_ignore_halts; +extern int g_user_halt_bad; +extern double g_fcycles_stop; +extern double g_last_vbl_dcycs; +//extern double g_sim65816.g_cur_dcycs; +extern int g_wait_pending; +extern int g_testing; +extern int g_num_brk; +extern int g_num_cop; + +*/ + +extern byte *g_memory_ptr; +extern byte *g_rom_fc_ff_ptr; +extern byte *g_rom_cards_ptr; +extern byte *g_dummy_memory1_ptr; + +// OG Need allocated memory +extern byte *g_slow_memory_ptr_allocated; +extern byte *g_memory_ptr_allocated; +extern byte *g_rom_fc_ff_ptr_allocated; +extern byte *g_rom_cards_ptr_allocated; +extern byte *g_dummy_memory1_ptr_allocated; + +/* +extern int g_num_breakpoints; +extern word32 g_breakpts[]; +*/ + +extern Pc_log *g_log_pc_ptr; +extern Pc_log *g_log_pc_start_ptr; +extern Pc_log *g_log_pc_end_ptr; + +extern Data_log *g_log_data_ptr; +extern Data_log *g_log_data_start_ptr; +extern Data_log *g_log_data_end_ptr; + +int size_tab[] = { +#include "size_c.h" +}; + +int bogus[] = { + 0, +#include "op_routs.h" +}; + +#define FINISH(arg1, arg2) g_moremem.g_ret1 = arg1; g_moremem.g_ret2 = arg2; goto finish; +#define INC_KPC_1 kpc = (kpc & 0xff0000) + ((kpc + 1) & 0xffff); +#define INC_KPC_2 kpc = (kpc & 0xff0000) + ((kpc + 2) & 0xffff); +#define INC_KPC_3 kpc = (kpc & 0xff0000) + ((kpc + 3) & 0xffff); +#define INC_KPC_4 kpc = (kpc & 0xff0000) + ((kpc + 4) & 0xffff); + +#define CYCLES_PLUS_1 fcycles += fplus_1; +#define CYCLES_PLUS_2 fcycles += fplus_2; +#define CYCLES_PLUS_3 fcycles += fplus_3; +#define CYCLES_PLUS_4 fcycles += (fplus_1 + fplus_3); +#define CYCLES_PLUS_5 fcycles += (fplus_2 + fplus_3); +#define CYCLES_MINUS_1 fcycles -= fplus_1; +#define CYCLES_MINUS_2 fcycles -= fplus_2; + +#define CYCLES_FINISH fcycles = g_sim65816.g_fcycles_stop + fplus_1; + +#define FCYCLES_ROUND fcycles = (int)(fcycles + fplus_x_m1); + +#ifdef LOG_PC +# define LOG_PC_MACRO() \ + tmp_pc_ptr = g_log_pc_ptr++; \ + tmp_pc_ptr->dbank_kpc = (dbank << 24) + kpc; \ + tmp_pc_ptr->instr = (opcode << 24) + arg_ptr[1] + \ + (arg_ptr[2] << 8) + (arg_ptr[3] << 16); \ + tmp_pc_ptr->psr_acc = ((psr & ~(0x82)) << 16) + acc + \ + (neg << 23) + ((!zero) << 17); \ + tmp_pc_ptr->xreg_yreg = (xreg << 16) + yreg; \ + tmp_pc_ptr->stack_direct = (stack << 16) + direct; \ + tmp_pc_ptr->dcycs = fcycles + g_last_vbl_dcycs - fplus_2; \ + if(g_log_pc_ptr >= g_log_pc_end_ptr) { \ + /*halt2_printf("log_pc oflow %f\n", tmp_pc_ptr->dcycs);*/ \ + g_log_pc_ptr = g_log_pc_start_ptr; \ + } + +# define LOG_DATA_MACRO(in_addr, in_val, in_size) \ + g_log_data_ptr->dcycs = fcycles + g_last_vbl_dcycs; \ + g_log_data_ptr->addr = in_addr; \ + g_log_data_ptr->val = in_val; \ + g_log_data_ptr->size = in_size; \ + g_log_data_ptr++; \ + if(g_log_data_ptr >= g_log_data_end_ptr) { \ + g_log_data_ptr = g_log_data_start_ptr; \ + } + +#else +# define LOG_PC_MACRO() +# define LOG_DATA_MACRO(addr, val, size) +/* Just do nothing */ +#endif + + +#define GET_1BYTE_ARG arg = arg_ptr[1]; +#define GET_2BYTE_ARG arg = arg_ptr[1] + (arg_ptr[2] << 8); +#define GET_3BYTE_ARG arg = arg_ptr[1] + (arg_ptr[2] << 8) + (arg_ptr[3]<<16); + +/* HACK HACK HACK */ +#define UPDATE_PSR(dummy, old_psr) \ + if(psr & 0x100) { \ + psr |= 0x30; \ + stack = 0x100 + (stack & 0xff); \ + } \ + if((old_psr ^ psr) & 0x10) { \ + if(psr & 0x10) { \ + xreg = xreg & 0xff; \ + yreg = yreg & 0xff; \ + } \ + } \ + if(((psr & 0x4) == 0) && g_moremem.g_irq_pending) { \ + FINISH(RET_IRQ, 0); \ + } \ + if((old_psr ^ psr) & 0x20) { \ + goto recalc_accsize; \ + } + +//extern Page_info page_info_rd_wr[]; +//extern word32 slow_mem_changed[]; + +#define GET_MEMORY8(addr,dest) \ + addr_latch = (addr); \ + CYCLES_PLUS_1; \ + stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + if(wstat & (1 << (31 - BANK_IO_BIT))) { \ + fcycles_tmp1 = fcycles; \ + dest = get_memory8_io_stub((addr), stat, \ + &fcycles_tmp1, fplus_x_m1); \ + fcycles = fcycles_tmp1; \ + } else { \ + dest = *ptr; \ + } + +#define GET_MEMORY(addr,dest) GET_MEMORY8(addr, dest) + +#define GET_MEMORY16(addr, dest, in_bank) \ + save_addr = addr; \ + stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + if((wstat & (1 << (31 - BANK_IO_BIT))) || (((addr) & 0xff) == 0xff)) { \ + fcycles_tmp1 = fcycles; \ + dest = get_memory16_pieces_stub((addr), stat, \ + &fcycles_tmp1, fplus_ptr, in_bank); \ + fcycles = fcycles_tmp1; \ + } else { \ + CYCLES_PLUS_2; \ + dest = ptr[0] + (ptr[1] << 8); \ + } \ + addr_latch = save_addr; + +#define GET_MEMORY24(addr, dest, in_bank) \ + save_addr = addr; \ + stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + if((wstat & (1 << (31 - BANK_IO_BIT))) || (((addr) & 0xfe) == 0xfe)) { \ + fcycles_tmp1 = fcycles; \ + dest = get_memory24_pieces_stub((addr), stat, \ + &fcycles_tmp1, fplus_ptr, in_bank); \ + fcycles = fcycles_tmp1; \ + } else { \ + CYCLES_PLUS_3; \ + dest = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16); \ + } \ + addr_latch = save_addr; + +#define GET_MEMORY_DIRECT_PAGE16(addr, dest) \ + save_addr = addr; \ + if(psr & 0x100) { \ + if((direct & 0xff) == 0) { \ + save_addr = (save_addr & 0xff) + direct; \ + } \ + } \ + if((psr & 0x100) && (((addr) & 0xff) == 0xff)) { \ + GET_MEMORY8(save_addr, getmem_tmp); \ + save_addr = (save_addr + 1) & 0xffff; \ + if((direct & 0xff) == 0) { \ + save_addr = (save_addr & 0xff) + direct; \ + } \ + GET_MEMORY8(save_addr, dest); \ + dest = (dest << 8) + getmem_tmp; \ + } else { \ + GET_MEMORY16(save_addr, dest, 1); \ + } + + +#define PUSH8(arg) \ + SET_MEMORY8(stack, arg); \ + stack--; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + stack = stack & 0xffff; + +#define PUSH16(arg) \ + if((stack & 0xfe) == 0) { \ + /* stack will cross page! */ \ + PUSH8((arg) >> 8); \ + PUSH8(arg); \ + } else { \ + stack -= 2; \ + stack = stack & 0xffff; \ + SET_MEMORY16(stack + 1, arg, 1); \ + } + +#define PUSH16_UNSAFE(arg) \ + save_addr = (stack - 1) & 0xffff; \ + stack -= 2; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + stack = stack & 0xffff; \ + SET_MEMORY16(save_addr, arg, 1); + +#define PUSH24_UNSAFE(arg) \ + save_addr = (stack - 2) & 0xffff; \ + stack -= 3; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + stack = stack & 0xffff; \ + SET_MEMORY24(save_addr, arg, 1); + +#define PULL8(dest) \ + stack++; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + stack = stack & 0xffff; \ + GET_MEMORY8(stack, dest); + +#define PULL16(dest) \ + if((stack & 0xfe) == 0xfe) { /* page cross */ \ + PULL8(dest); \ + PULL8(pull_tmp); \ + dest = (pull_tmp << 8) + dest; \ + } else { \ + GET_MEMORY16(stack + 1, dest, 1); \ + stack = (stack + 2) & 0xffff; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + } + +#define PULL16_UNSAFE(dest) \ + stack = (stack + 1) & 0xffff; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + GET_MEMORY16(stack, dest, 1); \ + stack = (stack + 1) & 0xffff; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } + +#define PULL24(dest) \ + if((stack & 0xfc) == 0xfc) { /* page cross */ \ + PULL8(dest); \ + PULL8(pull_tmp); \ + pull_tmp = (pull_tmp << 8) + dest; \ + PULL8(dest); \ + dest = (dest << 16) + pull_tmp; \ + } else { \ + GET_MEMORY24(stack + 1, dest, 1); \ + stack = (stack + 3) & 0xffff; \ + if(psr & 0x100) { \ + stack = 0x100 | (stack & 0xff); \ + } \ + } + +#define SET_MEMORY8(addr, val) \ + LOG_DATA_MACRO(addr, val, 8); \ + CYCLES_PLUS_1; \ + stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + if(wstat) { \ + fcycles_tmp1 = fcycles; \ + set_memory8_io_stub((addr), val, stat, &fcycles_tmp1, \ + fplus_x_m1); \ + fcycles = fcycles_tmp1; \ + } else { \ + *ptr = val; \ + } + + +#define SET_MEMORY16(addr, val, in_bank) \ + LOG_DATA_MACRO(addr, val, 16); \ + stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + if((wstat) || (((addr) & 0xff) == 0xff)) { \ + fcycles_tmp1 = fcycles; \ + set_memory16_pieces_stub((addr), (val), \ + &fcycles_tmp1, fplus_1, fplus_x_m1, in_bank); \ + fcycles = fcycles_tmp1; \ + } else { \ + CYCLES_PLUS_2; \ + ptr[0] = (val); \ + ptr[1] = (val) >> 8; \ + } + +#define SET_MEMORY24(addr, val, in_bank) \ + LOG_DATA_MACRO(addr, val, 24); \ + stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + if((wstat) || (((addr) & 0xfe) == 0xfe)) { \ + fcycles_tmp1 = fcycles; \ + set_memory24_pieces_stub((addr), (val), \ + &fcycles_tmp1, fplus_ptr, in_bank); \ + fcycles = fcycles_tmp1; \ + } else { \ + CYCLES_PLUS_3; \ + ptr[0] = (val); \ + ptr[1] = (val) >> 8; \ + ptr[2] = (val) >> 16; \ + } + + +int validate_breakpoint(word32 _addr, const char* check) +{ + if (check==NULL || *check==0) + return 1; + + while (check[0] || check[1]) + { + char p = g_memory_ptr[_addr++]; + if (p!=*check++) return 0; + + } + return 1; +} + +void +check_breakpoints(word32 _addr,enum mode_breakpoint _mode) +{ + int count; + int i; + + count = g_num_breakpoints; + for(i = 0; i < count; i++) { + if((g_breakpts[i].addr & 0xffffff) == _addr + && g_breakpts[i].mode & _mode) + { + + if (!validate_breakpoint(_addr,g_breakpts[i].check)) + continue ; + + if (g_breakpts[i].mode & BRK_MESSAGE) + { + + const char* msg = g_breakpts[i].patch; + if (g_driver.x_post_event) + g_driver.x_post_event(msg); + } + + if (g_breakpts[i].mode & BRK_SLOWSPEED) + { + g_moremem.g_c036_val_speed &= ~0x80; + } + if (g_breakpts[i].mode & BRK_DEFAULTSPEED) + { + g_moremem.g_c036_val_speed |= 0x80; + } + + if (g_breakpts[i].mode & BRK_PATCH) + { + const char*s = g_breakpts[i].patch; + if (s) + { + printf("patching.."); + while(*s) + { + #define READC(C) (C<='9'?C-'0':C<='Z'?C-'A'+10:C-'a'+10) + #define READX(P) READC(*P)*16+READC(*(P+1)) + int a = 0; + while(*s && *s!=':') + { + a = a*256+READX(s); + s+=2; + } + s++; + while(*s && *s!=';') + { + byte b = READX(s); + s+=2; + g_memory_ptr[a++]=b; + } + if (*s) s++; + } + g_breakpts[i].mode = (enum mode_breakpoint)( g_breakpts[i].mode & ~BRK_PATCH); + + } + } + if (g_breakpts[i].mode & BRK_STOP) + halt2_printf("Hit breakpoint at %06x\n", _addr); + } + } +} + +word32 +get_memory8_io_stub(word32 addr, byte *stat, double *fcycs_ptr, + double fplus_x_m1) +{ + double fcycles; + word32 wstat; + byte *ptr; + + wstat = PTR2WORD(stat) & 0xff; + if(wstat & BANK_BREAK) { + check_breakpoints(addr,BRK_READ); + } + fcycles = *fcycs_ptr; + if(wstat & BANK_IO2_TMP) { + FCYCLES_ROUND; + *fcycs_ptr = fcycles; + return get_memory_io((addr), fcycs_ptr); + } else { + ptr = stat - wstat + (addr & 0xff); + return *ptr; + } +} + +word32 +get_memory16_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, + Fplus *fplus_ptr, int in_bank) +{ + byte *ptr; + double fcycles, fcycles_tmp1; + double fplus_1; + double fplus_x_m1; + word32 addrp1; + word32 wstat; + word32 addr_latch; + word32 ret; + word32 tmp1; + + fcycles = *fcycs_ptr; + fplus_1 = fplus_ptr->plus_1; + fplus_x_m1 = fplus_ptr->plus_x_minus_1; + GET_MEMORY8(addr, tmp1); + addrp1 = addr + 1; + if(in_bank) { + addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff); + } + GET_MEMORY8(addrp1, ret); + *fcycs_ptr = fcycles; + return (ret << 8) + (tmp1); +} + +word32 +get_memory24_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, + Fplus *fplus_ptr, int in_bank) +{ + byte *ptr; + double fcycles, fcycles_tmp1; + double fplus_1; + double fplus_x_m1; + word32 addrp1, addrp2; + word32 wstat; + word32 addr_latch; + word32 ret; + word32 tmp1; + word32 tmp2; + + fcycles = *fcycs_ptr; + fplus_1 = fplus_ptr->plus_1; + fplus_x_m1 = fplus_ptr->plus_x_minus_1; + GET_MEMORY8(addr, tmp1); + addrp1 = addr + 1; + if(in_bank) { + addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff); + } + GET_MEMORY8(addrp1, tmp2); + addrp2 = addr + 2; + if(in_bank) { + addrp2 = (addr & 0xff0000) + (addrp2 & 0xffff); + } + GET_MEMORY8(addrp2, ret); + *fcycs_ptr = fcycles; + return (ret << 16) + (tmp2 << 8) + tmp1; +} + +void +set_memory8_io_stub(word32 addr, word32 val, byte *stat, double *fcycs_ptr, + double fplus_x_m1) +{ + double fcycles; + word32 setmem_tmp1; + word32 tmp1, tmp2; + byte *ptr; + word32 wstat; + + /* + if (Verbose) + { + if ( (addr >0x2000 && addr < 0x4000) && !(g_moremem.g_c068_statereg & 0x40)) + { + printf("writing page 0\n"); + set_halt(HALT_WANTTOBRK); + Verbose=0; + } + + if ( (addr >0x4000 && addr < 0x6000) && (g_moremem.g_c068_statereg & 0x40)) + { + printf("writing page 1\n"); + set_halt(HALT_WANTTOBRK); + Verbose=0; + + } + } + */ + + + wstat = PTR2WORD(stat) & 0xff; + /* + if(wstat & (1 << (31 - BANK_BREAK_BIT))) { + check_breakpoints(addr,BRK_WRITE); + } + */ + ptr = stat - wstat + ((addr) & 0xff); \ + fcycles = *fcycs_ptr; + if(wstat & (1 << (31 - BANK_IO2_BIT))) { + FCYCLES_ROUND; + *fcycs_ptr = fcycles; + set_memory_io((addr), val, fcycs_ptr); + } else if(wstat & (1 << (31 - BANK_SHADOW_BIT))) { + FCYCS_PTR_FCYCLES_ROUND_SLOW; + tmp1 = (addr & 0xffff); + setmem_tmp1 = g_slow_memory_ptr[tmp1]; + *ptr = val; + if(setmem_tmp1 != ((val) & 0xff)) { + g_slow_memory_ptr[tmp1] = val; + s_video.slow_mem_changed[tmp1 >> CHANGE_SHIFT] |= (1 << (31-((tmp1 >> SHIFT_PER_CHANGE) & 0x1f))); + } + } else if(wstat & (1 << (31 - BANK_SHADOW2_BIT))) { + FCYCS_PTR_FCYCLES_ROUND_SLOW; + tmp2 = (addr & 0xffff); + tmp1 = 0x10000 + tmp2; + setmem_tmp1 = g_slow_memory_ptr[tmp1]; + *ptr = val; + if(setmem_tmp1 != ((val) & 0xff)) { + g_slow_memory_ptr[tmp1] = val; + s_video.slow_mem_changed[tmp2 >>CHANGE_SHIFT] |= (1 <<(31-((tmp2 >> SHIFT_PER_CHANGE) & 0x1f))); + } + } else { + /* breakpoint only */ + *ptr = val; + } + // wstat = PTR2WORD(stat) & 0xff; + if(wstat & (1 << (31 - BANK_BREAK_BIT))) { + check_breakpoints(addr,BRK_WRITE); + } +} + +void +set_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, + double fplus_1, double fplus_x_m1, int in_bank) +{ + byte *ptr; + byte *stat; + double fcycles, fcycles_tmp1; + word32 addrp1; + word32 wstat; + + fcycles = *fcycs_ptr; + SET_MEMORY8(addr, val); + addrp1 = addr + 1; + if(in_bank) { + addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff); + } + SET_MEMORY8(addrp1, val >> 8); + + *fcycs_ptr = fcycles; +} + +void +set_memory24_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, + Fplus *fplus_ptr, int in_bank) +{ + byte *ptr; + byte *stat; + double fcycles, fcycles_tmp1; + double fplus_1; + double fplus_x_m1; + word32 addrp1, addrp2; + word32 wstat; + + fcycles = *fcycs_ptr; + fplus_1 = fplus_ptr->plus_1; + fplus_x_m1 = fplus_ptr->plus_x_minus_1; + SET_MEMORY8(addr, val); + addrp1 = addr + 1; + if(in_bank) { + addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff); + } + SET_MEMORY8(addrp1, val >> 8); + addrp2 = addr + 2; + if(in_bank) { + addrp2 = (addr & 0xff0000) + (addrp2 & 0xffff); + } + SET_MEMORY8(addrp2, val >> 16); + + *fcycs_ptr = fcycles; +} + + +word32 +get_memory_c(word32 addr, int cycs) +{ + byte *stat; + byte *ptr; + double fcycles, fcycles_tmp1; + double fplus_1; + double fplus_x_m1; + word32 addr_latch; + word32 wstat; + word32 ret; + + fcycles = 0; + fplus_1 = 0; + fplus_x_m1 = 0; + GET_MEMORY8(addr, ret); + return ret; +} + +word32 +get_memory16_c(word32 addr, int cycs) +{ + double fcycs; + + fcycs = 0; + return get_memory_c(addr, (int)fcycs) + + (get_memory_c(addr+1, (int)fcycs) << 8); +} + +word32 +get_memory24_c(word32 addr, int cycs) +{ + double fcycs; + + fcycs = 0; + return get_memory_c(addr, (int)fcycs) + + (get_memory_c(addr+1, (int)fcycs) << 8) + + (get_memory_c(addr+2, (int)fcycs) << 16); +} + +void +set_memory_c(word32 addr, word32 val, int cycs) +{ + byte *stat; + byte *ptr; + double fcycles, fcycles_tmp1; + double fplus_1; + double fplus_x_m1; + word32 wstat; + + fcycles = g_sim65816.g_cur_dcycs - g_sim65816.g_last_vbl_dcycs; + fplus_1 = 0; + fplus_x_m1 = 0; + SET_MEMORY8(addr, val); +} + +void +set_memory16_c(word32 addr, word32 val, int cycs) +{ + byte *stat; + byte *ptr; + double fcycles, fcycles_tmp1; + double fplus_1, fplus_2; + double fplus_x_m1; + word32 wstat; + + fcycles = g_sim65816.g_cur_dcycs - g_sim65816.g_last_vbl_dcycs; + fplus_1 = 0; + fplus_2 = 0; + fplus_x_m1 = 0; + SET_MEMORY16(addr, val, 0); +} + +void +set_memory24_c(word32 addr, word32 val, int cycs) +{ + set_memory_c(addr, val, 0); + set_memory_c(addr + 1, val >> 8, 0); + set_memory_c(addr + 2, val >> 16, 0); +} + +word32 +do_adc_sbc8(word32 in1, word32 in2, word32 psr, int sub) +{ + word32 sum, carry, overflow; + word32 zero; + int decimal; + + overflow = 0; + decimal = psr & 8; + if(sub) { + in2 = (in2 ^ 0xff); + } + if(!decimal) { + sum = (in1 & 0xff) + in2 + (psr & 1); + overflow = ((sum ^ in2) >> 1) & 0x40; + } else { + /* decimal */ + sum = (in1 & 0xf) + (in2 & 0xf) + (psr & 1); + if(sub) { + if(sum < 0x10) { + sum = (sum - 0x6) & 0xf; + } + } else { + if(sum >= 0xa) { + sum = (sum - 0xa) | 0x10; + } + } + + sum = (in1 & 0xf0) + (in2 & 0xf0) + sum; + overflow = ((sum >> 2) ^ (sum >> 1)) & 0x40; + if(sub) { + if(sum < 0x100) { + sum = (sum + 0xa0) & 0xff; + } + } else { + if(sum >= 0xa0) { + sum += 0x60; + } + } + } + + zero = ((sum & 0xff) == 0); + carry = (sum >= 0x100); + if((in1 ^ in2) & 0x80) { + overflow = 0; + } + + psr = psr & (~0xc3); + psr = psr + (sum & 0x80) + overflow + (zero << 1) + carry; + + return (psr << 16) + (sum & 0xff); +} + +word32 +do_adc_sbc16(word32 in1, word32 in2, word32 psr, int sub) +{ + word32 sum, carry, overflow; + word32 tmp1, tmp2; + word32 zero; + int decimal; + + overflow = 0; + decimal = psr & 8; + if(!decimal) { + if(sub) { + in2 = (in2 ^ 0xffff); + } + sum = in1 + in2 + (psr & 1); + overflow = ((sum ^ in2) >> 9) & 0x40; + } else { + /* decimal */ + if(sub) { + tmp1 = do_adc_sbc8(in1 & 0xff, in2 & 0xff, psr, sub); + psr = (tmp1 >> 16); + tmp2 = do_adc_sbc8((in1 >> 8) & 0xff, + (in2 >> 8) & 0xff, psr, sub); + in2 = (in2 ^ 0xfffff); + } else { + tmp1 = do_adc_sbc8(in1 & 0xff, in2 & 0xff, psr, sub); + psr = (tmp1 >> 16); + tmp2 = do_adc_sbc8((in1 >> 8) & 0xff, + (in2 >> 8) &0xff, psr, sub); + } + sum = ((tmp2 & 0xff) << 8) + (tmp1 & 0xff) + + (((tmp2 >> 16) & 1) << 16); + overflow = (tmp2 >> 16) & 0x40; + } + + zero = ((sum & 0xffff) == 0); + carry = (sum >= 0x10000); + if((in1 ^ in2) & 0x8000) { + overflow = 0; + } + + psr = psr & (~0xc3); + psr = psr + ((sum & 0x8000) >> 8) + overflow + (zero << 1) + carry; + + return (psr << 16) + (sum & 0xffff); +} + +/* +// moved to moremem +int g_ret1; +int g_ret2; +*/ + + +void fixed_memory_ptrs_init() +{ + /* set g_slow_memory_ptr, g_rom_fc_ff_ptr, g_dummy_memory1_ptr, */ + /* and rom_cards_ptr */ + + // OG Filled allocated ptr parameter to free the memory + g_slow_memory_ptr = memalloc_align(128*1024, 0, (void**)&g_slow_memory_ptr_allocated); + g_dummy_memory1_ptr = memalloc_align(256, 1024, (void**)&g_dummy_memory1_ptr_allocated); + g_rom_fc_ff_ptr = memalloc_align(256*1024, 512, (void**)&g_rom_fc_ff_ptr_allocated); + g_rom_cards_ptr = memalloc_align(16*256, 256, (void**)&g_rom_cards_ptr_allocated); + + if (g_driver.x_fixed_memory_ptr!=NULL) + g_driver.x_fixed_memory_ptr(); + +#if 0 + printf("g_memory_ptr: %08x, dummy_mem: %08x, slow_mem_ptr: %08x\n", + (word32)g_memory_ptr, (word32)g_dummy_memory1_ptr, + (word32)g_slow_memory_ptr); + printf("g_rom_fc_ff_ptr: %08x, g_rom_cards_ptr: %08x\n", + (word32)g_rom_fc_ff_ptr, (word32)g_rom_cards_ptr); + printf("page_info_rd = %08x, page_info_wr end = %08x\n", + (word32)&(page_info_rd_wr[0]), + (word32)&(page_info_rd_wr[PAGE_INFO_PAD_SIZE+0x1ffff].rd_wr)); +#endif +} + +// OG added fixed_memory_ptrs_shut +void fixed_memory_ptrs_shut() +{ + + free(g_slow_memory_ptr_allocated); + free(g_dummy_memory1_ptr_allocated); + free(g_rom_fc_ff_ptr_allocated); + free(g_rom_cards_ptr_allocated); + g_slow_memory_ptr=g_slow_memory_ptr_allocated= NULL; + g_dummy_memory1_ptr = g_dummy_memory1_ptr_allocated = NULL; + g_rom_fc_ff_ptr = g_rom_fc_ff_ptr_allocated = NULL; + g_rom_cards_ptr = g_rom_cards_ptr = NULL; +} + + +word32 +get_itimer() +{ +#if defined(__i386) && defined(__GNUC__) + /* Here's my bad ia32 asm code to do rdtsc */ + /* Linux source uses: */ + /* asm volatile("rdtsc" : "=a"(ret) : : "edx"); */ + /* asm volatile("rdtsc" : "=%eax"(ret) : : "%edx"); */ + + /* GCC bug report 2001-03/msg00786.html used: */ + /*register word64 dtmp; */ + /*asm volatile ("rdtsc" : "=A" (dtmp)); */ + /*return (word32)dtmp; */ + + register word32 ret; + + asm volatile ("rdtsc;movl %%eax,%0" : "=r"(ret) : : "%eax","%edx"); + + return ret; +#else +# if defined(__POWERPC__) && defined(__GNUC__) + register word32 ret; + + asm volatile ("mftb %0" : "=r"(ret)); + return ret; +# else + return 0; +# endif +#endif +} + +void +set_halt_act(int val) +{ + if(val == 1 && r_sim65816.g_ignore_halts && !r_sim65816.g_user_halt_bad) { + g_sim65816.g_code_red++; + } else { + g_sim65816.halt_sim |= val; + g_sim65816.g_fcycles_stop = (double)0.0; + } +} + +void +clr_halt_act() +{ + g_sim65816.halt_sim = 0; +} + +word32 +get_remaining_operands(word32 addr, word32 opcode, word32 psr, Fplus *fplus_ptr) +{ + byte *stat; + byte *ptr; + double fcycles, fcycles_tmp1; + double fplus_1, fplus_2, fplus_3; + double fplus_x_m1; + word32 addr_latch; + word32 wstat; + word32 save_addr; + word32 arg; + word32 addrp1; + int size; + + fcycles = 0; + fplus_1 = 0; + fplus_2 = 0; + fplus_3 = 0; + fplus_x_m1 = 0; + + size = size_tab[opcode]; + + addrp1 = (addr & 0xff0000) + ((addr + 1) & 0xffff); + switch(size) { + case 0: + arg = 0; /* no args */ + break; + case 1: + GET_MEMORY8(addrp1, arg); + break; /* 1 arg, already done */ + case 2: + GET_MEMORY16(addrp1, arg, 1); + break; + case 3: + GET_MEMORY24(addrp1, arg, 1); + break; + case 4: + if(psr & 0x20) { + GET_MEMORY8(addrp1, arg); + } else { + GET_MEMORY16(addrp1, arg, 1); + } + break; + case 5: + if(psr & 0x10) { + GET_MEMORY8(addrp1, arg); + } else { + GET_MEMORY16(addrp1, arg, 1); + } + break; + default: + printf("Unknown size: %d\n", size); + arg = 0; + x_exit(-2); + } + + return arg; +} + +#define FETCH_OPCODE \ + addr = kpc; \ + CYCLES_PLUS_2; \ + stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \ + wstat = PTR2WORD(stat) & 0xff; \ + ptr = stat - wstat + ((addr) & 0xff); \ + arg_ptr = ptr; \ + opcode = *ptr; \ + if((wstat & (1 << (31-BANK_IO_BIT))) || ((addr & 0xff) > 0xfc)) {\ + if(wstat & BANK_BREAK) { \ + check_breakpoints(addr,BRK_X); \ + } \ + if((addr & 0xfffff0) == 0x00c700) { \ + if(addr == 0xc700) { \ + FINISH(RET_C700, 0); \ + } else if(addr == 0xc70a) { \ + FINISH(RET_C70A, 0); \ + } else if(addr == 0xc70d) { \ + FINISH(RET_C70D, 0); \ + } \ + } \ + if(wstat & (1 << (31 - BANK_IO2_BIT))) { \ + FCYCLES_ROUND; \ + fcycles_tmp1 = fcycles; \ + opcode = get_memory_io((addr), &fcycles_tmp1); \ + fcycles = fcycles_tmp1; \ + } else { \ + opcode = *ptr; \ + } \ + arg = get_remaining_operands(addr, opcode, psr, fplus_ptr);\ + arg_ptr = (byte *)&tmp_bytes; \ + arg_ptr[1] = arg; \ + arg_ptr[2] = arg >> 8; \ + arg_ptr[3] = arg >> 16; \ + } + +#ifdef _DEBUG + word32 kpc; +#endif + +int +enter_engine(Engine_reg *engine_ptr) +{ + register byte *ptr; + byte *arg_ptr; + Pc_log *tmp_pc_ptr; + byte *stat; + word32 wstat; + word32 arg; +#ifndef _DEBUG + register word32 kpc; +#endif + register word32 acc; + register word32 xreg; + register word32 yreg; + word32 stack; + word32 dbank; + register word32 direct; + register word32 psr; + register word32 zero; + register word32 neg; + word32 getmem_tmp; + word32 save_addr; + word32 pull_tmp; + word32 tmp_bytes; + double fcycles; + Fplus *fplus_ptr; + double fplus_1; + double fplus_2; + double fplus_3; + double fplus_x_m1; + double fcycles_tmp1; + + word32 opcode; + register word32 addr; + word32 addr_latch; + word32 tmp1, tmp2; + + + tmp_pc_ptr = 0; + + kpc = engine_ptr->kpc; + acc = engine_ptr->acc; + xreg = engine_ptr->xreg; + yreg = engine_ptr->yreg; + stack = engine_ptr->stack; + dbank = engine_ptr->dbank; + direct = engine_ptr->direct; + psr = engine_ptr->psr; + fcycles = engine_ptr->fcycles; + fplus_ptr = engine_ptr->fplus_ptr; + zero = !(psr & 2); + neg = (psr >> 7) & 1; + + fplus_1 = fplus_ptr->plus_1; + fplus_2 = fplus_ptr->plus_2; + fplus_3 = fplus_ptr->plus_3; + fplus_x_m1 = fplus_ptr->plus_x_minus_1; + + g_moremem.g_ret1 = 0; + g_moremem.g_ret2 = 0; + +recalc_accsize: + if(psr & 0x20) { + while(fcycles <= g_sim65816.g_fcycles_stop) { +#if 0 + if((neg & ~1) || (psr & (~0x1ff))) { + halt_printf("psr = %04x\n", psr); + } +#endif + + FETCH_OPCODE; + + LOG_PC_MACRO(); + + switch(opcode) { + default: + halt_printf("acc8 unk op: %02x\n", opcode); + arg = 9 +#define ACC8 +#include "defs_instr.h" + * 2; + break; +#include "8inst_c.h" + break; + } + } + } else { + while(fcycles <= g_sim65816.g_fcycles_stop) { + FETCH_OPCODE; + LOG_PC_MACRO(); + + switch(opcode) { + default: + halt_printf("acc16 unk op: %02x\n", opcode); + arg = 9 +#undef ACC8 +#include "defs_instr.h" + * 2; + break; +#include "16inst_c.h" + break; + } + } + } + +finish: + engine_ptr->kpc = kpc; + engine_ptr->acc = acc; + engine_ptr->xreg = xreg; + engine_ptr->yreg = yreg; + engine_ptr->stack = stack; + engine_ptr->dbank = dbank; + engine_ptr->direct = direct; + engine_ptr->fcycles = fcycles; + + psr = psr & (~0x82); + psr |= (neg << 7); + psr |= ((!zero) << 1); + + engine_ptr->psr = psr; + + return (g_moremem.g_ret1 << 28) + g_moremem.g_ret2; +} + + +int g_engine_c_mode = 1; + +int defs_instr_start_8 = 0; +int defs_instr_end_8 = 0; +int defs_instr_start_16 = 0; +int defs_instr_end_16 = 0; +int op_routs_start = 0; +int op_routs_end = 0; + + diff --git a/kegs/Src/graphcounter.h b/kegs/Src/graphcounter.h new file mode 100644 index 0000000..01cd49a --- /dev/null +++ b/kegs/Src/graphcounter.h @@ -0,0 +1,53 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#if defined(_DEBUG) && defined(_WIN32) +//#define ENABLE_GRAPH +#endif + +#if defined(USE_RASTER) && defined(_DEBUG) +#define BORDER_SCAN +#endif + +#ifdef BORDER_SCAN +void change_border(int,int); +void draw_border(); +void reset_border(); +#define RESET_BORDER() reset_border() +#define CHANGE_BORDER(ID,X) change_border(ID,X) +#define DRAW_BORDER() draw_border() +#else +#define CHANGE_BORDER(ID,X) +#define DRAW_BORDER() +#define RESET_BORDER() + +#endif + + +#ifdef ENABLE_GRAPH + +#define NB_GRAPH 4 +#define NB_GRAPH_VALUES 300 +#define NB_GRAPH_HEIGHT 100 + +class s_graph +{ + float min[NB_GRAPH]; + float max[NB_GRAPH]; + float ref[NB_GRAPH]; + int color[NB_GRAPH]; + float values[NB_GRAPH][NB_GRAPH_VALUES]; + +public: + s_graph(); + void add_graph(int _counter, float _value, int _vblcount); + void draw_graph(Kimage* _dest, int _curvbl); +}; + +extern s_graph g_graph; +#endif // ENABLE_GRAPH \ No newline at end of file diff --git a/kegs/Src/iwm.cpp b/kegs/Src/iwm.cpp new file mode 100644 index 0000000..5b8f2ae --- /dev/null +++ b/kegs/Src/iwm.cpp @@ -0,0 +1,2378 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "moremem.h" +#include "sim65816.h" +#include "iwm.h" +#include "config.h" +#include "sound.h" + +s_iwm g_iwm; + +const byte phys_to_dos_sec[] = { + 0x00, 0x07, 0x0e, 0x06, 0x0d, 0x05, 0x0c, 0x04, + 0x0b, 0x03, 0x0a, 0x02, 0x09, 0x01, 0x08, 0x0f +}; + +const byte phys_to_prodos_sec[] = { + 0x00, 0x08, 0x01, 0x09, 0x02, 0x0a, 0x03, 0x0b, + 0x04, 0x0c, 0x05, 0x0d, 0x06, 0x0e, 0x07, 0x0f +}; + + +const byte to_disk_byte[] = { + 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6, + 0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3, +/* 0x10 */ + 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3, +/* 0x20 */ + 0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + 0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec, +/* 0x30 */ + 0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +/*const*/ int g_track_bytes_35[] = { + 0x200*12, + 0x200*11, + 0x200*10, + 0x200*9, + 0x200*8 +}; + +/*const*/ int g_track_nibs_35[] = { + 816*12, + 816*11, + 816*10, + 816*9, + 816*8 +}; + + +/* prototypes for IWM special routs */ +int iwm_read_data_35(Disk *dsk, int fast_disk_emul, double dcycs); +int iwm_read_data_525(Disk *dsk, int fast_disk_emul, double dcycs); +void iwm_write_data_35(Disk *dsk, word32 val, int fast_disk_emul, double dcycs); +void iwm_write_data_525(Disk *dsk, word32 val, int fast_disk_emul,double dcycs); + +void +iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525) +{ + dsk->dcycs_last_read = 0.0; + dsk->name_ptr[0] = 0; + dsk->partition_name[0] = 0; + dsk->partition_num = -1; + dsk->fd = -1; + dsk->force_size = 0; + dsk->image_start = 0; + dsk->image_size = 0; + dsk->smartport = smartport; + dsk->disk_525 = disk_525; + dsk->drive = drive; + dsk->cur_qtr_track = 0; + dsk->image_type = 0; + dsk->vol_num = 254; + dsk->write_prot = 1; + dsk->write_through_to_unix = 0; + dsk->disk_dirty = 0; + dsk->just_ejected = 0; + dsk->last_phase = 0; + dsk->nib_pos = 0; + dsk->num_tracks = 0; + dsk->trks = 0; + +} + +void +disk_set_num_tracks(Disk *dsk, int num_tracks) +{ + int i; + + if(dsk->trks != 0) { + /* This should not be necessary! */ + free(dsk->trks); + halt_printf("Needed to free dsk->trks: %p\n", dsk->trks); + } + dsk->num_tracks = num_tracks; + dsk->trks = (Trk *)malloc(num_tracks * sizeof(Trk)); + + for(i = 0; i < num_tracks; i++) { + dsk->trks[i].dsk = dsk; + dsk->trks[i].nib_area = 0; + dsk->trks[i].track_dirty = 0; + dsk->trks[i].overflow_size = 0; + dsk->trks[i].track_len = 0; + dsk->trks[i].unix_pos = -1; + dsk->trks[i].unix_len = -1; + } +} + +void +iwm_init() +{ + int val; + int i; + + for(i = 0; i < 2; i++) { + iwm_init_drive(&(g_iwm.iwm.drive525[i]), 0, i, 1); + iwm_init_drive(&(g_iwm.iwm.drive35[i]), 0, i, 0); + } + + for(i = 0; i < MAX_C7_DISKS; i++) { + iwm_init_drive(&(g_iwm.iwm.smartport[i]), 1, i, 0); + } + + if(g_iwm.from_disk_byte_valid == 0) { + for(i = 0; i < 256; i++) { + g_iwm.from_disk_byte[i] = -1; + } + for(i = 0; i < 64; i++) { + val = to_disk_byte[i]; + g_iwm.from_disk_byte[val] = i; + } + g_iwm.from_disk_byte_valid = 1; + } else { + halt_printf("iwm_init called twice!\n"); + } + + iwm_reset(); +} + +// OG Added shut function to IWM +// Free the memory, and more important free the open handle onto the disk +void +iwm_shut() +{ + int i; + for(i = 0; i < 2; i++) { + eject_disk(&g_iwm.iwm.drive525[i]); + eject_disk(&g_iwm.iwm.drive35[i]); + } + + for(i = 0; i < MAX_C7_DISKS; i++) { + eject_disk(&g_iwm.iwm.smartport[i]); + } + + g_iwm.from_disk_byte_valid = 0; +} + +void +iwm_reset() +{ + g_iwm.iwm.q6 = 0; + g_iwm.iwm.q7 = 0; + g_iwm.iwm.motor_on = 0; + g_iwm.iwm.motor_on35 = 0; + g_iwm.iwm.motor_off = 0; + g_iwm.iwm.motor_off_vbl_count = 0; + g_iwm.iwm.step_direction35 = 0; + g_iwm.iwm.head35 = 0; + g_iwm.iwm.drive_select = 0; + g_iwm.iwm.iwm_mode = 0; + g_iwm.iwm.enable2 = 0; + g_iwm.iwm.reset = 0; + g_iwm.iwm.iwm_phase[0] = 0; + g_iwm.iwm.iwm_phase[1] = 0; + g_iwm.iwm.iwm_phase[2] = 0; + g_iwm.iwm.iwm_phase[3] = 0; + g_iwm.iwm.previous_write_val = 0; + g_iwm.iwm.previous_write_bits = 0; + + g_iwm.g_iwm_motor_on = 0; + g_moremem.g_c031_disk35 = 0; +} + +void +draw_iwm_status(int line, char *buf) +{ + const char *flag[2][2]; + int apple35_sel; + + flag[0][0] = " "; + flag[0][1] = " "; + flag[1][0] = " "; + flag[1][1] = " "; + + apple35_sel = (g_moremem.g_c031_disk35 >> 6) & 1; + if(g_iwm.g_iwm_motor_on) { + flag[apple35_sel][g_iwm.iwm.drive_select] = "*"; + } + + // OG Pass motorOn information to the hosting program + extern void x_notify_motor_status(int _motorOn,int _slot,int _drive, int _curtrack); + + int curtrack=0; + if (apple35_sel) + curtrack = g_iwm.iwm.drive35[g_iwm.iwm.drive_select].cur_qtr_track ; + else + curtrack = g_iwm.iwm.drive525[g_iwm.iwm.drive_select].cur_qtr_track >> 2 ; + + x_notify_motor_status(g_iwm.g_iwm_motor_on,apple35_sel?5:6,g_iwm.iwm.drive_select+1,curtrack); + + sprintf(buf, "s6d1:%2d%s s6d2:%2d%s s5d1:%2d/%d%s " + "s5d2:%2d/%d%s fast_disk_emul:%d,%d c036:%02x", + g_iwm.iwm.drive525[0].cur_qtr_track >> 2, flag[0][0], + g_iwm.iwm.drive525[1].cur_qtr_track >> 2, flag[0][1], + g_iwm.iwm.drive35[0].cur_qtr_track >> 1, + g_iwm.iwm.drive35[0].cur_qtr_track & 1, flag[1][0], + g_iwm.iwm.drive35[1].cur_qtr_track >> 1, + g_iwm.iwm.drive35[1].cur_qtr_track & 1, flag[1][1], + g_iwm.g_fast_disk_emul, g_iwm.g_slow_525_emul_wr, g_moremem.g_c036_val_speed); + + video_update_status_line(line, buf); +} + + +void +iwm_flush_disk_to_unix(Disk *dsk) +{ + byte buffer[0x4000]; + int num_dirty; + int j; + int ret; + int unix_pos; + int unix_len; + + if(dsk->disk_dirty == 0 || dsk->write_through_to_unix == 0) { + return; + } + + printf("Writing disk %s to Unix\n", dsk->name_ptr); + dsk->disk_dirty = 0; + num_dirty = 0; + + /* Dirty data! */ + for(j = 0; j < dsk->num_tracks; j++) { + + ret = disk_track_to_unix(dsk, j, &(buffer[0])); + + if(ret != 1 && ret != 0) { + printf("iwm_flush_disk_to_unix ret: %d, cannot write " + "image to unix\n", ret); + halt_printf("Adjusting image not to write through!\n"); + dsk->write_through_to_unix = 0; + break; + } + + if(ret != 1) { + /* not at an even track, or not dirty */ + continue; + } + if((j & 3) != 0 && dsk->disk_525) { + halt_printf("Valid data on a non-whole trk: %03x\n", j); + continue; + } + + num_dirty++; + + /* Write it out */ + unix_pos = dsk->trks[j].unix_pos; + unix_len = dsk->trks[j].unix_len; + if(unix_pos < 0 || unix_len < 0x1000) { + halt_printf("Disk:%s trk:%d, unix_pos:%08x, len:%08x\n", + dsk->name_ptr, j, unix_pos, unix_len); + break; + } + + ret = lseek(dsk->fd, unix_pos, SEEK_SET); + if(ret != unix_pos) { + halt_printf("lseek 525: %08x, errno: %d\n", ret, errno); + } + + ret = write(dsk->fd, &(buffer[0]), unix_len); + if(ret != unix_len) { + printf("write: %08x, errno:%d, qtrk: %02x, disk: %s\n", + ret, errno, j, dsk->name_ptr); + } + } + + if(num_dirty == 0) { + halt_printf("Drive %s was dirty, but no track was dirty!\n", + dsk->name_ptr); + } + +} + +/* Check for dirty disk 3 times a second */ + +void +iwm_vbl_update(int doit_3_persec) +{ + Disk *dsk; + int motor_on; + int i; + + if(g_iwm.iwm.motor_on && g_iwm.iwm.motor_off) { + if((word32)g_iwm.iwm.motor_off_vbl_count <= g_sim65816.g_vbl_count) { + printf("Disk timer expired, drive off: %08x\n", + g_sim65816.g_vbl_count); + g_iwm.iwm.motor_on = 0; + g_iwm.iwm.motor_off = 0; + } + } + + if(!doit_3_persec) { + return; + } + + motor_on = g_iwm.iwm.motor_on; + if(g_moremem.g_c031_disk35 & 0x40) { + motor_on = g_iwm.iwm.motor_on35; + } + + if(motor_on == 0 || g_iwm.iwm.motor_off) { + /* Disk not spinning, see if any dirty tracks to flush */ + /* out to Unix */ + for(i = 0; i < 2; i++) { + dsk = &(g_iwm.iwm.drive525[i]); + iwm_flush_disk_to_unix(dsk); + } + for(i = 0; i < 2; i++) { + dsk = &(g_iwm.iwm.drive35[i]); + iwm_flush_disk_to_unix(dsk); + } + } +} + + +void +iwm_show_stats() +{ + printf("IWM stats: q7,q6: %d, %d, reset,enable2: %d,%d, mode: %02x\n", + g_iwm.iwm.q7, g_iwm.iwm.q6, g_iwm.iwm.reset, g_iwm.iwm.enable2, g_iwm.iwm.iwm_mode); + printf("motor: %d,%d, motor35:%d drive: %d, c031:%02x " + "phs: %d %d %d %d\n", + g_iwm.iwm.motor_on, g_iwm.iwm.motor_off, g_iwm.g_iwm_motor_on, + g_iwm.iwm.drive_select, g_moremem.g_c031_disk35, + g_iwm.iwm.iwm_phase[0], g_iwm.iwm.iwm_phase[1], g_iwm.iwm.iwm_phase[2], + g_iwm.iwm.iwm_phase[3]); + printf("g_iwm.iwm.drive525[0].fd: %d, [1].fd: %d\n", + g_iwm.iwm.drive525[0].fd, g_iwm.iwm.drive525[1].fd); + printf("g_iwm.iwm.drive525[0].last_phase: %d, [1].last_phase: %d\n", + g_iwm.iwm.drive525[0].last_phase, g_iwm.iwm.drive525[1].last_phase); +} + +void +iwm_touch_switches(int loc, double dcycs) +{ + Disk *dsk; + int phase; + int on; + int drive; + + if(g_iwm.iwm.reset) { + iwm_printf("IWM under reset: %d, enable2: %d\n", g_iwm.iwm.reset, + g_iwm.iwm.enable2); + } + + on = loc & 1; + drive = g_iwm.iwm.drive_select; + phase = loc >> 1; + if(g_moremem.g_c031_disk35 & 0x40) { + dsk = &(g_iwm.iwm.drive35[drive]); + } else { + dsk = &(g_iwm.iwm.drive525[drive]); + } + + + if(loc < 8) { + /* phase adjustments. See if motor is on */ + + g_iwm.iwm.iwm_phase[phase] = on; + iwm_printf("Iwm phase %d=%d, all phases: %d %d %d %d (%f)\n", + phase, on, g_iwm.iwm.iwm_phase[0], g_iwm.iwm.iwm_phase[1], + g_iwm.iwm.iwm_phase[2], g_iwm.iwm.iwm_phase[3], dcycs); + + if(g_iwm.iwm.motor_on) { + if(g_moremem.g_c031_disk35 & 0x40) { + if(phase == 3 && on) { + iwm_do_action35(dcycs); + } + } else if(on) { + /* Move apple525 head */ + iwm525_phase_change(drive, phase); + } + } + /* See if enable or reset is asserted */ + if(g_iwm.iwm.iwm_phase[0] && g_iwm.iwm.iwm_phase[2]) { + g_iwm.iwm.reset = 1; + iwm_printf("IWM reset active\n"); + } else { + g_iwm.iwm.reset = 0; + } + if(g_iwm.iwm.iwm_phase[1] && g_iwm.iwm.iwm_phase[3]) { + g_iwm.iwm.enable2 = 1; + iwm_printf("IWM ENABLE2 active\n"); + } else { + g_iwm.iwm.enable2 = 0; + } + } else { + /* loc >= 8 */ + switch(loc) { + case 0x8: + iwm_printf("Turning IWM motor off!\n"); + if(g_iwm.iwm.iwm_mode & 0x04) { + /* Turn off immediately */ + g_iwm.iwm.motor_off = 0; + g_iwm.iwm.motor_on = 0; + } else { + /* 1 second delay */ + if(g_iwm.iwm.motor_on && !g_iwm.iwm.motor_off) { + g_iwm.iwm.motor_off = 1; + g_iwm.iwm.motor_off_vbl_count = g_sim65816.g_vbl_count + + 60; + } + } + + if(g_iwm.g_iwm_motor_on || g_iwm.g_slow_525_emul_wr) { + /* recalc current speed */ + set_halt(HALT_EVENT); + } + + g_iwm.g_iwm_motor_on = 0; + g_iwm.g_slow_525_emul_wr = 0; + break; + case 0x9: + iwm_printf("Turning IWM motor on!\n"); + g_iwm.iwm.motor_on = 1; + g_iwm.iwm.motor_off = 0; + + if(g_iwm.g_iwm_motor_on == 0) { + /* recalc current speed */ + set_halt(HALT_EVENT); + } + g_iwm.g_iwm_motor_on = 1; + + break; + case 0xa: + case 0xb: + g_iwm.iwm.drive_select = on; + break; + case 0xc: + case 0xd: + g_iwm.iwm.q6 = on; + break; + case 0xe: + case 0xf: + g_iwm.iwm.q7 = on; + break; + default: + printf("iwm_touch_switches: loc: %02x unknown!\n", loc); + x_exit(2); + } + } + + if(!g_iwm.iwm.q7) { + g_iwm.iwm.previous_write_bits = 0; + } + + if((dcycs > g_iwm.g_dcycs_end_emul_wr) && g_iwm.g_slow_525_emul_wr) { + set_halt(HALT_EVENT); + g_iwm.g_slow_525_emul_wr = 0; + } +} + +void +iwm_move_to_track(Disk *dsk, int new_track) +{ + int disk_525; + int dr; + + disk_525 = dsk->disk_525; + + if(new_track < 0) { + new_track = 0; + } + if(new_track >= dsk->num_tracks) { + if(disk_525) { + new_track = dsk->num_tracks - 4; + } else { + new_track = dsk->num_tracks - 2 + g_iwm.iwm.head35; + } + + if(new_track <= 0) { + new_track = 0; + } + } + + if(dsk->cur_qtr_track != new_track) { + dr = dsk->drive + 1; + if(disk_525) { + iwm_printf("s6d%d Track: %d.%02d\n", dr, + new_track >> 2, 25* (new_track & 3)); + } else { + iwm_printf("s5d%d Track: %d Side: %d\n", dr, + new_track >> 1, new_track & 1); + } + + dsk->cur_qtr_track = new_track; + } +} + +void +iwm525_phase_change(int drive, int phase) +{ + Disk *dsk; + int qtr_track; + int last_phase; + int phase_up; + int phase_down; + int delta; + + phase_up = (phase - 1) & 3; + phase_down = (phase + 1) & 3; + + dsk = &(g_iwm.iwm.drive525[drive]); + last_phase = dsk->last_phase; + + qtr_track = dsk->cur_qtr_track; + + delta = 0; + if(last_phase == phase_up) { + delta = 2; + last_phase = phase; + } else if(last_phase == phase_down) { + delta = -2; + last_phase = phase; + } + + qtr_track += delta; + if(qtr_track < 0) + { +#ifndef ACTIVEGSKARATEKA + if(g_sim65816.g_enable_disk_sound) + play_sound(SOUND_SPIN_UP_SEARCH_1); +#else + extern void x_play_boot_sound(); + x_play_boot_sound(); +#endif + printf("GRIND...GRIND...GRIND\n"); + qtr_track = 0; + last_phase = 0; + } + else + if(qtr_track > 4*34) { + printf("Disk arm moved past track 34, moving it back\n"); + qtr_track = 4*34; + last_phase = 0; + } + + iwm_move_to_track(dsk, qtr_track); + + dsk->last_phase = last_phase; + + iwm_printf("Moving drive to qtr track: %04x (trk:%d.%02d), %d, %d, %d, " + "%d %d %d %d\n", qtr_track, qtr_track>>2, 25*(qtr_track & 3), + phase, delta, last_phase, g_iwm.iwm.iwm_phase[0], + g_iwm.iwm.iwm_phase[1], g_iwm.iwm.iwm_phase[2], g_iwm.iwm.iwm_phase[3]); + + /* sanity check stepping algorithm */ + if((qtr_track & 7) == 0) { + /* check for just access phase 0 */ + if(last_phase != 0 ) { + halt_printf("last_phase: %d!\n", last_phase); + } + } +} + +int +iwm_read_status35(double dcycs) +{ + Disk *dsk; + int drive; + int state; + int tmp; + + drive = g_iwm.iwm.drive_select; + dsk = &(g_iwm.iwm.drive35[drive]); + + if(g_iwm.iwm.motor_on) { + /* Read status */ + state = (g_iwm.iwm.iwm_phase[1] << 3) + (g_iwm.iwm.iwm_phase[0] << 2) + + ((g_moremem.g_c031_disk35 >> 6) & 2) + g_iwm.iwm.iwm_phase[2]; + + iwm_printf("Iwm status read state: %02x\n", state); + + switch(state) { + case 0x00: /* step direction */ + return g_iwm.iwm.step_direction35; + break; + case 0x01: /* lower head activate */ + /* also return instantaneous data from head */ + g_iwm.iwm.head35 = 0; + iwm_move_to_track(dsk, (dsk->cur_qtr_track & (-2))); + return (((int)dcycs) & 1); + break; + case 0x02: /* disk in place */ + /* 1 = no disk, 0 = disk */ + iwm_printf("read disk in place, num_tracks: %d\n", + dsk->num_tracks); + tmp = (dsk->num_tracks <= 0); + return tmp; + break; + case 0x03: /* upper head activate */ + /* also return instantaneous data from head */ + g_iwm.iwm.head35 = 1; + iwm_move_to_track(dsk, (dsk->cur_qtr_track | 1)); + return (((int)dcycs) & 1); + break; + case 0x04: /* disk is stepping? */ + /* 1 = not stepping, 0 = stepping */ + return 1; + break; + case 0x05: /* Unknown function of ROM 03? */ + /* 1 = or $20 into 0xe1/f24+drive, 0 = don't */ + return 1; + break; + case 0x06: /* disk is locked */ + /* 0 = locked, 1 = unlocked */ + return (!dsk->write_prot); + break; + case 0x08: /* motor on */ + /* 0 = on, 1 = off */ + return !g_iwm.iwm.motor_on35; + break; + case 0x09: /* number of sides */ + /* 1 = 2 sides, 0 = 1 side */ + return 1; + break; + case 0x0a: /* at track 0 */ + /* 1 = not at track 0, 0 = there */ + tmp = (dsk->cur_qtr_track != 0); + iwm_printf("Read at track0_35: %d\n", tmp); + return tmp; + break; + case 0x0b: /* disk ready??? */ + /* 0 = ready, 1 = not ready? */ + tmp = !g_iwm.iwm.motor_on35; + iwm_printf("Read disk ready, ret: %d\n", tmp); + return tmp; + break; + case 0x0c: /* disk switched?? */ + /* 0 = not switched, 1 = switched? */ + tmp = (dsk->just_ejected != 0); + iwm_printf("Read disk switched: %d\n", tmp); + return tmp; + break; + case 0x0d: /* false read when ejecting disk */ + return 1; + case 0x0e: /* tachometer */ + halt_printf("Reading tachometer!\n"); + return (((int)dcycs) & 1); + break; + case 0x0f: /* drive installed? */ + /* 0 = drive exists, 1 = no drive */ + if(drive) { + /* pretend no drive 1 */ + return 1; + } + return 0; + break; + default: + halt_printf("Read 3.5 status, state: %02x\n", state); + return 1; + } + } else { + iwm_printf("Read 3.5 status with drive off!\n"); + return 1; + } +} + +void +iwm_do_action35(double dcycs) +{ + Disk *dsk; + int drive; + int state; + + drive = g_iwm.iwm.drive_select; + dsk = &(g_iwm.iwm.drive35[drive]); + + if(g_iwm.iwm.motor_on) { + /* Perform action */ + state = (g_iwm.iwm.iwm_phase[1] << 3) + (g_iwm.iwm.iwm_phase[0] << 2) + + ((g_moremem.g_c031_disk35 >> 6) & 2) + g_iwm.iwm.iwm_phase[2]; + switch(state) { + case 0x00: /* Set step direction inward */ + /* towards higher tracks */ + g_iwm.iwm.step_direction35 = 0; + iwm_printf("Iwm set step dir35 = 0\n"); + break; + case 0x01: /* Set step direction outward */ + /* towards lower tracks */ + g_iwm.iwm.step_direction35 = 1; + iwm_printf("Iwm set step dir35 = 1\n"); + break; + case 0x03: /* reset disk-switched flag? */ + iwm_printf("Iwm reset disk switch\n"); + dsk->just_ejected = 0; + /* set_halt(1); */ + break; + case 0x04: /* step disk */ + if(g_iwm.iwm.step_direction35) { + iwm_move_to_track(dsk, dsk->cur_qtr_track - 2); + } else { + iwm_move_to_track(dsk, dsk->cur_qtr_track + 2); + } + break; + case 0x08: /* turn motor on */ + iwm_printf("Iwm set motor_on35 = 1\n"); + g_iwm.iwm.motor_on35 = 1; + break; + case 0x09: /* turn motor off */ + iwm_printf("Iwm set motor_on35 = 0\n"); + g_iwm.iwm.motor_on35 = 0; + break; + case 0x0d: /* eject disk */ + eject_disk(dsk); + // OG : pass eject info to the COntrol (ActiveX specific) + { + extern void x_notify_disk_ejection(int slot,int disk); + x_notify_disk_ejection(dsk->disk_525?6:5,dsk->drive+1); + } + break; + case 0x02: + case 0x07: + case 0x0b: /* hacks to allow AE 1.6MB driver to not crash me */ + break; + default: + halt_printf("Do 3.5 action, state: %02x\n", state); + return; + } + } else { + halt_printf("Set 3.5 status with drive off!\n"); + return; + } +} + +int +iwm_read_c0ec(double dcycs) +{ + Disk *dsk; + int drive; + + g_iwm.iwm.q6 = 0; + + if(g_iwm.iwm.q7 == 0 && g_iwm.iwm.enable2 == 0 && g_iwm.iwm.motor_on) { + drive = g_iwm.iwm.drive_select; + if(g_moremem.g_c031_disk35 & 0x40) { + dsk = &(g_iwm.iwm.drive35[drive]); + return iwm_read_data_35(dsk, g_iwm.g_fast_disk_emul, dcycs); + } else { + dsk = &(g_iwm.iwm.drive525[drive]); + return iwm_read_data_525(dsk, g_iwm.g_fast_disk_emul, dcycs); + } + + } + + return read_iwm(0xc, dcycs); +} + + +int +read_iwm(int loc, double dcycs) +{ + Disk *dsk; + word32 status; + double diff_dcycs; + double dcmp; + int on; + int state; + int drive; + int val; + + loc = loc & 0xf; + on = loc & 1; + + if(loc == 0xc) { + g_iwm.iwm.q6 = 0; + } else { + iwm_touch_switches(loc, dcycs); + } + + state = (g_iwm.iwm.q7 << 1) + g_iwm.iwm.q6; + drive = g_iwm.iwm.drive_select; + if(g_moremem.g_c031_disk35 & 0x40) { + dsk = &(g_iwm.iwm.drive35[drive]); + } else { + dsk = &(g_iwm.iwm.drive525[drive]); + } + + if(on) { + /* odd address, return 0 */ + return 0; + } else { + /* even address */ + switch(state) { + case 0x00: /* q7 = 0, q6 = 0 */ + if(g_iwm.iwm.enable2) { + return iwm_read_enable2(dcycs); + } else { + if(g_iwm.iwm.motor_on) { + return iwm_read_data(dsk, + g_iwm.g_fast_disk_emul, dcycs); + } else { + iwm_printf("read iwm st 0, m off!\n"); +/* HACK!!!! */ + return 0xff; + //return (((int)dcycs) & 0x7f) + 0x80; + } + } + break; + case 0x01: /* q7 = 0, q6 = 1 */ + /* read IWM status reg */ + if(g_iwm.iwm.enable2) { + iwm_printf("Read status under enable2: 1\n"); + status = 1; + } else { + if(g_moremem.g_c031_disk35 & 0x40) { + status = iwm_read_status35(dcycs); + } else { + status = dsk->write_prot; + } + } + + val = (status << 7) + (g_iwm.iwm.motor_on << 5) + + g_iwm.iwm.iwm_mode; + iwm_printf("Read status: %02x\n", val); + + return val; + break; + case 0x02: /* q7 = 1, q6 = 0 */ + /* read handshake register */ + if(g_iwm.iwm.enable2) { + return iwm_read_enable2_handshake(dcycs); + } else { + status = 0xc0; + diff_dcycs = dcycs - dsk->dcycs_last_read; + dcmp = 16.0; + if(dsk->disk_525 == 0) { + dcmp = 32.0; + } + if(diff_dcycs > dcmp) { + iwm_printf("Write underrun!\n"); + iwm_printf("cur: %f, dc_last: %f\n", + dcycs, dsk->dcycs_last_read); + status = status & 0xbf; + } + return status; + } + break; + case 0x03: /* q7 = 1, q6 = 1 */ + halt_printf("read g_iwm.iwm state 3!\n"); + return 0; + break; + } + + } + halt_printf("Got to end of read_iwm, loc: %02x!\n", loc); + + return 0; +} + +void +write_iwm(int loc, int val, double dcycs) +{ + Disk *dsk; + int on; + int state; + int drive; + int fast_writes; + + loc = loc & 0xf; + on = loc & 1; + + iwm_touch_switches(loc, dcycs); + + state = (g_iwm.iwm.q7 << 1) + g_iwm.iwm.q6; + drive = g_iwm.iwm.drive_select; + fast_writes = g_iwm.g_fast_disk_emul; + if(g_moremem.g_c031_disk35 & 0x40) { + dsk = &(g_iwm.iwm.drive35[drive]); + } else { + dsk = &(g_iwm.iwm.drive525[drive]); + fast_writes = !g_iwm.g_slow_525_emul_wr && fast_writes; + } + + if(on) { + /* odd address, write something */ + if(state == 0x03) { + /* q7, q6 = 1,1 */ + if(g_iwm.iwm.motor_on) { + if(g_iwm.iwm.enable2) { + iwm_write_enable2(val, dcycs); + } else { + iwm_write_data(dsk, val, + fast_writes, dcycs); + } + } else { + /* write mode register */ + val = val & 0x1f; + g_iwm.iwm.iwm_mode = val; + if(val != 0 && val != 0x0f && val != 0x07 && + val != 0x04 && val != 0x0b) { + halt_printf("set iwm_mode:%02x!\n",val); + } + } + } else { + if(g_iwm.iwm.enable2) { + iwm_write_enable2(val, dcycs); + } else { +#if 0 +// Flobynoid writes to 0xc0e9 causing these messages... + printf("Write iwm1, st: %02x, loc: %x: %02x\n", + state, loc, val); +#endif + } + } + return; + } else { + /* even address */ + if(g_iwm.iwm.enable2) { + iwm_write_enable2(val, dcycs); + } else { + iwm_printf("Write iwm2, st: %02x, loc: %x: %02x\n", + state, loc, val); + } + return; + } + + return; +} + + + +int +iwm_read_enable2(double dcycs) +{ + iwm_printf("Read under enable2!\n"); + return 0xff; +} + + +int +iwm_read_enable2_handshake(double dcycs) +{ + int val; + + iwm_printf("Read handshake under enable2!\n"); + + val = 0xc0; + g_iwm.g_cnt_enable2_handshake++; + if(g_iwm.g_cnt_enable2_handshake > 3) { + g_iwm.g_cnt_enable2_handshake = 0; + val = 0x80; + } + + return val; +} + +void +iwm_write_enable2(int val, double dcycs) +{ + iwm_printf("Write under enable2: %02x!\n", val); + + return; +} + +int +iwm_read_data(Disk *dsk, int fast_disk_emul, double dcycs) +{ + if(dsk->disk_525) { + return iwm_read_data_525(dsk, fast_disk_emul, dcycs); + } else { + return iwm_read_data_35(dsk, fast_disk_emul, dcycs); + } +} + +void +iwm_write_data(Disk *dsk, word32 val, int fast_disk_emul, double dcycs) +{ + if(dsk->disk_525) { + iwm_write_data_525(dsk, val, fast_disk_emul, dcycs); + } else { + iwm_write_data_35(dsk, val, fast_disk_emul, dcycs); + } +} + +#undef IWM_READ_ROUT +#undef IWM_WRITE_ROUT +#undef IWM_CYC_MULT +#undef IWM_DISK_525 + +#define IWM_READ_ROUT iwm_read_data_35 +#define IWM_WRITE_ROUT iwm_write_data_35 +#define IWM_CYC_MULT 1 +#define IWM_DISK_525 0 + +#define INCLUDE_IWM_RCSID_C +#include "iwm_35_525.h" +#undef INCLUDE_IWM_RCSID_C + +#undef IWM_READ_ROUT +#undef IWM_WRITE_ROUT +#undef IWM_CYC_MULT +#undef IWM_DISK_525 + +#define IWM_READ_ROUT iwm_read_data_525 +#define IWM_WRITE_ROUT iwm_write_data_525 +#define IWM_CYC_MULT 2 +#define IWM_DISK_525 1 +#include "iwm_35_525.h" + +#undef IWM_READ_ROUT +#undef IWM_WRITE_ROUT +#undef IWM_CYC_MULT +#undef IWM_DISK_525 + + + + + +/* c600 */ +void +sector_to_partial_nib(byte *in, byte *nib_ptr) +{ + byte *aux_buf; + byte *nib_out; + int val; + int val2; + int x; + int i; + + /* Convert 256(+1) data bytes to 342+1 disk nibbles */ + + aux_buf = nib_ptr; + nib_out = nib_ptr + 0x56; + + for(i = 0; i < 0x56; i++) { + aux_buf[i] = 0; + } + + x = 0x55; + for(i = 0x101; i >= 0; i--) { + val = in[i]; + if(i >= 0x100) { + val = 0; + } + val2 = (aux_buf[x] << 1) + (val & 1); + val = val >> 1; + val2 = (val2 << 1) + (val & 1); + val = val >> 1; + nib_out[i] = val; + aux_buf[x] = val2; + x--; + if(x < 0) { + x = 0x55; + } + } +} + + +int +disk_unnib_4x4(Disk *dsk) +{ + int val1; + int val2; + + val1 = iwm_read_data(dsk, 1, 0); + val2 = iwm_read_data(dsk, 1, 0); + + return ((val1 << 1) + 1) & val2; +} + +int +iwm_denib_track525(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf) +{ + byte aux_buf[0x80]; + byte *buf; + int sector_done[16]; + int num_sectors_done; + int track_len; + int vol, track, phys_sec, log_sec, cksum; + int val; + int val2; + int prev_val; + int x; + int my_nib_cnt; + int save_qtr_track; + int save_nib_pos; + int tmp_nib_pos; + int status; + int i; + + save_qtr_track = dsk->cur_qtr_track; + save_nib_pos = dsk->nib_pos; + + iwm_move_to_track(dsk, qtr_track); + + dsk->nib_pos = 0; + g_iwm.g_fast_disk_unnib = 1; + + track_len = trk->track_len; + + for(i = 0; i < 16; i++) { + sector_done[i] = 0; + } + + num_sectors_done = 0; + + val = 0; + status = -1; + my_nib_cnt = 0; + while(my_nib_cnt++ < 2*track_len) { + /* look for start of a sector */ + if(val != 0xd5) { + val = iwm_read_data(dsk, 1, 0); + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0x96) { + continue; + } + + /* It's a sector start */ + vol = disk_unnib_4x4(dsk); + track = disk_unnib_4x4(dsk); + phys_sec = disk_unnib_4x4(dsk); + if(phys_sec < 0 || phys_sec > 15) { + printf("Track %02x, read sec as %02x\n", qtr_track>>2, + phys_sec); + break; + } + if(dsk->image_type == DSK_TYPE_DOS33) { + log_sec = phys_to_dos_sec[phys_sec]; + } else { + log_sec = phys_to_prodos_sec[phys_sec]; + } + cksum = disk_unnib_4x4(dsk); + if((vol ^ track ^ phys_sec ^ cksum) != 0) { + /* not correct format */ + printf("Track %02x not DOS 3.3 since hdr cksum, %02x " + "%02x %02x %02x\n", + qtr_track>>2, vol, track, phys_sec, cksum); + break; + } + + /* see what sector it is */ + if(track != (qtr_track>>2) || (phys_sec < 0)||(phys_sec > 15)) { + printf("Track %02x bad since track: %02x, sec: %02x\n", + qtr_track>>2, track, phys_sec); + break; + } + + if(sector_done[phys_sec]) { + printf("Already done sector %02x on track %02x!\n", + phys_sec, qtr_track>>2); + break; + } + + /* So far so good, let's do it! */ + val = 0; + i = 0; + while(i < NIBS_FROM_ADDR_TO_DATA) { + i++; + if(val != 0xd5) { + val = iwm_read_data(dsk, 1, 0); + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xad) { + continue; + } + + /* got it, just break */ + break; + } + + if(i >= NIBS_FROM_ADDR_TO_DATA) { + printf("No data header, track %02x, sec %02x\n", + qtr_track>>2, phys_sec); + printf("nib_pos: %08x\n", dsk->nib_pos); + break; + } + + buf = outbuf + 0x100*log_sec; + + /* Data start! */ + prev_val = 0; + for(i = 0x55; i >= 0; i--) { + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area1, val:%02x,val2:%02x\n", + val, val2); + printf(" i:%03x,n_pos:%04x\n", i, dsk->nib_pos); + break; + } + prev_val = val2 ^ prev_val; + aux_buf[i] = prev_val; + } + + /* rest of data area */ + for(i = 0; i < 0x100; i++) { + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area2, read: %02x\n", val); + printf(" nib_pos: %04x\n", dsk->nib_pos); + break; + } + prev_val = val2 ^ prev_val; + buf[i] = prev_val; + } + + /* checksum */ + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area3, read: %02x\n", val); + printf(" nib_pos: %04x\n", dsk->nib_pos); + break; + } + if(val2 != prev_val) { + printf("Bad data cksum, got %02x, wanted: %02x\n", + val2, prev_val); + printf(" nib_pos: %04x\n", dsk->nib_pos); + break; + } + + /* Got this far, data is good, merge aux_buf into buf */ + x = 0x55; + for(i = 0; i < 0x100; i++) { + val = aux_buf[x]; + val2 = (buf[i] << 1) + (val & 1); + val = val >> 1; + val2 = (val2 << 1) + (val & 1); + buf[i] = val2; + val = val >> 1; + aux_buf[x] = val; + x--; + if(x < 0) { + x = 0x55; + } + } + sector_done[phys_sec] = 1; + num_sectors_done++; + if(num_sectors_done >= 16) { + status = 0; + break; + } + } + + tmp_nib_pos = dsk->nib_pos; + iwm_move_to_track(dsk, save_qtr_track); + dsk->nib_pos = save_nib_pos; + g_iwm.g_fast_disk_unnib = 0; + + if(status == 0) { + return 1; + } + + printf("Nibblization not done, %02x sectors found on track %02x\n", + num_sectors_done, qtr_track>>2); + printf("my_nib_cnt: %04x, nib_pos: %04x, trk_len: %04x\n", my_nib_cnt, + tmp_nib_pos, track_len); + for(i = 0; i < 16; i++) { + printf("sector_done[%d] = %d\n", i, sector_done[i]); + } + return -1; +} + +int +iwm_denib_track35(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf) +{ + word32 buf_c00[0x100]; + word32 buf_d00[0x100]; + word32 buf_e00[0x100]; + byte *buf; + word32 tmp_5c, tmp_5d, tmp_5e; + word32 tmp_66, tmp_67; + int sector_done[16]; + int num_sectors_done; + int track_len; + int phys_track, phys_sec, phys_side, phys_capacity, cksum; + int tmp; + int track, side; + int num_sectors; + int val; + int val2; + int x, y; + int carry; + int my_nib_cnt; + int save_qtr_track; + int save_nib_pos; + int status; + int i; + + save_qtr_track = dsk->cur_qtr_track; + save_nib_pos = dsk->nib_pos; + + iwm_move_to_track(dsk, qtr_track); + + dsk->nib_pos = 0; + g_iwm.g_fast_disk_unnib = 1; + + track_len = trk->track_len; + + num_sectors = g_track_bytes_35[qtr_track >> 5] >> 9; + + for(i = 0; i < num_sectors; i++) { + sector_done[i] = 0; + } + + num_sectors_done = 0; + + val = 0; + status = -1; + my_nib_cnt = 0; + + track = qtr_track >> 1; + side = qtr_track & 1; + + while(my_nib_cnt++ < 2*track_len) { + /* look for start of a sector */ + if(val != 0xd5) { + val = iwm_read_data(dsk, 1, 0); + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0x96) { + continue; + } + + /* It's a sector start */ + val = iwm_read_data(dsk, 1, 0); + phys_track = g_iwm.from_disk_byte[val]; + if(phys_track != (track & 0x3f)) { + printf("Track %02x.%d, read track %02x, %02x\n", + track, side, phys_track, val); + break; + } + + phys_sec = g_iwm.from_disk_byte[iwm_read_data(dsk, 1, 0)]; + if(phys_sec < 0 || phys_sec >= num_sectors) { + printf("Track %02x.%d, read sector %02x??\n", + track, side, phys_sec); + break; + } + phys_side = g_iwm.from_disk_byte[iwm_read_data(dsk, 1, 0)]; + + if(phys_side != ((side << 5) + (track >> 6))) { + printf("Track %02x.%d, read side %02x??\n", + track, side, phys_side); + break; + } + phys_capacity = g_iwm.from_disk_byte[iwm_read_data(dsk, 1, 0)]; + if(phys_capacity != 0x24 && phys_capacity != 0x22) { + printf("Track %02x.%x capacity: %02x != 0x24/22\n", + track, side, phys_capacity); + } + cksum = g_iwm.from_disk_byte[iwm_read_data(dsk, 1, 0)]; + + tmp = phys_track ^ phys_sec ^ phys_side ^ phys_capacity; + if(cksum != tmp) { + printf("Track %02x.%d, sector %02x, cksum: %02x.%02x\n", + track, side, phys_sec, cksum, tmp); + break; + } + + + if(sector_done[phys_sec]) { + printf("Already done sector %02x on track %02x.%x!\n", + phys_sec, track, side); + break; + } + + /* So far so good, let's do it! */ + val = 0; + for(i = 0; i < 38; i++) { + val = iwm_read_data(dsk, 1, 0); + if(val == 0xd5) { + break; + } + } + if(val != 0xd5) { + printf("No data header, track %02x.%x, sec %02x\n", + track, side, phys_sec); + break; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + printf("Bad data hdr1,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + printf("nib_pos: %08x\n", dsk->nib_pos); + break; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xad) { + printf("Bad data hdr2,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + buf = outbuf + (phys_sec << 9); + + /* check sector again */ + val = g_iwm.from_disk_byte[iwm_read_data(dsk, 1, 0)]; + if(val != phys_sec) { + printf("Bad data hdr3,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + /* Data start! */ + tmp_5c = 0; + tmp_5d = 0; + tmp_5e = 0; + y = 0xaf; + carry = 0; + + while(y > 0) { +/* 626f */ + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area1b, read: %02x\n", val); + printf(" i:%03x,n_pos:%04x\n", i, dsk->nib_pos); + break; + } + tmp_66 = val2; + + tmp_5c = tmp_5c << 1; + carry = (tmp_5c >> 8); + tmp_5c = (tmp_5c + carry) & 0xff; + + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area2, read: %02x\n", val); + break; + } + + val2 = val2 + ((tmp_66 << 2) & 0xc0); + + val2 = val2 ^ tmp_5c; + buf_c00[y] = val2; + + tmp_5e = val2 + tmp_5e + carry; + carry = (tmp_5e >> 8); + tmp_5e = tmp_5e & 0xff; +/* 62b8 */ + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + val2 = val2 + ((tmp_66 << 4) & 0xc0); + val2 = val2 ^ tmp_5e; + buf_d00[y] = val2; + tmp_5d = val2 + tmp_5d + carry; + + carry = (tmp_5d >> 8); + tmp_5d = tmp_5d & 0xff; + + y--; + if(y <= 0) { + break; + } + +/* 6274 */ + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + val2 = val2 + ((tmp_66 << 6) & 0xc0); + val2 = val2 ^ tmp_5d; + buf_e00[y+1] = val2; + + tmp_5c = val2 + tmp_5c + carry; + carry = (tmp_5c >> 8); + tmp_5c = tmp_5c & 0xff; + } + +/* 62d0 */ + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val]; + + tmp_66 = (val2 << 6) & 0xc0; + tmp_67 = (val2 << 4) & 0xc0; + val2 = (val2 << 2) & 0xc0; + + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val] + val2; + if(tmp_5e != (word32)val2) { + printf("Checksum 5e bad: %02x vs %02x\n", tmp_5e, val2); + printf("val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val] + tmp_67; + if(tmp_5d != (word32)val2) { + printf("Checksum 5d bad: %02x vs %02x\n", tmp_5e, val2); + printf("val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + val = iwm_read_data(dsk, 1, 0); + val2 = g_iwm.from_disk_byte[val] + tmp_66; + if(tmp_5c != (word32)val2) { + printf("Checksum 5c bad: %02x vs %02x\n", tmp_5e, val2); + printf("val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + /* Whew, got it!...check for DE AA */ + val = iwm_read_data(dsk, 1, 0); + if(val != 0xde) { + printf("Bad data epi1,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + printf("nib_pos: %08x\n", dsk->nib_pos); + break; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + printf("Bad data epi2,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + /* Now, convert buf_c/d/e to output */ +/* 6459 */ + y = 0; + for(x = 0xab; x >= 0; x--) { + *buf++ = buf_c00[x]; + y++; + if(y >= 0x200) { + break; + } + + *buf++ = buf_d00[x]; + y++; + if(y >= 0x200) { + break; + } + + *buf++ = buf_e00[x]; + y++; + if(y >= 0x200) { + break; + } + } + + sector_done[phys_sec] = 1; + num_sectors_done++; + if(num_sectors_done >= num_sectors) { + status = 0; + break; + } + val = 0; + } + + if(status < 0) { + printf("dsk->nib_pos: %04x, status: %d\n", dsk->nib_pos, + status); + for(i = 0; i < num_sectors; i++) { + printf("sector done[%d] = %d\n", i, sector_done[i]); + } + } + + iwm_move_to_track(dsk, save_qtr_track); + dsk->nib_pos = save_nib_pos; + g_iwm.g_fast_disk_unnib = 0; + + if(status == 0) { + return 1; + } + + printf("Nibblization not done, %02x sectors found on track %02x\n", + num_sectors_done, qtr_track>>2); + return -1; + + + +} + +/* ret = 1 -> dirty data written out */ +/* ret = 0 -> not dirty, no error */ +/* ret < 0 -> error */ +int +disk_track_to_unix(Disk *dsk, int qtr_track, byte *outbuf) +{ + Trk *trk; + int disk_525; + + disk_525 = dsk->disk_525; + + trk = &(dsk->trks[qtr_track]); + + if(trk->track_len == 0 || trk->track_dirty == 0) { + return 0; + } + + trk->track_dirty = 0; + + if((qtr_track & 3) && disk_525) { + halt_printf("You wrote to phase %02x! Can't wr bk to unix!\n", + qtr_track); + dsk->write_through_to_unix = 0; + return -1; + } + + if(disk_525) + { + // OG + // Add support for .nib file + if (dsk->image_type!=DSK_TYPE_NIB) + return iwm_denib_track525(dsk, trk, qtr_track, outbuf); + else + { + int len = trk->track_len; + byte* trk_ptr = trk->nib_area+1; + byte* nib_ptr = outbuf; + for(int i = 0; i < len; i += 2) + { + *nib_ptr++ = *trk_ptr; + trk_ptr+=2; + } + return 1; + } + } else { + return iwm_denib_track35(dsk, trk, qtr_track, outbuf); + } +} + + +void +show_hex_data(byte *buf, int count) +{ + int i; + + for(i = 0; i < count; i += 16) { + printf("%04x: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, + buf[i+0], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } + +} + +void +disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size) +{ + byte buffer[0x3000]; + Trk *trk; + int ret, ret2; + int i; + + if(size > 0x3000) { + printf("size %08x is > 0x3000, disk_check_nibblization\n",size); + x_exit(3); + } + + for(i = 0; i < size; i++) { + buffer[i] = 0; + } + + trk = &(dsk->trks[qtr_track]); + + if(dsk->disk_525) { + ret = iwm_denib_track525(dsk, trk, qtr_track, &(buffer[0])); + } else { + ret = iwm_denib_track35(dsk, trk, qtr_track, &(buffer[0])); + } + + ret2 = -1; + for(i = 0; i < size; i++) { + if(buffer[i] != buf[i]) { + printf("buffer[%04x]: %02x != %02x\n", i, buffer[i], + buf[i]); + ret2 = i; + break; + } + } + + if(ret != 1 || ret2 >= 0) { + printf("disk_check_nib ret:%d, ret2:%d for q_track %03x\n", + ret, ret2, qtr_track); + show_hex_data(buf, 0x1000); + show_hex_data(buffer, 0x1000); + iwm_show_a_track(&(dsk->trks[qtr_track])); + + x_exit(2); + } +} + + +#define TRACK_BUF_LEN 0x2000 + +void +disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len, + int nib_len) +{ + byte track_buf[TRACK_BUF_LEN]; + Trk *trk; + int must_clear_track; + int ret; + int len; + int i; + + /* Read track from dsk int track_buf */ + + must_clear_track = 0; + + if(unix_len > TRACK_BUF_LEN) { + printf("diks_unix_to_nib: requested len of image %s = %05x\n", + dsk->name_ptr, unix_len); + } + + if(unix_pos >= 0) { + ret = lseek(dsk->fd, unix_pos, SEEK_SET); + if(ret != unix_pos) { + printf("lseek of disk %s len 0x%x ret: %d, errno: %d\n", + dsk->name_ptr, unix_pos, ret, errno); + must_clear_track = 1; + } + + len = read(dsk->fd, (char*)track_buf, unix_len); + if(len != unix_len) { + printf("read of disk %s q_trk %d ret: %d, errno: %d\n", + dsk->name_ptr, qtr_track, ret, errno); + must_clear_track = 1; + } + } + + if(must_clear_track) { + for(i = 0; i < TRACK_BUF_LEN; i++) { + track_buf[i] = 0; + } + } +#ifdef ACTIVEGS + { + extern void apply_patch(int _slot, int _disk,byte * _buf, int pos, int len); + apply_patch(dsk->slot,dsk->disk,track_buf,unix_pos,unix_len); + } +#endif + +#if 0 + printf("Q_track %02x dumped out\n", qtr_track); + + for(i = 0; i < 4096; i += 32) { + printf("%04x: %02x%02x%02x%02x%02x%02x%02x%02x " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", i, + track_buf[i+0], track_buf[i+1], track_buf[i+2], + track_buf[i+3], track_buf[i+4], track_buf[i+5], + track_buf[i+6], track_buf[i+7], track_buf[i+8], + track_buf[i+9], track_buf[i+10], track_buf[i+11], + track_buf[i+12], track_buf[i+13], track_buf[i+14], + track_buf[i+15], track_buf[i+16], track_buf[i+17], + track_buf[i+18], track_buf[i+19], track_buf[i+20], + track_buf[i+21], track_buf[i+22], track_buf[i+23], + track_buf[i+24], track_buf[i+25], track_buf[i+26], + track_buf[i+27], track_buf[i+28], track_buf[i+29], + track_buf[i+30], track_buf[i+31]); + } +#endif + + dsk->nib_pos = 0; /* for consistency */ + + trk = &(dsk->trks[qtr_track]); + trk->track_dirty = 0; + trk->overflow_size = 0; + trk->track_len = 2*nib_len; + trk->unix_pos = unix_pos; + trk->unix_len = unix_len; + trk->dsk = dsk; + trk->nib_area = (byte *)malloc(trk->track_len); + + /* create nibblized image */ + + if(dsk->disk_525 && dsk->image_type == DSK_TYPE_NIB) { + iwm_nibblize_track_nib525(dsk, trk, track_buf, qtr_track); + } else if(dsk->disk_525) { + iwm_nibblize_track_525(dsk, trk, track_buf, qtr_track); + } else { + iwm_nibblize_track_35(dsk, trk, track_buf, qtr_track); + } +} + +void +iwm_nibblize_track_nib525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) +{ + byte *nib_ptr; + byte *trk_ptr; + int len; + int i; + + len = trk->track_len; + trk_ptr = track_buf; + nib_ptr = &(trk->nib_area[0]); + for(i = 0; i < len; i += 2) { + nib_ptr[i] = 8; + nib_ptr[i+1] = *trk_ptr++;; + } + + iwm_printf("Nibblized q_track %02x\n", qtr_track); +} + +void +iwm_nibblize_track_525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) +{ + byte partial_nib_buf[0x300]; + word32 *word_ptr; + word32 val; + word32 last_val; + int phys_sec; + int log_sec; + int num_sync; + int i; + + + word_ptr = (word32 *)&(trk->nib_area[0]); +#ifdef KEGS_LITTLE_ENDIAN + val = 0xff08ff08; +#else + val = 0x08ff08ff; +#endif + for(i = 0; i < trk->track_len; i += 4) { + *word_ptr++ = val; + } + + + for(phys_sec = 0; phys_sec < 16; phys_sec++) { + if(dsk->image_type == DSK_TYPE_DOS33) { + log_sec = phys_to_dos_sec[phys_sec]; + } else { + log_sec = phys_to_prodos_sec[phys_sec]; + } + + /* Create sync headers */ + if(phys_sec == 0) { + num_sync = 70; + } else { + num_sync = 14; + } + + for(i = 0; i < num_sync; i++) { + disk_nib_out(dsk, 0xff, 10); + } + disk_nib_out(dsk, 0xd5, 10); /* prolog */ + disk_nib_out(dsk, 0xaa, 8); /* prolog */ + disk_nib_out(dsk, 0x96, 8); /* prolog */ + disk_4x4_nib_out(dsk, dsk->vol_num); + disk_4x4_nib_out(dsk, qtr_track >> 2); + disk_4x4_nib_out(dsk, phys_sec); + disk_4x4_nib_out(dsk, dsk->vol_num ^ (qtr_track>>2) ^ phys_sec); + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + disk_nib_out(dsk, 0xeb, 8); /* epi */ + + /* Inter sync */ + disk_nib_out(dsk, 0xff, 8); + for(i = 0; i < 5; i++) { + disk_nib_out(dsk, 0xff, 10); + } + disk_nib_out(dsk, 0xd5, 10); /* data prolog */ + disk_nib_out(dsk, 0xaa, 8); /* data prolog */ + disk_nib_out(dsk, 0xad, 8); /* data prolog */ + + sector_to_partial_nib( &(track_buf[log_sec*256]), + &(partial_nib_buf[0])); + + last_val = 0; + for(i = 0; i < 0x156; i++) { + val = partial_nib_buf[i]; + disk_nib_out(dsk, to_disk_byte[last_val ^ val], 8); + last_val = val; + } + disk_nib_out(dsk, to_disk_byte[last_val], 8); + + /* data epilog */ + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + disk_nib_out(dsk, 0xeb, 8); /* epi */ + disk_nib_out(dsk, 0xff, 8); + for(i = 0; i < 6; i++) { + disk_nib_out(dsk, 0xff, 10); + } + } + + /* finish nibblization */ + disk_nib_end_track(dsk); + + iwm_printf("Nibblized q_track %02x\n", qtr_track); + + if(g_iwm.g_check_nibblization) { + disk_check_nibblization(dsk, qtr_track, &(track_buf[0]),0x1000); + } +} + +void +iwm_nibblize_track_35(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) +{ + int phys_to_log_sec[16]; + word32 buf_c00[0x100]; + word32 buf_d00[0x100]; + word32 buf_e00[0x100]; + byte *buf; + word32 *word_ptr; + word32 val; + int num_sectors; + int unix_len; + int log_sec; + int phys_sec; + int track; + int side; + int interleave; + int num_sync; + word32 phys_track, phys_side, capacity, cksum; + word32 tmp_5c, tmp_5d, tmp_5e, tmp_5f; + word32 tmp_63, tmp_64, tmp_65; + word32 acc_hi; + int carry; + int x, y; + int i; + + word_ptr = (word32 *)&(trk->nib_area[0]); +#ifdef KEGS_LITTLE_ENDIAN + val = 0xff08ff08; +#else + val = 0x08ff08ff; +#endif + if(trk->track_len & 3) { + halt_printf("track_len: %08x is not a multiple of 4\n", + trk->track_len); + } + + for(i = 0; i < trk->track_len; i += 4) { + *word_ptr++ = val; + } + + unix_len = trk->unix_len; + + num_sectors = (unix_len >> 9); + + for(i = 0; i < num_sectors; i++) { + phys_to_log_sec[i] = -1; + } + + phys_sec = 0; + interleave = 2; + for(log_sec = 0; log_sec < num_sectors; log_sec++) { + while(phys_to_log_sec[phys_sec] >= 0) { + phys_sec++; + if(phys_sec >= num_sectors) { + phys_sec = 0; + } + } + phys_to_log_sec[phys_sec] = log_sec; + phys_sec += interleave; + if(phys_sec >= num_sectors) { + phys_sec -= num_sectors; + } + } + + track = qtr_track >> 1; + side = qtr_track & 1; + for(phys_sec = 0; phys_sec < num_sectors; phys_sec++) { + + log_sec = phys_to_log_sec[phys_sec]; + if(log_sec < 0) { + printf("Track: %02x.%x phys_sec: %02x = %d!\n", + track, side, phys_sec, log_sec); + x_exit(2); + } + + /* Create sync headers */ + if(phys_sec == 0) { + num_sync = 400; + } else { + num_sync = 54; + } + + for(i = 0; i < num_sync; i++) { + disk_nib_out(dsk, 0xff, 10); + } + + disk_nib_out(dsk, 0xd5, 10); /* prolog */ + disk_nib_out(dsk, 0xaa, 8); /* prolog */ + disk_nib_out(dsk, 0x96, 8); /* prolog */ + + phys_track = track & 0x3f; + phys_side = (side << 5) + (track >> 6); + capacity = 0x22; + disk_nib_out(dsk, to_disk_byte[phys_track], 8); /* trk */ + disk_nib_out(dsk, to_disk_byte[log_sec], 8); /* sec */ + disk_nib_out(dsk, to_disk_byte[phys_side], 8); /* sides+trk */ + disk_nib_out(dsk, to_disk_byte[capacity], 8); /* capacity*/ + + cksum = (phys_track ^ log_sec ^ phys_side ^ capacity) & 0x3f; + disk_nib_out(dsk, to_disk_byte[cksum], 8); /* cksum*/ + + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + + /* Inter sync */ + for(i = 0; i < 5; i++) { + disk_nib_out(dsk, 0xff, 10); + } + disk_nib_out(dsk, 0xd5, 10); /* data prolog */ + disk_nib_out(dsk, 0xaa, 8); /* data prolog */ + disk_nib_out(dsk, 0xad, 8); /* data prolog */ + disk_nib_out(dsk, to_disk_byte[log_sec], 8); /* sec again */ + + /* do nibblizing! */ + buf = track_buf + (log_sec << 9); + +/* 6320 */ + tmp_5e = 0; + tmp_5d = 0; + tmp_5c = 0; + y = 0; + x = 0xaf; + buf_c00[0] = 0; + buf_d00[0] = 0; + buf_e00[0] = 0; + buf_e00[1] = 0; + for(y = 0x4; y > 0; y--) { + buf_c00[x] = 0; + buf_d00[x] = 0; + buf_e00[x] = 0; + x--; + } + + while(x >= 0) { +/* 6338 */ + tmp_5c = tmp_5c << 1; + carry = (tmp_5c >> 8); + tmp_5c = (tmp_5c + carry) & 0xff; + + val = buf[y]; + tmp_5e = val + tmp_5e + carry; + carry = (tmp_5e >> 8); + tmp_5e = tmp_5e & 0xff; + + val = val ^ tmp_5c; + buf_c00[x] = val; + y++; +/* 634c */ + val = buf[y]; + tmp_5d = tmp_5d + val + carry; + carry = (tmp_5d >> 8); + tmp_5d = tmp_5d & 0xff; + val = val ^ tmp_5e; + buf_d00[x] = val; + y++; + x--; + if(x <= 0) { + break; + } + +/* 632a */ + val = buf[y]; + tmp_5c = tmp_5c + val + carry; + carry = (tmp_5c >> 8); + tmp_5c = tmp_5c & 0xff; + + val = val ^ tmp_5d; + buf_e00[x+1] = val; + y++; + } + +/* 635f */ + val = ((tmp_5c >> 2) ^ tmp_5d) & 0x3f; +/* 6367 */ + val = (val ^ tmp_5d) >> 2; +/* 636b */ + val = (val ^ tmp_5e) & 0x3f; +/* 636f */ + val = (val ^ tmp_5e) >> 2; +/* 6373 */ + tmp_5f = val; +/* 6375 */ + tmp_63 = 0; + tmp_64 = 0; + tmp_65 = 0; + acc_hi = 0; + + + y = 0xae; + while(y >= 0) { +/* 63e4 */ + /* write out acc_hi */ + val = to_disk_byte[acc_hi & 0x3f]; + disk_nib_out(dsk, val, 8); + +/* 63f2 */ + val = to_disk_byte[tmp_63 & 0x3f]; + tmp_63 = buf_c00[y]; + acc_hi = tmp_63 >> 6; + disk_nib_out(dsk, val, 8); +/* 640b */ + val = to_disk_byte[tmp_64 & 0x3f]; + tmp_64 = buf_d00[y]; + acc_hi = (acc_hi << 2) + (tmp_64 >> 6); + disk_nib_out(dsk, val, 8); + y--; + if(y < 0) { + break; + } + +/* 63cb */ + val = to_disk_byte[tmp_65 & 0x3f]; + tmp_65 = buf_e00[y+1]; + acc_hi = (acc_hi << 2) + (tmp_65 >> 6); + disk_nib_out(dsk, val, 8); + } +/* 6429 */ + val = to_disk_byte[tmp_5f & 0x3f]; + disk_nib_out(dsk, val, 8); + + val = to_disk_byte[tmp_5e & 0x3f]; + disk_nib_out(dsk, val, 8); + + val = to_disk_byte[tmp_5d & 0x3f]; + disk_nib_out(dsk, val, 8); + + val = to_disk_byte[tmp_5c & 0x3f]; + disk_nib_out(dsk, val, 8); + +/* 6440 */ + /* data epilog */ + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + disk_nib_out(dsk, 0xff, 8); + } + + + disk_nib_end_track(dsk); + + if(g_iwm.g_check_nibblization) { + disk_check_nibblization(dsk, qtr_track, &(track_buf[0]), + unix_len); + } +} + +void +disk_4x4_nib_out(Disk *dsk, word32 val) +{ + disk_nib_out(dsk, 0xaa | (val >> 1), 8); + disk_nib_out(dsk, 0xaa | val, 8); +} + +void +disk_nib_out(Disk *dsk, byte val, int size) +{ + Trk *trk; + int pos; + int old_size; + int track_len; + int overflow_size; + int qtr_track; + + + qtr_track = dsk->cur_qtr_track; + + track_len = 0; + trk = 0; + if(dsk->trks != 0) { + trk = &(dsk->trks[qtr_track]); + track_len = trk->track_len; + } + + if(track_len <= 10) { + printf("Writing to an invalid qtr track: %02x!\n", qtr_track); + printf("name: %s, track_len: %08x, val: %08x, size: %d\n", + dsk->name_ptr, track_len, val, size); + x_exit(1); + return; + } + + trk->track_dirty = 1; + dsk->disk_dirty = 1; + + pos = trk->dsk->nib_pos; + overflow_size = trk->overflow_size; + if(pos >= track_len) { + pos = 0; + } + + old_size = trk->nib_area[pos]; + + + while(size >= (10 + old_size)) { + size = size - old_size; + pos += 2; + if(pos >= track_len) { + pos = 0; + } + old_size = trk->nib_area[pos]; + } + + if(size > 10) { + size = 10; + } + + if((val & 0x80) == 0) { + val |= 0x80; + } + + trk->nib_area[pos++] = size; + trk->nib_area[pos++] = val; + if(pos >= track_len) { + pos = 0; + } + + overflow_size += (size - old_size); + if((overflow_size > 8) && (size > 8)) { + overflow_size -= trk->nib_area[pos]; + trk->nib_area[pos++] = 0; + trk->nib_area[pos++] = 0; + if(pos >= track_len) { + pos = 0; + } + } else if(overflow_size < -64) { + halt_printf("overflow_sz:%03x, pos:%02x\n",overflow_size,pos); + } + + trk->dsk->nib_pos = pos; + trk->overflow_size = overflow_size; + + if((val & 0x80) == 0 || size < 8) { + halt_printf("disk_nib_out, wrote %02x, size: %d\n", val, size); + } +} + +void +disk_nib_end_track(Disk *dsk) +{ + int qtr_track; + + dsk->nib_pos = 0; + qtr_track = dsk->cur_qtr_track; + dsk->trks[qtr_track].track_dirty = 0; + + dsk->disk_dirty = 0; +} + +void +iwm_show_track(int slot_drive, int track) +{ + Disk *dsk; + Trk *trk; + int drive; + int sel35; + int qtr_track; + + if(slot_drive < 0) { + drive = g_iwm.iwm.drive_select; + sel35 = (g_moremem.g_c031_disk35 >> 6) & 1; + } else { + drive = slot_drive & 1; + sel35 = !((slot_drive >> 1) & 1); + } + + if(sel35) { + dsk = &(g_iwm.iwm.drive35[drive]); + } else { + dsk = &(g_iwm.iwm.drive525[drive]); + } + + if(track < 0) { + qtr_track = dsk->cur_qtr_track; + } else { + qtr_track = track; + } + if(dsk->trks == 0) { + return; + } + trk = &(dsk->trks[qtr_track]); + + if(trk->track_len <= 0) { + printf("Track_len: %d\n", trk->track_len); + printf("No track for type: %d, drive: %d, qtrk: 0x%02x\n", + sel35, drive, qtr_track); + return; + } + + printf("Current drive: %d, q_track: 0x%02x\n", drive, qtr_track); + + iwm_show_a_track(trk); +} + +void +iwm_show_a_track(Trk *trk) +{ + int sum; + int len; + int pos; + int i; + + printf(" Showtrack:dirty: %d, pos: %04x, ovfl: %04x, len: %04x\n", + trk->track_dirty, trk->dsk->nib_pos, + trk->overflow_size, trk->track_len); + + len = trk->track_len; + printf("Track len in bytes: %04x\n", len); + if(len >= 2*15000) { + len = 2*15000; + printf("len too big, using %04x\n", len); + } + + pos = 0; + for(i = 0; i < len; i += 16) { + printf("%04x: %2d,%02x %2d,%02x %2d,%02x %2d,%02x " + "%2d,%02x %2d,%02x %2d,%02x %2d,%02x\n", pos, + trk->nib_area[pos], trk->nib_area[pos+1], + trk->nib_area[pos+2], trk->nib_area[pos+3], + trk->nib_area[pos+4], trk->nib_area[pos+5], + trk->nib_area[pos+6], trk->nib_area[pos+7], + trk->nib_area[pos+8], trk->nib_area[pos+9], + trk->nib_area[pos+10], trk->nib_area[pos+11], + trk->nib_area[pos+12], trk->nib_area[pos+13], + trk->nib_area[pos+14], trk->nib_area[pos+15]); + pos += 16; + if(pos >= len) { + pos -= len; + } + } + + sum = 0; + for(i = 0; i < len; i += 2) { + sum += trk->nib_area[i]; + } + + printf("bit_sum: %d, expected: %d, overflow_size: %d\n", + sum, len*8/2, trk->overflow_size); +} + diff --git a/kegs/Src/iwm.h b/kegs/Src/iwm.h new file mode 100644 index 0000000..85eca68 --- /dev/null +++ b/kegs/Src/iwm.h @@ -0,0 +1,326 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#ifdef INCLUDE_RCSID_C +const char rcsid_iwm_h[] = "@(#)$KmKId: iwm.h,v 1.14 2004-10-20 17:29:38-04 kentd Exp $"; +#endif + +#define MAX_TRACKS (2*80) +#define MAX_C7_DISKS 8 + +#define NIB_LEN_525 0x1900 /* 51072 bits per track */ +#define NIBS_FROM_ADDR_TO_DATA 20 + +#define DSK_TYPE_PRODOS 0 +#define DSK_TYPE_DOS33 1 +#define DSK_TYPE_NIB 2 + +typedef struct _Disk Disk; + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +STRUCT(Trk) { + Disk *dsk; + byte *nib_area; + int track_dirty; + int overflow_size; + int track_len; + int unix_pos; + int unix_len; +} XCODE_PRAGMA_PACK; + +#define MAX_DISK_NAME 512 +struct _Disk { + _ALIGNED(8) double dcycs_last_read; + char name_ptr[MAX_DISK_NAME]; + char partition_name[MAX_DISK_NAME]; + + int partition_num; + int fd; + int force_size; + int image_start; + int image_size; + int smartport; + int disk_525; + int drive; + int cur_qtr_track; + int image_type; + int vol_num; + int write_prot; + int write_through_to_unix; + int disk_dirty; + int just_ejected; + int last_phase; + int nib_pos; + int num_tracks; + Trk *trks; + int slot; + int disk; +} XCODE_PRAGMA_PACK; + + +STRUCT(Iwm) { + Disk drive525[2]; + Disk drive35[2]; + Disk smartport[MAX_C7_DISKS]; + int motor_on; + int motor_off; + int motor_off_vbl_count; + int motor_on35; + int head35; + int step_direction35; + int iwm_phase[4]; + int iwm_mode; + int drive_select; + int q6; + int q7; + int enable2; + int reset; + + word32 previous_write_val; + int previous_write_bits; +} XCODE_PRAGMA_PACK; + + +STRUCT(Driver_desc) { + word16 sig; + word16 blk_size; + word32 blk_count; + word16 dev_type; + word16 dev_id; + word32 data; + word16 drvr_count; +} XCODE_PRAGMA_PACK; + +STRUCT(Part_map) { + word16 sig; + word16 sigpad; + word32 map_blk_cnt; + word32 phys_part_start; + word32 part_blk_cnt; + char part_name[32]; + char part_type[32]; + word32 data_start; + word32 data_cnt; + word32 part_status; + word32 log_boot_start; + word32 boot_size; + word32 boot_load; + word32 boot_load2; + word32 boot_entry; + word32 boot_entry2; + word32 boot_cksum; + char processor[16]; + char junk[128]; +} XCODE_PRAGMA_PACK; + +class s_iwm : public serialized +{ +public: + int g_fast_disk_emul ; + int g_slow_525_emul_wr ; + _ALIGNED(8) double g_dcycs_end_emul_wr ; + int g_fast_disk_unnib ; + int g_iwm_fake_fast ; + int from_disk_byte[256]; + int from_disk_byte_valid ; + Iwm iwm; + int g_iwm_motor_on ; + int g_check_nibblization ; + int g_highest_smartport_unit ; + word32 g_cycs_in_io_read; + int g_cnt_enable2_handshake ; + + + s_iwm() + { + INIT_SERIALIZED(); + + g_fast_disk_emul = 1; + g_highest_smartport_unit = -1; + + } +#define WRITE_TRK(X) \ + if (X.trks) \ + { \ + memcpy(ptr,X.trks,X.num_tracks * sizeof(Trk)); \ + ptr += X.num_tracks * sizeof(Trk); \ + for(int t=0;tdata; + int ssize = *(int*)ptr; + if (ssize!= sizeof(*this)) + ALIGNMENT_ERROR("iwm",ssize,sizeof(*this)); + ptr += sizeof(ssize); + memcpy(this,ptr,sizeof(*this)); + + RESTORE_TRK_PTR(iwm.drive525[0],drive5251); + RESTORE_TRK_PTR(iwm.drive525[1],drive5252); + RESTORE_TRK_PTR(iwm.drive35[0],drive351); + RESTORE_TRK_PTR(iwm.drive35[1],drive352); + RESTORE_TRK_PTR(iwm.smartport[0],smartport0); + RESTORE_TRK_PTR(iwm.smartport[1],smartport1); + RESTORE_TRK_PTR(iwm.smartport[2],smartport2); + RESTORE_TRK_PTR(iwm.smartport[3],smartport3); + + + + } + + int out(serialize* _s, int _fastalloc) + { + // calcule la taille totale de la structure + + SAVE_TRK_PTR(iwm.drive525[0],drive5251); + SAVE_TRK_PTR(iwm.drive525[1],drive5252); + SAVE_TRK_PTR(iwm.drive35[0],drive351); + SAVE_TRK_PTR(iwm.drive35[1],drive352); + SAVE_TRK_PTR(iwm.smartport[0],smartport0); + SAVE_TRK_PTR(iwm.smartport[1],smartport1); + SAVE_TRK_PTR(iwm.smartport[2],smartport2); + SAVE_TRK_PTR(iwm.smartport[3],smartport3); + + // copie la structure de base + + int ssize = sizeof(*this); + int size = ssize + sizeof(ssize); + _s->size = size; + _s->fastalloc = _fastalloc; + _s->data = (void*)x_malloc(size,_fastalloc); + byte* ptr = (byte*) _s->data; + memcpy(ptr,&ssize,sizeof(ssize)); + ptr+=sizeof(ssize); + memcpy(ptr,this,sizeof(*this)); + + RESTORE_TRK_PTR(iwm.drive525[0],drive5251); + RESTORE_TRK_PTR(iwm.drive525[1],drive5252); + RESTORE_TRK_PTR(iwm.drive35[0],drive351); + RESTORE_TRK_PTR(iwm.drive35[1],drive352); + RESTORE_TRK_PTR(iwm.smartport[0],smartport0); + RESTORE_TRK_PTR(iwm.smartport[1],smartport1); + RESTORE_TRK_PTR(iwm.smartport[2],smartport2); + RESTORE_TRK_PTR(iwm.smartport[3],smartport3); + + return size; + } +} XCODE_PRAGMA_PACK; +#ifdef _WIN32 +#pragma pack(pop) +#endif + +extern s_iwm g_iwm; +extern int g_track_bytes_35[]; +extern int g_track_nibs_35[]; + +void iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525); +void disk_set_num_tracks(Disk *dsk, int num_tracks); +void iwm_init(void); +void iwm_shut(void); //OG +void iwm_reset(void); +void draw_iwm_status(int line, char *buf); +void iwm_flush_disk_to_unix(Disk *dsk); +void iwm_vbl_update(int doit_3_persec); +void iwm_show_stats(void); +void iwm_touch_switches(int loc, double dcycs); +void iwm_move_to_track(Disk *dsk, int new_track); +void iwm525_phase_change(int drive, int phase); +int iwm_read_status35(double dcycs); +void iwm_do_action35(double dcycs); +int iwm_read_c0ec(double dcycs); +int read_iwm(int loc, double dcycs); +void write_iwm(int loc, int val, double dcycs); +int iwm_read_enable2(double dcycs); +int iwm_read_enable2_handshake(double dcycs); +void iwm_write_enable2(int val, double dcycs); +int iwm_read_data(Disk *dsk, int fast_disk_emul, double dcycs); +void iwm_write_data(Disk *dsk, word32 val, int fast_disk_emul, double dcycs); +void sector_to_partial_nib(byte *in, byte *nib_ptr); +int disk_unnib_4x4(Disk *dsk); +int iwm_denib_track525(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf); +int iwm_denib_track35(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf); +int disk_track_to_unix(Disk *dsk, int qtr_track, byte *outbuf); +void show_hex_data(byte *buf, int count); +void disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size); +void disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len, int nib_len); +void iwm_nibblize_track_nib525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track); +void iwm_nibblize_track_525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track); +void iwm_nibblize_track_35(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track); +void disk_4x4_nib_out(Disk *dsk, word32 val); +void disk_nib_out(Disk *dsk, byte val, int size); +void disk_nib_end_track(Disk *dsk); +void iwm_show_track(int slot_drive, int track); +void iwm_show_a_track(Trk *trk); + + diff --git a/kegs/Src/iwm_35_525.h b/kegs/Src/iwm_35_525.h new file mode 100644 index 0000000..45bcca4 --- /dev/null +++ b/kegs/Src/iwm_35_525.h @@ -0,0 +1,331 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_IWM_RCSID_C +const char rcsdif_iwm_35_525_h[] = "@(#)$KmKId: iwm_35_525.h,v 1.14 2004-12-01 19:45:02-05 kentd Exp $"; +#endif + +int +IWM_READ_ROUT (Disk *dsk, int fast_disk_emul, double dcycs) +{ + Trk *trk; + double dcycs_last_read; + int pos; + int pos2; + int size; + int next_size; + int qtr_track; + int skip_nibs; + int track_len; + byte ret; + int shift; + int skip; + int cycs_this_nib; + int cycs_passed; + double dcycs_this_nib; + double dcycs_next_nib; + double dcycs_passed; + double track_dcycs; + double dtmp; + + g_iwm.iwm.previous_write_bits = 0; + + qtr_track = dsk->cur_qtr_track; + +#if IWM_DISK_525 + qtr_track = qtr_track & -4; /* round to nearest whole trk! */ +#endif + + trk = 0; + track_len = 0; + if(dsk->trks) { + trk = &(dsk->trks[qtr_track]); + track_len = trk->track_len; + } + + dcycs_last_read = dsk->dcycs_last_read; + dcycs_passed = dcycs - dcycs_last_read; + + cycs_passed = (int)dcycs_passed; + + if(track_len == 0) { + ret = (cycs_passed & 0x7f) + 0x80; + iwm_printf("Reading c0ec, track_len 0, returning %02x\n", ret); + return ret; + } + + pos = dsk->nib_pos; + if(pos >= track_len) { + /* Arm may have moved from inner 3.5 track to outer one, */ + /* and so must make pos fit on smaller sized track */ + pos = 0; + } + + if (pos<0) + { + printf("invalid pos"); + pos=0; + } + size = trk->nib_area[pos]; + + while(size == 0) { + pos += 2; + if(pos >= track_len) { + pos = 0; + } + size = trk->nib_area[pos]; + } + + cycs_this_nib = size * (2 * IWM_CYC_MULT); + dcycs_this_nib = (double)cycs_this_nib; + + if(fast_disk_emul) { + cycs_passed = cycs_this_nib; + dcycs_passed = dcycs_this_nib; + + /* pull a trick to make disk motor-on test pass ($bd34 RWTS) */ + /* if this would be a sync byte, and we didn't just do this */ + /* then don't return whole byte */ + /* BUT, don't do this if g_fast_disk_unnib, since it will */ + /* cause the dsk->unix routines to break */ + if(size > 8 && !g_iwm.g_fast_disk_unnib && (g_iwm.g_iwm_fake_fast == 0)) { + cycs_passed = cycs_passed >> 1; + dcycs_passed = dcycs_passed * 0.5; + g_iwm.g_iwm_fake_fast = 1; + } else { + g_iwm.g_iwm_fake_fast = 0; + } + } + + skip = 0; + if(cycs_passed >= (cycs_this_nib + 11)) { + /* skip some bits? */ + skip = 1; + if(g_iwm.iwm.iwm_mode & 1) { + /* latch mode */ + + pos2 = pos + 2; + if(pos2 >= track_len) { + pos2 = 0; + } + next_size = trk->nib_area[pos2]; + while(next_size == 0) { + pos2 += 2; + if(pos2 >= track_len) { + pos2 = 0; + } + next_size = trk->nib_area[pos2]; + } + + dcycs_next_nib = next_size * (2 * IWM_CYC_MULT); + + if(dcycs_passed < (dcycs_this_nib + dcycs_next_nib)) { + skip = 0; + } + } + } + + if(skip) { + iwm_printf("skip since cycs_passed: %f, cycs_this_nib: %f\n", + dcycs_passed, dcycs_this_nib); + + track_dcycs = IWM_CYC_MULT * (track_len * 8); + + if(dcycs_passed >= track_dcycs) { + dtmp = (int)(dcycs_passed / track_dcycs); + dcycs_passed = dcycs_passed - + (dtmp * track_dcycs); + dcycs_last_read += (dtmp * track_dcycs); + } + + if(dcycs_passed >= track_dcycs || dcycs_passed < 0.0) { + dcycs_passed = 0.0; + } + + cycs_passed = (int)dcycs_passed; + + skip_nibs = ((word32)cycs_passed) >> (4 + IWM_DISK_525); + + pos += skip_nibs * 2; + while(pos >= track_len) { + pos -= track_len; + } + + dcycs_last_read += (skip_nibs * 16 * IWM_CYC_MULT); + + dsk->dcycs_last_read = dcycs_last_read; + + size = trk->nib_area[pos]; + dcycs_passed = dcycs - dcycs_last_read; + if(dcycs_passed < 0.0 || dcycs_passed > 64.0) { + halt_printf("skip, last_read:%f, dcycs:%f, dcyc_p:%f\n", + dcycs_last_read, dcycs, dcycs_passed); + } + + while(size == 0) { + pos += 2; + if(pos >= track_len) { + pos = 0; + } + size = trk->nib_area[pos]; + } + + cycs_this_nib = size * (2 * IWM_CYC_MULT); + cycs_passed = (int)dcycs_passed; + dcycs_this_nib = cycs_this_nib; + } + + if(cycs_passed < cycs_this_nib) { + /* partial */ +#if 0 + iwm_printf("Disk partial, %f < %f, size: %d\n", + dcycs_passed, dcycs_this_nib, size); +#endif + shift = (cycs_passed) >> (1 + IWM_DISK_525); + ret = trk->nib_area[pos+1] >> (size - shift); + if(ret & 0x80) { + halt_printf("Bad shift in partial read: %02x, but " + "c_pass:%f, this_nib:%f, shift: %d, size: %d\n", + ret, dcycs_passed, dcycs_this_nib, shift, size); + } + } else { + /* whole thing */ + ret = trk->nib_area[pos+1]; + pos += 2; + if(pos >= track_len) { + pos = 0; + } + if(!fast_disk_emul) { + dsk->dcycs_last_read = dcycs_last_read + dcycs_this_nib; + } + } + + dsk->nib_pos = pos; + if(pos < 0 || pos > track_len) { + halt_printf("I just set nib_pos: %d!\n", pos); + } + +#if 0 + iwm_printf("Disk read, returning: %02x\n", ret); +#endif + + return ret; +} + + +void +IWM_WRITE_ROUT (Disk *dsk, word32 val, int fast_disk_emul, double dcycs) +{ + double dcycs_last_read; + int bits_read; // OG must be signed to detect errors + word32 mask; + word32 prev_val; + double dcycs_this_nib; + double dcycs_passed; + int sdiff; + int prev_bits; + + if(dsk->fd < 0 || dsk->trks == 0) { + halt_printf("Tried to write to type: %d, drive: %d, fd: %d!\n", + IWM_DISK_525, dsk->drive, dsk->fd, dsk->trks); + return; + } + + dcycs_last_read = dsk->dcycs_last_read; + + dcycs_passed = dcycs - dcycs_last_read; + + prev_val = g_iwm.iwm.previous_write_val; + prev_bits = g_iwm.iwm.previous_write_bits; + mask = 0x100; + iwm_printf("Iwm write: prev: %x,%d, new:%02x\n", prev_val, prev_bits, + val); + + if(IWM_DISK_525) { + /* Activate slow write emulation mode */ + g_iwm.g_dcycs_end_emul_wr = dcycs + 64.0; + if(!g_iwm.g_slow_525_emul_wr) { + set_halt(HALT_EVENT); + g_iwm.g_slow_525_emul_wr = 1; + } + } else { + /* disable slow writes on 3.5" drives */ + if(g_iwm.g_slow_525_emul_wr) { + set_halt(HALT_EVENT); + printf("HACK3: g_slow_525_emul_wr set to 0\n"); + g_iwm.g_slow_525_emul_wr = 0; + } + } + + if(g_iwm.iwm.iwm_mode & 2) { + /* async mode = 3.5" default */ + bits_read = 8; + } else { + /* sync mode, 5.25" drives */ + bits_read = ((int)dcycs_passed) >> (1 + IWM_DISK_525); + if(bits_read < 8) { + bits_read = 8; + } + } + + if(fast_disk_emul) { + bits_read = 8; + } + + dcycs_this_nib = bits_read * (2 * IWM_CYC_MULT); + + if(fast_disk_emul) { + dcycs_passed = dcycs_this_nib; + } + + if(prev_bits > 0) { + while((prev_val & 0x80) == 0 && bits_read > 0) { + /* previous byte needs some bits */ + mask = mask >> 1; + prev_val = (prev_val << 1) + ((val & mask) !=0); + prev_bits++; + bits_read--; + } + } + + val = val & (mask - 1); + if(prev_bits) { + /* force out prev_val if it had many bits before */ + /* this prevents writes of 0 from messing us up */ + if(((prev_val & 0x80) == 0) && (prev_bits < 10)) { + /* special case: we still don't have enough to go */ + iwm_printf("iwm_write: zip2: %02x, %d, left:%02x,%d\n", + prev_val, prev_bits, val,bits_read); + val = prev_val; + bits_read = prev_bits; + } else { + iwm_printf("iwm_write: prev: %02x, %d, left:%02x, %d\n", + prev_val, prev_bits, val, bits_read); + disk_nib_out(dsk, prev_val, prev_bits); + } + } else if(val & 0x80) { + iwm_printf("iwm_write: new: %02x, %d\n", val,bits_read); + disk_nib_out(dsk, val, bits_read); + bits_read = 0; + } else { + iwm_printf("iwm_write: zip: %02x, %d, left:%02x,%d\n", + prev_val, prev_bits, val,bits_read); + } + + g_iwm.iwm.previous_write_val = val; + g_iwm.iwm.previous_write_bits = bits_read; + if(bits_read < 0) { + halt_printf("iwm, bits_rd:%d, val:%08x, prev:%02x, prevb:%d\n", + bits_read, val, prev_val, prev_bits); + } + + sdiff = (int)( dcycs - dcycs_last_read ); + if(sdiff < (dcycs_this_nib) || (sdiff > (2*dcycs_this_nib)) ) { + dsk->dcycs_last_read = dcycs; + } else { + dsk->dcycs_last_read = dcycs_last_read + dcycs_this_nib; + } +} diff --git a/kegs/Src/kegsfont.h b/kegs/Src/kegsfont.h new file mode 100644 index 0000000..15211dd --- /dev/null +++ b/kegs/Src/kegsfont.h @@ -0,0 +1,517 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + + { 0xc7, 0xbb, 0xab, 0xa3, 0xa7, 0xbf, 0xc3, 0xff }, +/* char 0x01 (raw 0x41) */ + { 0xef, 0xd7, 0xbb, 0xbb, 0x83, 0xbb, 0xbb, 0xff }, +/* char 0x02 (raw 0x42) */ + { 0x87, 0xbb, 0xbb, 0x87, 0xbb, 0xbb, 0x87, 0xff }, +/* char 0x03 (raw 0x43) */ + { 0xc7, 0xbb, 0xbf, 0xbf, 0xbf, 0xbb, 0xc7, 0xff }, +/* char 0x04 (raw 0x44) */ + { 0x87, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x87, 0xff }, +/* char 0x05 (raw 0x45) */ + { 0x83, 0xbf, 0xbf, 0x87, 0xbf, 0xbf, 0x83, 0xff }, +/* char 0x06 (raw 0x46) */ + { 0x83, 0xbf, 0xbf, 0x87, 0xbf, 0xbf, 0xbf, 0xff }, +/* char 0x07 (raw 0x47) */ + { 0xc3, 0xbf, 0xbf, 0xbf, 0xb3, 0xbb, 0xc3, 0xff }, +/* char 0x08 (raw 0x48) */ + { 0xbb, 0xbb, 0xbb, 0x83, 0xbb, 0xbb, 0xbb, 0xff }, +/* char 0x09 (raw 0x49) */ + { 0xc7, 0xef, 0xef, 0xef, 0xef, 0xef, 0xc7, 0xff }, +/* char 0x0a (raw 0x4a) */ + { 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xc7, 0xff }, +/* char 0x0b (raw 0x4b) */ + { 0xbb, 0xb7, 0xaf, 0x9f, 0xaf, 0xb7, 0xbb, 0xff }, +/* char 0x0c (raw 0x4c) */ + { 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x83, 0xff }, +/* char 0x0d (raw 0x4d) */ + { 0xbb, 0x93, 0xab, 0xab, 0xbb, 0xbb, 0xbb, 0xff }, +/* char 0x0e (raw 0x4e) */ + { 0xbb, 0xbb, 0x9b, 0xab, 0xb3, 0xbb, 0xbb, 0xff }, +/* char 0x0f (raw 0x4f) */ + { 0xc7, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xc7, 0xff }, +/* char 0x10 (raw 0x50) */ + { 0x87, 0xbb, 0xbb, 0x87, 0xbf, 0xbf, 0xbf, 0xff }, +/* char 0x11 (raw 0x51) */ + { 0xc7, 0xbb, 0xbb, 0xbb, 0xab, 0xb7, 0xcb, 0xff }, +/* char 0x12 (raw 0x52) */ + { 0x87, 0xbb, 0xbb, 0x87, 0xaf, 0xb7, 0xbb, 0xff }, +/* char 0x13 (raw 0x53) */ + { 0xc7, 0xbb, 0xbf, 0xc7, 0xfb, 0xbb, 0xc7, 0xff }, +/* char 0x14 (raw 0x54) */ + { 0x83, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xff }, +/* char 0x15 (raw 0x55) */ + { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xc7, 0xff }, +/* char 0x16 (raw 0x56) */ + { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xd7, 0xef, 0xff }, +/* char 0x17 (raw 0x57) */ + { 0xbb, 0xbb, 0xbb, 0xab, 0xab, 0x93, 0xbb, 0xff }, +/* char 0x18 (raw 0x58) */ + { 0xbb, 0xbb, 0xd7, 0xef, 0xd7, 0xbb, 0xbb, 0xff }, +/* char 0x19 (raw 0x59) */ + { 0xbb, 0xbb, 0xd7, 0xef, 0xef, 0xef, 0xef, 0xff }, +/* char 0x1a (raw 0x5a) */ + { 0x83, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x83, 0xff }, +/* char 0x1b (raw 0x5b) */ + { 0x83, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x83, 0xff }, +/* char 0x1c (raw 0x5c) */ + { 0xff, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xff, 0xff }, +/* char 0x1d (raw 0x5d) */ + { 0x83, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0x83, 0xff }, +/* char 0x1e (raw 0x5e) */ + { 0xff, 0xff, 0xef, 0xd7, 0xbb, 0xff, 0xff, 0xff }, +/* char 0x1f (raw 0x5f) */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01 }, +/* char 0x20 (raw 0x20) */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, +/* char 0x21 (raw 0x21) */ + { 0xef, 0xef, 0xef, 0xef, 0xef, 0xff, 0xef, 0xff }, +/* char 0x22 (raw 0x22) */ + { 0xd7, 0xd7, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff }, +/* char 0x23 (raw 0x23) */ + { 0xd7, 0xd7, 0x83, 0xd7, 0x83, 0xd7, 0xd7, 0xff }, +/* char 0x24 (raw 0x24) */ + { 0xef, 0xc3, 0xaf, 0xc7, 0xeb, 0x87, 0xef, 0xff }, +/* char 0x25 (raw 0x25) */ + { 0x9f, 0x9b, 0xf7, 0xef, 0xdf, 0xb3, 0xf3, 0xff }, +/* char 0x26 (raw 0x26) */ + { 0xdf, 0xaf, 0xaf, 0xdf, 0xab, 0xb7, 0xcb, 0xff }, +/* char 0x27 (raw 0x27) */ + { 0xef, 0xef, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff }, +/* char 0x28 (raw 0x28) */ + { 0xef, 0xdf, 0xbf, 0xbf, 0xbf, 0xdf, 0xef, 0xff }, +/* char 0x29 (raw 0x29) */ + { 0xef, 0xf7, 0xfb, 0xfb, 0xfb, 0xf7, 0xef, 0xff }, +/* char 0x2a (raw 0x2a) */ + { 0xef, 0xab, 0xc7, 0xef, 0xc7, 0xab, 0xef, 0xff }, +/* char 0x2b (raw 0x2b) */ + { 0xff, 0xef, 0xef, 0x83, 0xef, 0xef, 0xff, 0xff }, +/* char 0x2c (raw 0x2c) */ + { 0xff, 0xff, 0xff, 0xff, 0xef, 0xef, 0xdf, 0xff }, +/* char 0x2d (raw 0x2d) */ + { 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff }, +/* char 0x2e (raw 0x2e) */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff }, +/* char 0x2f (raw 0x2f) */ + { 0xff, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0xff, 0xff }, +/* char 0x30 (raw 0x30) */ + { 0xc7, 0xbb, 0xb3, 0xab, 0x9b, 0xbb, 0xc7, 0xff }, +/* char 0x31 (raw 0x31) */ + { 0xef, 0xcf, 0xef, 0xef, 0xef, 0xef, 0xc7, 0xff }, +/* char 0x32 (raw 0x32) */ + { 0xc7, 0xbb, 0xfb, 0xe7, 0xdf, 0xbf, 0x83, 0xff }, +/* char 0x33 (raw 0x33) */ + { 0x83, 0xfb, 0xf7, 0xe7, 0xfb, 0xbb, 0xc7, 0xff }, +/* char 0x34 (raw 0x34) */ + { 0xf7, 0xe7, 0xd7, 0xb7, 0x83, 0xf7, 0xf7, 0xff }, +/* char 0x35 (raw 0x35) */ + { 0x83, 0xbf, 0x87, 0xfb, 0xfb, 0xbb, 0xc7, 0xff }, +/* char 0x36 (raw 0x36) */ + { 0xe3, 0xdf, 0xbf, 0x87, 0xbb, 0xbb, 0xc7, 0xff }, +/* char 0x37 (raw 0x37) */ + { 0x83, 0xfb, 0xf7, 0xef, 0xdf, 0xdf, 0xdf, 0xff }, +/* char 0x38 (raw 0x38) */ + { 0xc7, 0xbb, 0xbb, 0xc7, 0xbb, 0xbb, 0xc7, 0xff }, +/* char 0x39 (raw 0x39) */ + { 0xc7, 0xbb, 0xbb, 0xc3, 0xfb, 0xf7, 0x8f, 0xff }, +/* char 0x3a (raw 0x3a) */ + { 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xff, 0xff }, +/* char 0x3b (raw 0x3b) */ + { 0xff, 0xff, 0xef, 0xff, 0xef, 0xef, 0xdf, 0xff }, +/* char 0x3c (raw 0x3c) */ + { 0xf7, 0xef, 0xdf, 0xbf, 0xdf, 0xef, 0xf7, 0xff }, +/* char 0x3d (raw 0x3d) */ + { 0xff, 0xff, 0x83, 0xff, 0x83, 0xff, 0xff, 0xff }, +/* char 0x3e (raw 0x3e) */ + { 0xdf, 0xef, 0xf7, 0xfb, 0xf7, 0xef, 0xdf, 0xff }, +/* char 0x3f (raw 0x3f) */ + { 0xc7, 0xbb, 0xf7, 0xef, 0xef, 0xff, 0xef, 0xff }, +/* char 0x40 (raw 0x14) */ + { 0x08, 0x10, 0x6c, 0xfe, 0xfc, 0xfc, 0x7e, 0x6c }, +/* char 0x41 (raw 0x11) */ + { 0x08, 0x10, 0x6c, 0x82, 0x84, 0x84, 0x52, 0x6c }, +/* char 0x42 (raw 0xf5) */ + { 0x00, 0x00, 0x40, 0x60, 0x70, 0x78, 0x6c, 0x42 }, +/* char 0x43 (raw 0x82) */ + { 0xfe, 0x44, 0x28, 0x10, 0x10, 0x28, 0x54, 0xfe }, +/* char 0x44 (raw 0xeb) */ + { 0x00, 0x02, 0x04, 0x88, 0x50, 0x20, 0x20, 0x00 }, +/* char 0x45 (raw 0xe4) */ + { 0xfe, 0xfc, 0xfa, 0x36, 0xae, 0xde, 0xde, 0xfe }, +/* char 0x46 (raw 0xec) */ + { 0xfc, 0xfc, 0xfc, 0xdc, 0x9c, 0x00, 0x9e, 0xde }, +/* char 0x47 (raw 0xed) */ + { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe }, +/* char 0x48 (raw 0xee) */ + { 0x10, 0x20, 0x40, 0xfe, 0x40, 0x20, 0x10, 0x00 }, +/* char 0x49 (raw 0xe9) */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54 }, +/* char 0x4a (raw 0xef) */ + { 0x10, 0x10, 0x10, 0x10, 0x92, 0x54, 0x38, 0x10 }, +/* char 0x4b (raw 0xf0) */ + { 0x10, 0x38, 0x54, 0x92, 0x10, 0x10, 0x10, 0x10 }, +/* char 0x4c (raw 0xf1) */ + { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +/* char 0x4d (raw 0xf7) */ + { 0x02, 0x02, 0x02, 0x22, 0x62, 0xfe, 0x60, 0x20 }, +/* char 0x4e (raw 0xf6) */ + { 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc }, +/* char 0x4f (raw 0xaf) */ + { 0xc8, 0x18, 0x38, 0x7e, 0x38, 0x18, 0x08, 0xf6 }, +/* char 0x50 (raw 0xb8) */ + { 0x26, 0x30, 0x38, 0xfc, 0x38, 0x30, 0x20, 0xde }, +/* char 0x51 (raw 0xce) */ + { 0x02, 0x12, 0x10, 0xfe, 0x7c, 0x38, 0x12, 0x02 }, +/* char 0x52 (raw 0xe5) */ + { 0x02, 0x12, 0x38, 0x7c, 0xfe, 0x10, 0x12, 0x02 }, +/* char 0x53 (raw 0xea) */ + { 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00 }, +/* char 0x54 (raw 0xe6) */ + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfe }, +/* char 0x55 (raw 0xe8) */ + { 0x10, 0x08, 0x04, 0xfe, 0x04, 0x08, 0x10, 0x00 }, +/* char 0x56 (raw 0xd7) */ + { 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa }, +/* char 0x57 (raw 0xe3) */ + { 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54 }, +/* char 0x58 (raw 0xf4) */ + { 0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0xfe, 0x00 }, +/* char 0x59 (raw 0xe7) */ + { 0x00, 0x00, 0xfc, 0x02, 0x02, 0x02, 0xfe, 0x00 }, +/* char 0x5a (raw 0xf3) */ + { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, +/* char 0x5b (raw 0xd2) */ + { 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, +/* char 0x5c (raw 0xc7) */ + { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe }, +/* char 0x5d (raw 0xd4) */ + { 0x28, 0x28, 0xee, 0x00, 0xee, 0x28, 0x28, 0x00 }, +/* char 0x5e (raw 0xdf) */ + { 0xfe, 0x02, 0x02, 0x32, 0x32, 0x02, 0x02, 0xfe }, +/* char 0x5f (raw 0xd1) */ + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, +/* char 0x60 (raw 0x60) */ + { 0xdf, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff }, +/* char 0x61 (raw 0x61) */ + { 0xff, 0xff, 0xc7, 0xfb, 0xc3, 0xbb, 0xc3, 0xff }, +/* char 0x62 (raw 0x62) */ + { 0xbf, 0xbf, 0x87, 0xbb, 0xbb, 0xbb, 0x87, 0xff }, +/* char 0x63 (raw 0x63) */ + { 0xff, 0xff, 0xc3, 0xbf, 0xbf, 0xbf, 0xc3, 0xff }, +/* char 0x64 (raw 0x64) */ + { 0xfb, 0xfb, 0xc3, 0xbb, 0xbb, 0xbb, 0xc3, 0xff }, +/* char 0x65 (raw 0x65) */ + { 0xff, 0xff, 0xc7, 0xbb, 0x83, 0xbf, 0xc3, 0xff }, +/* char 0x66 (raw 0x66) */ + { 0xe7, 0xdb, 0xdf, 0x87, 0xdf, 0xdf, 0xdf, 0xff }, +/* char 0x67 (raw 0x67) */ + { 0xff, 0xff, 0xc7, 0xbb, 0xbb, 0xc3, 0xfb, 0xc7 }, +/* char 0x68 (raw 0x68) */ + { 0xbf, 0xbf, 0x87, 0xbb, 0xbb, 0xbb, 0xbb, 0xff }, +/* char 0x69 (raw 0x69) */ + { 0xef, 0xff, 0xcf, 0xef, 0xef, 0xef, 0xc7, 0xff }, +/* char 0x6a (raw 0x6a) */ + { 0xf7, 0xff, 0xe7, 0xf7, 0xf7, 0xf7, 0xb7, 0xcf }, +/* char 0x6b (raw 0x6b) */ + { 0xbf, 0xbf, 0xbb, 0xb7, 0x8f, 0xb7, 0xbb, 0xff }, +/* char 0x6c (raw 0x6c) */ + { 0xcf, 0xef, 0xef, 0xef, 0xef, 0xef, 0xc7, 0xff }, +/* char 0x6d (raw 0x6d) */ + { 0xff, 0xff, 0x93, 0xab, 0xab, 0xab, 0xbb, 0xff }, +/* char 0x6e (raw 0x6e) */ + { 0xff, 0xff, 0x87, 0xbb, 0xbb, 0xbb, 0xbb, 0xff }, +/* char 0x6f (raw 0x6f) */ + { 0xff, 0xff, 0xc7, 0xbb, 0xbb, 0xbb, 0xc7, 0xff }, +/* char 0x70 (raw 0x70) */ + { 0xff, 0xff, 0x87, 0xbb, 0xbb, 0x87, 0xbf, 0xbf }, +/* char 0x71 (raw 0x71) */ + { 0xff, 0xff, 0xc3, 0xbb, 0xbb, 0xc3, 0xfb, 0xfb }, +/* char 0x72 (raw 0x72) */ + { 0xff, 0xff, 0xa3, 0x9f, 0xbf, 0xbf, 0xbf, 0xff }, +/* char 0x73 (raw 0x73) */ + { 0xff, 0xff, 0xc3, 0xbf, 0xc7, 0xfb, 0x87, 0xff }, +/* char 0x74 (raw 0x74) */ + { 0xdf, 0xdf, 0x87, 0xdf, 0xdf, 0xdb, 0xe7, 0xff }, +/* char 0x75 (raw 0x75) */ + { 0xff, 0xff, 0xbb, 0xbb, 0xbb, 0xb3, 0xcb, 0xff }, +/* char 0x76 (raw 0x76) */ + { 0xff, 0xff, 0xbb, 0xbb, 0xbb, 0xd7, 0xef, 0xff }, +/* char 0x77 (raw 0x77) */ + { 0xff, 0xff, 0xbb, 0xbb, 0xab, 0xab, 0x93, 0xff }, +/* char 0x78 (raw 0x78) */ + { 0xff, 0xff, 0xbb, 0xd7, 0xef, 0xd7, 0xbb, 0xff }, +/* char 0x79 (raw 0x79) */ + { 0xff, 0xff, 0xbb, 0xbb, 0xbb, 0xc3, 0xfb, 0xc7 }, +/* char 0x7a (raw 0x7a) */ + { 0xff, 0xff, 0x83, 0xf7, 0xef, 0xdf, 0x83, 0xff }, +/* char 0x7b (raw 0x7b) */ + { 0xe3, 0xcf, 0xcf, 0x9f, 0xcf, 0xcf, 0xe3, 0xff }, +/* char 0x7c (raw 0x7c) */ + { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef }, +/* char 0x7d (raw 0x7d) */ + { 0x8f, 0xe7, 0xe7, 0xf3, 0xe7, 0xe7, 0x8f, 0xff }, +/* char 0x7e (raw 0x7e) */ + { 0xcb, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, +/* char 0x7f (raw 0x7f) */ + { 0xff, 0xab, 0xd7, 0xab, 0xd7, 0xab, 0xff, 0xff }, +/* char 0x80 (raw 0x40) */ + { 0x38, 0x44, 0x54, 0x5c, 0x58, 0x40, 0x3c, 0x00 }, +/* char 0x81 (raw 0x41) */ + { 0x10, 0x28, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x00 }, +/* char 0x82 (raw 0x42) */ + { 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 }, +/* char 0x83 (raw 0x43) */ + { 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 }, +/* char 0x84 (raw 0x44) */ + { 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x00 }, +/* char 0x85 (raw 0x45) */ + { 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7c, 0x00 }, +/* char 0x86 (raw 0x46) */ + { 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 }, +/* char 0x87 (raw 0x47) */ + { 0x3c, 0x40, 0x40, 0x40, 0x4c, 0x44, 0x3c, 0x00 }, +/* char 0x88 (raw 0x48) */ + { 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00 }, +/* char 0x89 (raw 0x49) */ + { 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 }, +/* char 0x8a (raw 0x4a) */ + { 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00 }, +/* char 0x8b (raw 0x4b) */ + { 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 }, +/* char 0x8c (raw 0x4c) */ + { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x00 }, +/* char 0x8d (raw 0x4d) */ + { 0x44, 0x6c, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00 }, +/* char 0x8e (raw 0x4e) */ + { 0x44, 0x44, 0x64, 0x54, 0x4c, 0x44, 0x44, 0x00 }, +/* char 0x8f (raw 0x4f) */ + { 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 }, +/* char 0x90 (raw 0x50) */ + { 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00 }, +/* char 0x91 (raw 0x51) */ + { 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00 }, +/* char 0x92 (raw 0x52) */ + { 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00 }, +/* char 0x93 (raw 0x53) */ + { 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00 }, +/* char 0x94 (raw 0x54) */ + { 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 }, +/* char 0x95 (raw 0x55) */ + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 }, +/* char 0x96 (raw 0x56) */ + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 }, +/* char 0x97 (raw 0x57) */ + { 0x44, 0x44, 0x44, 0x54, 0x54, 0x6c, 0x44, 0x00 }, +/* char 0x98 (raw 0x58) */ + { 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 }, +/* char 0x99 (raw 0x59) */ + { 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00 }, +/* char 0x9a (raw 0x5a) */ + { 0x7c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7c, 0x00 }, +/* char 0x9b (raw 0x5b) */ + { 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00 }, +/* char 0x9c (raw 0x5c) */ + { 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00 }, +/* char 0x9d (raw 0x5d) */ + { 0x7c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00 }, +/* char 0x9e (raw 0x5e) */ + { 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00 }, +/* char 0x9f (raw 0x5f) */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe }, +/* char 0xa0 (raw 0x20) */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +/* char 0xa1 (raw 0x21) */ + { 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00 }, +/* char 0xa2 (raw 0x22) */ + { 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00 }, +/* char 0xa3 (raw 0x23) */ + { 0x28, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x28, 0x00 }, +/* char 0xa4 (raw 0x24) */ + { 0x10, 0x3c, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00 }, +/* char 0xa5 (raw 0x25) */ + { 0x60, 0x64, 0x08, 0x10, 0x20, 0x4c, 0x0c, 0x00 }, +/* char 0xa6 (raw 0x26) */ + { 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00 }, +/* char 0xa7 (raw 0x27) */ + { 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 }, +/* char 0xa8 (raw 0x28) */ + { 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00 }, +/* char 0xa9 (raw 0x29) */ + { 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00 }, +/* char 0xaa (raw 0x2a) */ + { 0x10, 0x54, 0x38, 0x10, 0x38, 0x54, 0x10, 0x00 }, +/* char 0xab (raw 0x2b) */ + { 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00 }, +/* char 0xac (raw 0x2c) */ + { 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00 }, +/* char 0xad (raw 0x2d) */ + { 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00 }, +/* char 0xae (raw 0x2e) */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }, +/* char 0xaf (raw 0x2f) */ + { 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00 }, +/* char 0xb0 (raw 0x30) */ + { 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38, 0x00 }, +/* char 0xb1 (raw 0x31) */ + { 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 }, +/* char 0xb2 (raw 0x32) */ + { 0x38, 0x44, 0x04, 0x18, 0x20, 0x40, 0x7c, 0x00 }, +/* char 0xb3 (raw 0x33) */ + { 0x7c, 0x04, 0x08, 0x18, 0x04, 0x44, 0x38, 0x00 }, +/* char 0xb4 (raw 0x34) */ + { 0x08, 0x18, 0x28, 0x48, 0x7c, 0x08, 0x08, 0x00 }, +/* char 0xb5 (raw 0x35) */ + { 0x7c, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00 }, +/* char 0xb6 (raw 0x36) */ + { 0x1c, 0x20, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00 }, +/* char 0xb7 (raw 0x37) */ + { 0x7c, 0x04, 0x08, 0x10, 0x20, 0x20, 0x20, 0x00 }, +/* char 0xb8 (raw 0x38) */ + { 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00 }, +/* char 0xb9 (raw 0x39) */ + { 0x38, 0x44, 0x44, 0x3c, 0x04, 0x08, 0x70, 0x00 }, +/* char 0xba (raw 0x3a) */ + { 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00 }, +/* char 0xbb (raw 0x3b) */ + { 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x20, 0x00 }, +/* char 0xbc (raw 0x3c) */ + { 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00 }, +/* char 0xbd (raw 0x3d) */ + { 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00 }, +/* char 0xbe (raw 0x3e) */ + { 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00 }, +/* char 0xbf (raw 0x3f) */ + { 0x38, 0x44, 0x08, 0x10, 0x10, 0x00, 0x10, 0x00 }, +/* char 0xc0 (raw 0x40) */ + { 0x38, 0x44, 0x54, 0x5c, 0x58, 0x40, 0x3c, 0x00 }, +/* char 0xc1 (raw 0x41) */ + { 0x10, 0x28, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x00 }, +/* char 0xc2 (raw 0x42) */ + { 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 }, +/* char 0xc3 (raw 0x43) */ + { 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 }, +/* char 0xc4 (raw 0x44) */ + { 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x00 }, +/* char 0xc5 (raw 0x45) */ + { 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7c, 0x00 }, +/* char 0xc6 (raw 0x46) */ + { 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 }, +/* char 0xc7 (raw 0x47) */ + { 0x3c, 0x40, 0x40, 0x40, 0x4c, 0x44, 0x3c, 0x00 }, +/* char 0xc8 (raw 0x48) */ + { 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00 }, +/* char 0xc9 (raw 0x49) */ + { 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 }, +/* char 0xca (raw 0x4a) */ + { 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00 }, +/* char 0xcb (raw 0x4b) */ + { 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 }, +/* char 0xcc (raw 0x4c) */ + { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x00 }, +/* char 0xcd (raw 0x4d) */ + { 0x44, 0x6c, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00 }, +/* char 0xce (raw 0x4e) */ + { 0x44, 0x44, 0x64, 0x54, 0x4c, 0x44, 0x44, 0x00 }, +/* char 0xcf (raw 0x4f) */ + { 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 }, +/* char 0xd0 (raw 0x50) */ + { 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00 }, +/* char 0xd1 (raw 0x51) */ + { 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00 }, +/* char 0xd2 (raw 0x52) */ + { 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00 }, +/* char 0xd3 (raw 0x53) */ + { 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00 }, +/* char 0xd4 (raw 0x54) */ + { 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 }, +/* char 0xd5 (raw 0x55) */ + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 }, +/* char 0xd6 (raw 0x56) */ + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 }, +/* char 0xd7 (raw 0x57) */ + { 0x44, 0x44, 0x44, 0x54, 0x54, 0x6c, 0x44, 0x00 }, +/* char 0xd8 (raw 0x58) */ + { 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 }, +/* char 0xd9 (raw 0x59) */ + { 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00 }, +/* char 0xda (raw 0x5a) */ + { 0x7c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7c, 0x00 }, +/* char 0xdb (raw 0x5b) */ + { 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00 }, +/* char 0xdc (raw 0x5c) */ + { 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00 }, +/* char 0xdd (raw 0x5d) */ + { 0x7c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00 }, +/* char 0xde (raw 0x5e) */ + { 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00 }, +/* char 0xdf (raw 0x5f) */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe }, +/* char 0xe0 (raw 0x60) */ + { 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, +/* char 0xe1 (raw 0x61) */ + { 0x00, 0x00, 0x38, 0x04, 0x3c, 0x44, 0x3c, 0x00 }, +/* char 0xe2 (raw 0x62) */ + { 0x40, 0x40, 0x78, 0x44, 0x44, 0x44, 0x78, 0x00 }, +/* char 0xe3 (raw 0x63) */ + { 0x00, 0x00, 0x3c, 0x40, 0x40, 0x40, 0x3c, 0x00 }, +/* char 0xe4 (raw 0x64) */ + { 0x04, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x3c, 0x00 }, +/* char 0xe5 (raw 0x65) */ + { 0x00, 0x00, 0x38, 0x44, 0x7c, 0x40, 0x3c, 0x00 }, +/* char 0xe6 (raw 0x66) */ + { 0x18, 0x24, 0x20, 0x78, 0x20, 0x20, 0x20, 0x00 }, +/* char 0xe7 (raw 0x67) */ + { 0x00, 0x00, 0x38, 0x44, 0x44, 0x3c, 0x04, 0x38 }, +/* char 0xe8 (raw 0x68) */ + { 0x40, 0x40, 0x78, 0x44, 0x44, 0x44, 0x44, 0x00 }, +/* char 0xe9 (raw 0x69) */ + { 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00 }, +/* char 0xea (raw 0x6a) */ + { 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x48, 0x30 }, +/* char 0xeb (raw 0x6b) */ + { 0x40, 0x40, 0x44, 0x48, 0x70, 0x48, 0x44, 0x00 }, +/* char 0xec (raw 0x6c) */ + { 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 }, +/* char 0xed (raw 0x6d) */ + { 0x00, 0x00, 0x6c, 0x54, 0x54, 0x54, 0x44, 0x00 }, +/* char 0xee (raw 0x6e) */ + { 0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x44, 0x00 }, +/* char 0xef (raw 0x6f) */ + { 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 }, +/* char 0xf0 (raw 0x70) */ + { 0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40 }, +/* char 0xf1 (raw 0x71) */ + { 0x00, 0x00, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x04 }, +/* char 0xf2 (raw 0x72) */ + { 0x00, 0x00, 0x5c, 0x60, 0x40, 0x40, 0x40, 0x00 }, +/* char 0xf3 (raw 0x73) */ + { 0x00, 0x00, 0x3c, 0x40, 0x38, 0x04, 0x78, 0x00 }, +/* char 0xf4 (raw 0x74) */ + { 0x20, 0x20, 0x78, 0x20, 0x20, 0x24, 0x18, 0x00 }, +/* char 0xf5 (raw 0x75) */ + { 0x00, 0x00, 0x44, 0x44, 0x44, 0x4c, 0x34, 0x00 }, +/* char 0xf6 (raw 0x76) */ + { 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 }, +/* char 0xf7 (raw 0x77) */ + { 0x00, 0x00, 0x44, 0x44, 0x54, 0x54, 0x6c, 0x00 }, +/* char 0xf8 (raw 0x78) */ + { 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 }, +/* char 0xf9 (raw 0x79) */ + { 0x00, 0x00, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38 }, +/* char 0xfa (raw 0x7a) */ + { 0x00, 0x00, 0x7c, 0x08, 0x10, 0x20, 0x7c, 0x00 }, +/* char 0xfb (raw 0x7b) */ + { 0x1c, 0x30, 0x30, 0x60, 0x30, 0x30, 0x1c, 0x00 }, +/* char 0xfc (raw 0x7c) */ + { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, +/* char 0xfd (raw 0x7d) */ + { 0x70, 0x18, 0x18, 0x0c, 0x18, 0x18, 0x70, 0x00 }, +/* char 0xfe (raw 0x7e) */ + { 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +/* char 0xff (raw 0x7f) */ + { 0x00, 0x54, 0x28, 0x54, 0x28, 0x54, 0x00, 0x00 }, diff --git a/kegs/Src/kegsversion.h b/kegs/Src/kegsversion.h new file mode 100644 index 0000000..253a699 --- /dev/null +++ b/kegs/Src/kegsversion.h @@ -0,0 +1,10 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +const char* g_kegs_version_str = "0.91"; +const char* g_kegs_version_build = "3.7.1199"; diff --git a/kegs/Src/marinetti.cpp b/kegs/Src/marinetti.cpp new file mode 100644 index 0000000..0a977d7 --- /dev/null +++ b/kegs/Src/marinetti.cpp @@ -0,0 +1,881 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "sim65816.h" +#include "marinetti.h" + + +#ifdef NO_MARINETTI_SUPPORT +int process_marinetti_command(int _command,word32* param, word32& _regx, word32& _regy) +{ + return TCPIP_ERR_NO_DEVICE; +} + +void marinetti_init() +{ + printf("no marinetti support\n"); +} + +void marinetti_shutdown() +{ + +} + + +#else + +/* + 05/6187: SEGMENT ARRIVE + 05/6905: ACK_FINWAIT2 + 05/6945: ACK_CLOSING + 05/6cd5: PROCESSTHIS + 05/505f: TCPIPMangleDomainName + 05/4c70: TCPIPValidateI + 05/3f4d: PASC2HEXIP + 05/6DE0: BASICACK + */ + + + +// Constantes + +MAC_STRUCT server_mac_addr; +IP_STRUCT server_ip_addr; +IP_STRUCT server_identifier; +IP_STRUCT gateway_ip_addr; +MAC_STRUCT gateway_mac_addr; +IP_STRUCT gateway_dns_addr; +IP_STRUCT gateway_mask_addr; +IP_STRUCT client_ip_addr; +IP_STRUCT local_ip_addr; +IP_STRUCT host_ip_addr; + +// Globales + +MAC_STRUCT client_mac_addr; +int eth_first,eth_last; +eth_queue ethqueues[MAX_ETH_QUEUE]; +tcp_queue tcpqueues[MAX_TCP_QUEUE]; +PConnection PConnections[MAX_TCP_CONNECTION]; + +double start_tcp_time; + +void marinetti_init() +{ + + MAC_SET(server_mac_addr,0xAB,0xAB,0xAB,0xAB,0xAB, 0xAB ); + IP_SET(server_ip_addr, 100,100,0,1 ); + IP_SET(server_identifier, 9,9,9,9 ); + IP_SET(gateway_ip_addr,128,0,0,254 ); + MAC_SET(gateway_mac_addr,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA ); + IP_SET(gateway_dns_addr, 208,67,222,222); // OPENDNS + IP_SET(gateway_mask_addr, 255,255,255,0 ); + IP_SET(client_ip_addr,128,0,0,100 ); + IP_SET(local_ip_addr,127,0,0,1 ); + IP_SET(host_ip_addr,128,0,0,1 ); + + +} + +void marinetti_shutdown() +{ + for(int i=0;iudp+sizeof(UDP_HEADER)); + int dhcplen = ntohs(p->udp.udp_len)-sizeof(UDP_HEADER); + + packet->udp.udp_dst = p->udp.udp_src; // inverse + packet->udp.udp_src = p->udp.udp_dst; // inverse + + DHCP_HEADER* target = (DHCP_HEADER*)((byte*)&packet->udp + sizeof(UDP_HEADER)); + // construit la rponse en UDP + byte* response_str = (byte*)target; + + unsigned int pos= sizeof(DHCP_HEADER)-DHCP_OPTION_LEN; + unsigned int parse= 0; + const byte* dhcp_request = _dhcp->options; + + // vrifie le magic cookie + if ( + dhcp_request[0]!=99 + || dhcp_request[1]!=130 + || dhcp_request[2]!=83 + || dhcp_request[3]!=99) + { + printf("invalid magic cookie\n"); + return 0; + } + memcpy(&response_str[pos],dhcp_request,4); + parse+=4; + pos+=4; + + while( parse < ( dhcplen - ( sizeof(DHCP_HEADER) - DHCP_OPTION_LEN) ) ) + { + int cmd = dhcp_request[parse++]; + if (cmd==255) //-1 + break; + int len = dhcp_request[parse++]; + + switch(cmd) + { + case 53: // messagetype + { + int type = dhcp_request[parse]; + response_str[pos++]=53; + response_str[pos++]=1; + + switch(type) + { + case dhcpdiscover: + printf(" ### [DHCP] dhcpdiscover"); + response_str[pos++]=dhcpoffer; + break; + case dhcprequest: // request + printf(" ### [DHCP] dhcprequest"); + response_str[pos++]=dhcppack; + break; + + } + } + break; + + case 55: // options + { + for(int l=0;ludp.udp_len = htons(sizeof(UDP_HEADER) + pos); + + packet->ip.protocol = 17; // udp + packet->ip.ver = 4; + packet->ip.ihl = 5; + packet->ip.ttl = 64; + packet->ip.ucSource = server_ip_addr; + packet->ip.ucDestination = client_ip_addr; + packet->ip.length = htons(sizeof(IP_HEADER)+sizeof(UDP_HEADER) + pos); + + packet->eth.type = htons(0x0800); // IP + packet->eth.dest_mac = client_mac_addr ; + packet->eth.source_mac = server_mac_addr ; + + target->yiaddr = client_ip_addr; + *(MAC_STRUCT*)&target->chaddr = client_mac_addr; + target->xid = _dhcp->xid; + packet->queuelen = sizeof(ETH_HEADER)+sizeof(IP_HEADER)+sizeof(UDP_HEADER) + pos; + packet->iplen = sizeof(UDP_HEADER) + pos; + packet->state = QS_TOSEND; + return 1; +} + + +int process_marinetti_command(int _command,word32* _param, word32& _regx, word32& _regy) +{ + + switch(_command) + { + case TCPIP_CMD_STARTUP: + { + printf("TCPIP_CMD_STARTUP\n"); +#ifdef _WIN32 + int err; + + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 2); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) + { + printf("WSAStartup failed with error: %d\n", err); + return TCPIP_ERR_STARTUP_FAILED; + } +#endif + + return 0; + } + break; + + case TCPIP_CMD_GET_DATAGRAM: + { + _param[1]=0; + + server_loop(); + + // if (eth_first == eth_last) + for(int i=0;itcpsocket>=0) + { + if (p->socktype == PCT_HOST && p->type==RT_UDP )// && p->udp_query) + { + + // regarde si il y a des donnes de dispo + fd_set input_set; + timeval timeout; + timeout.tv_usec = 1; + timeout.tv_sec = 0; + FD_ZERO(&input_set); + FD_SET(p->tcpsocket,&input_set); + int s = select(p->tcpsocket+1,&input_set,NULL,NULL,&timeout); + if (s>0) + { + + byte recvbuf[MAX_UDP_SIZE]; + int iResult = recv(p->tcpsocket, (char*)recvbuf, MAX_UDP_SIZE, 0); + if ( iResult > 0 ) + { + _LOG("Bytes received: %d\n", iResult); + // p->udp_query--; + p->sendudppacket(iResult,recvbuf); + } + else if ( iResult == 0 ) + printf("Connection closed\n"); + else + printf("recv failed: %d\n", SockLastError()); + } + else + if (s==SOCKET_ERROR) + printf("select failed: %d\n", SockLastError()); + } + else + if ( p->type==RT_TCP && p->state == PCS_CLEARINGQUEUE) + { + // regarde si il y a encore des donnes envoyer pour cette connection + int empty=1; + for(int q=0;qstate = PCS_LASTACK; + p->sendtcppacket(TCP_ACK|TCP_FIN,0,NULL); + p->state_seq = p->send_seq; + printf("\nLAST ACK SENT\n"); + } + + } + else + if ( p->type==RT_TCP&& p->state == PCS_ESTABLISHED && (p->already_sent<(p->window-MAX_TCP_SIZE))) + { + // regarde si il y a des donnes TCP en entre + // regarde si il y a des donnes de dispo + fd_set input_set; + timeval timeout; + timeout.tv_usec = 1; + timeout.tv_sec = 0; + FD_ZERO(&input_set); + FD_SET(p->tcpsocket,&input_set); + int s = select(p->tcpsocket+1,&input_set,NULL,NULL,&timeout); + if (s>0) + { + byte recv_data[MAX_TCP_SIZE]; // window max size + int lr =recv(p->tcpsocket,(char*)recv_data,MAX_TCP_SIZE,0); + if (lr>0) + { + // p->udp_query--; + if (lr>p->window) + printf("*** overflow ***\n"); + + p->sendtcppacket(TCP_ACK,lr,recv_data); + + } + } + } + } + } + + // ajout les TCP la liste des datagrammes envoyer + + for(int q=0;qstate == QS_TOSEND||tcp->state == QS_TOSENDANDRETRY ) + { + printf("\n<print(); + + static int identification=1; + + int sent = 0; + identification++; + while(sent < tcp->iplen) + { + int tosend = tcp->iplen - sent; + int frag = 0; + + eth_queue* qdest = findETHQueue(); + if (!qdest) + { + printf("\n *** no more queue ***\n"); + // not sure how it will recover??? + break; + } + + qdest->eth = tcp->eth; + qdest->ip = tcp->ip; + + if (tosend>ETH_MAX_SIZE) + { + frag = FLAG_MF; + tosend = ETH_MAX_SIZE; + } + + qdest->ip.flag_offset = htons(frag + sent/8); + qdest->ip.identification = identification; + qdest->ip.length = htons(tosend+sizeof(IP_HEADER)); + qdest->ip.checksum = 0; + qdest->queuelen = tosend+sizeof(IP_HEADER)+sizeof(ETH_HEADER); + + memcpy(((byte*)&qdest->ip) + sizeof(IP_HEADER),((const byte*)&tcp->padding) + sent,tosend); + u16 chkip= ip_sum_calc(sizeof(IP_HEADER),(const byte*)&qdest->ip); + qdest->ip.checksum = htons(chkip); + + sent += tosend; + } + + if (tcp->state == QS_TOSENDANDRETRY) + { + tcp->state = QS_SENT; + tcp->timeout =get_dtime(); + } + else + { + tcp->state = QS_IDLE; // pas d'ack + } + + } + else + if (tcp->state == QS_SENT) + { + double tick = get_dtime(); + if (tick - tcp->timeout>30.0) // 5 000ms + { + if (tcp->connection->state != PCS_ESTABLISHED) + { + tcp->state = QS_IDLE; + printf("syn did not succeed...\n"); + tcp->connection->Reset(); + } + else + { + printf("\nretrying..."); + tcp->state = QS_TOSENDANDRETRY; + } + } + } + } + + // envoie les datagrammes (dans l'ordre) + if (eth_first != eth_last) + { + eth_queue& q = ethqueues[eth_first]; + eth_first = (eth_first+1)% MAX_ETH_QUEUE; + q.print(); + + word32 p = _param[0]; + byte* pdata = (byte*)&g_memory_ptr[p]; + _param[1] = q.queuelen; + memcpy((void*)pdata,&q.eth,_param[1]); + *((byte*)pdata+q.queuelen) = 0; + + } + + return 0; + } + break; + + case TCPIP_CMD_SEND_DATAGRAM: + { + + word32 len = _param[1] & 0xFFFF; + byte* pdata = ( byte*)&g_memory_ptr[_param[0]]; + *(pdata+len) = 0; // odd-even + + eth_queue* p = (eth_queue*)pdata; + +#ifdef DEBUG_ETH + int d = (int)((get_dtime()-start_tcp_time)*1000); + printf("\n>>>[%07d]\n",d); +#endif + + int t = ntohs(p->eth.type); + switch(t) + { + case 0x0806: // arp + { + + print_arp(&p->arp); + eth_queue* packet = findETHQueue(); + if (!packet) + return TCPIP_ERR_UNSUPPORTED; + + + MAC_STRUCT target_mac; + IP_STRUCT target_ip = p->arp.dst_protoaddr; + if (GET_INT_FROM_IP(p->arp.dst_protoaddr) == GET_INT_FROM_IP(gateway_ip_addr)) + target_mac = gateway_mac_addr; + else + target_mac.SetFromIP(target_ip); + + packet->eth.type = ntohs(0x0806); + packet->eth.dest_mac = client_mac_addr; + packet->eth.source_mac = target_mac; //gateway_mac_addr; + + // copie la source en dest + packet->arp.dst_hwaddr = p->arp.src_hwaddr; + packet->arp.dst_protoaddr = p->arp.src_protoaddr; + + // remplis le destinataire + packet->arp.src_hwaddr =target_mac; //gateway_mac_addr; + packet->arp.src_protoaddr = target_ip; //gateway_ip_addr; + packet->arp.hwaddr_format = p->arp.hwaddr_format; + packet->arp.hwaddr_length = p->arp.hwaddr_length; + packet->arp.opcode = htons(2); // reply + packet->queuelen = sizeof(ARP_HEADER)+sizeof(ETH_HEADER); + + } + break; + case 0x0800: // IP + { + print_ip_packet(&p->ip); + // ajoute les donnes dans unfragmented + add_fragment(p); + } + break; + default: + printf("unsupported protocol"); + return TCPIP_ERR_UNSUPPORTED; + } + + } + return 0; + + case TCPIP_CMD_CONNECT: + for(int i=0;istate == QS_IDLE) + free_frag = q; + + if (tcp->state == QS_FRAGMENT && tcp->ip.identification == f->ip.identification) + return tcp; + } + + if (free_frag == -1) + { + printf("\n*** no more TCP queues****\n"); + return NULL; + } + tcp = &tcpqueues[free_frag]; + memset(tcp,0,sizeof(tcp_queue)); + tcp->state = QS_FRAGMENT; + tcp->eth = f->eth; + tcp->ip = f->ip; + return tcp; + +} + + +tcp_queue* findTCPQueue() +{ + tcp_queue* q = NULL; + for(int i=0;istate = QS_IDLE; + return q; + } + } + printf("\n*** no more TCP queues****\n"); + return q; +} + + + +int add_fragment(eth_queue* p) +{ + tcp_queue* f = findTCPQueueByFragment(p); + if (!f) + return 0; + + // ajoute les donnes + f->ip = p->ip; + f->eth = p->eth; + + int ipdatalen = ntohs(p->ip.length) - sizeof(IP_HEADER); + + memcpy(f->padding+f->iplen,(const byte*)&p->ip+sizeof(IP_HEADER),ipdatalen); + f->iplen += ipdatalen; + + int fo = ntohs(p->ip.flag_offset); + if (!(fo & FLAG_MF)) + { + process_unfragmented(f); + f->state=QS_IDLE; + } + + return 1; +} + +int process_unfragmented(tcp_queue* p) +{ + + int ip_protocol = p->ip.protocol; + p->print(); + + if (ip_protocol==17) // udp + { + + int dest_port = ntohs(p->udp.udp_dst); + int src_port = ntohs(p->udp.udp_src); + + if (p->isDHCP()) + { + send_dhcp_response(p); + } + else + { + print_udp(&p->udp); + + // cre une nouvelle connection udp + PConnection* pco = init_connection(PCT_HOST,RT_UDP, src_port,p->ip.ucDestination, dest_port, p->eth.dest_mac,0); + if (pco==NULL) + { + printf("\ncannot init connection\n"); + return TCPIP_ERR_SEND; + } + + // envoie la commande + struct sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr = p->ip.ucDestination; + server.sin_port = htons( dest_port ); + + int len = ntohs(p->udp.udp_len)-sizeof(UDP_HEADER); + const char* data = (const char*)&p->udp+sizeof(UDP_HEADER); + // prpare la rponse + int ret = sendto(pco->tcpsocket, data, len, 0, (struct sockaddr *) &server,sizeof(server) ); + if (ret< 0) + { +#ifdef _DEBUG + int err = SockLastError(); + printf("socket send failed with err:%d\n",err); +#endif + return TCPIP_ERR_SEND; + } + } + } + else + if (ip_protocol==6) // tcp + { + +#ifdef _DEBUG + int chk = p->check_tcp(); + if (!chk) + { + printf("ignoring packet\n"); + return 0; + } +#endif + + int offset =p->tcp.data_offset*4; + int tcplen = p->iplen - offset; + + int dest_port = ntohs(p->tcp.dest_port); + int source_port = ntohs(p->tcp.src_port); + struct in_addr dest_ip; + dest_ip= p->ip.ucDestination; + + const byte *tcpdata = (const byte*)&p->tcp +offset; + + if (p->tcp.flags & TCP_RST) + { + printf("\n*** CONNECTION RESET ***\n"); + const char* reset_str = "HTTP/1.0 500"; + ::send(p->connection->tcpsocket, (const char*)reset_str, strlen(reset_str), 0); + reset_connection(PCT_HOST,RT_TCP,source_port,dest_ip,dest_port); + + } + + if (p->tcp.flags & TCP_ACK) + { + PConnection* ptcp = find_connection(PCT_HOST,RT_TCP,source_port,dest_ip, dest_port); + if (ptcp) + { + // libre les query correspondantes + int ack_seq = ntohl(p->tcp.ack_number); + + for(int q=0;qalready_sent -= tcpqueues[q].tcplen; + if (ptcp->already_sent<0) + { + printf("too many acked!***\n"); + ptcp->already_sent=0; // pour essayer de se rcuprer + } + + tcpqueues[q].state = QS_IDLE; + } + } + if (ptcp->state == PCS_BEINGESTABLISHED && (ptcp->state_seq+1) == ack_seq) + { + ptcp->state = PCS_ESTABLISHED; + ptcp->send_seq++; + printf("\nCONNECTION ESTABLISHED (SERVER)\n"); + } + else + if (ptcp->state == PCS_SYNSENT && (ptcp->state_seq+1) == ack_seq) + { + ptcp->sendtcppacket(TCP_ACK , 0, NULL); + ptcp->state = PCS_ESTABLISHED; + ptcp->send_seq++; + printf("\nCONNECTION ESTABLISHED2 (CLIENT)\n"); + + } + else + if (ptcp->state == PCS_SYNCHING && (ptcp->state_seq+1) == ack_seq) + { + ptcp->state = PCS_ESTABLISHED; + printf("\nCONNECTION ESTABLISHED (CLIENT)\n"); + ptcp->send_seq++; + } + else + if (ptcp->state == PCS_CLOSING && ptcp->state_seq == ack_seq) + { + // envoie notre data de fin + ptcp->state = PCS_CLEARINGQUEUE; + + } + else + if (ptcp->state == PCS_LASTACK && ( ptcp->state_seq + 1) == ack_seq) + { + // envoie notre data de fin, mais n'attend pas de rponse + ptcp->last_ack = ntohl(p->tcp.seq_number)+1; + ptcp->sendtcppacket(TCP_ACK,0,NULL); + ptcp->Reset(); + printf("\nCONNECTION CLOSED\n"); + } + + + } + + } + + if (p->tcp.flags & TCP_FIN) + { + PConnection* ptcp = find_connection(PCT_HOST,RT_TCP,source_port,dest_ip, dest_port); + if (ptcp) + { + printf("\nclose_wait\n"); + + ptcp->last_ack = ntohl(p->tcp.seq_number)+2; + ptcp->sendtcppacket(TCP_ACK , 0, NULL); + ptcp->state_seq = ptcp->send_seq; + ptcp->state = PCS_CLOSING; + } + } + + + if (p->tcp.flags & TCP_SYN && !(p->tcp.flags & TCP_ACK)) + { + PConnection* ptcp = init_connection(PCT_HOST,RT_TCP,source_port,dest_ip, dest_port,p->eth.dest_mac, ntohs(p->tcp.window)); + if (ptcp==NULL) + return TCPIP_ERR_NO_CONNECTION; + + ptcp->last_ack = ntohl(p->tcp.seq_number)+1; + ptcp->state = PCS_SYNCHING; + ptcp->state_seq = ptcp->send_seq; + ptcp->sendtcppacket(TCP_ACK|TCP_SYN, 0, NULL); + + } + + if (tcplen) + { + PConnection* ptcp = find_connection(PCT_HOST,RT_TCP,source_port,dest_ip, dest_port); + if (ptcp==NULL) + return TCPIP_ERR_NO_CONNECTION; + + int ret = send(ptcp->tcpsocket, (const char*)tcpdata, tcplen, 0); + if (ret< 0) + { +#ifdef _DEBUG + int err = SockLastError(); + printf("socket send failed with err:%d\n",err); +#endif + return TCPIP_ERR_SEND; + } + + // envoie l'ack + ptcp->last_ack = ntohl( p->tcp.seq_number) +tcplen ; + ptcp->sendtcppacket(TCP_ACK , 0, NULL); + + } + + } + else + { + printf("unsupported ip protocol\n"); + return TCPIP_ERR_UNSUPPORTED; + } + + return 1; +} + +#endif diff --git a/kegs/Src/marinetti.h b/kegs/Src/marinetti.h new file mode 100644 index 0000000..a4279be --- /dev/null +++ b/kegs/Src/marinetti.h @@ -0,0 +1,460 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#if defined(ACTIVEGS_ANDROID) + // not tester yet! + #define NO_MARINETTI_SUPPORT +#endif + +#ifndef NO_MARINETTI_SUPPORT + #ifdef WIN32 + #include + #include + #include + #pragma comment(lib, "Ws2_32.lib") + #else + #include + #include + #include + #include + #include + #include + #include + #endif +#endif // NO MARINETTI SUPPORT + + + +#define MAX_TCP_QUEUE 32 +#define MAX_ETH_QUEUE 64 + +#define MAX_TCP_SIZE 2048 +#define MAX_UDP_SIZE 2048 +#define MTU 1500 + + +#define TCPIP_ERR_NO_DEVICE 1 // No network device found +#define TCPIP_ERR_NO_CONNECTION 2 // Unable to connect to network device +#define TCPIP_ERR_STARTUP_FAILED 3 // Unable to initiate network access +#define TCPIP_ERR_UNSUPPORTED 4 // An unsupported operation was attempted +#define TCPIP_ERR_MEMORY 5 // Unable to allocate buffer memory +#define TCPIP_ERR_SEND 6 // Error sending packet + +extern void marinetti_init(); +extern void marinetti_shutdown(); + + +#ifndef NO_MARINETTI_SUPPORT + +// helpers + +typedef unsigned short u16; +typedef unsigned long u32; + + +#pragma pack(push) +#pragma pack(1) + +#ifdef WIN32 +#define SockLastError() WSAGetLastError() +#define SockClose(X) if (X>=0) { closesocket(X); printf("\n sock %d closed\n",X); X=-1; } +#else +#define SockLastError() -1 +#define SockClose(X) if (X>=0) { close(X); X=-1; } +#define SOCKET_ERROR -1 +#endif + + +#define _LOG(...) do {} while(0) +#ifndef _DEBUG + #undef printf + #define printf(...) do {} while(0) +#endif + +enum enum_response_type +{ + RT_NA=0, + RT_UDP=100, + RT_ARP=101, + RT_DHCP=102, + RT_DNS=103, + RT_TCP=104 +}; + +// ETH/IP/UDP/ARP/TCP/DHCP HEADER + +#define dhcpdiscover 1 +#define dhcpoffer 2 +#define dhcprequest 3 +#define dhcpdecline 4 +#define dhcppack 5 +#define dhcpnack 6 +#define dhcprelease 7 +#define dhcpinform 8 + +// DNS STRUCT +typedef in_addr IP_STRUCT; + +#ifdef WIN32 +#define GET_INT_FROM_IP(X) X.S_un.S_addr +#else +#define GET_INT_FROM_IP(X) X.s_addr +#endif + +struct MAC_STRUCT +{ + + byte addr[6]; MAC_STRUCT& operator=(const byte* _ptr) + { + memcpy(addr,_ptr,6); + return *this; + }; + + void SetFromIP(IP_STRUCT _ip) + { + memset(addr,0x88,6); + *(int*)&addr[0]=GET_INT_FROM_IP(_ip); + }; +} ; + + +#define IP_SET(i,d,c,b,a) GET_INT_FROM_IP(i) = ((a << 24) + (b << 16) + (c << 8) + d) +#define MAC_SET(m,a,b,c,d,e,f) m.addr[0]=a;m.addr[1]=b;m.addr[2]=c;m.addr[3]=d;m.addr[4]=e;m.addr[5]=f; + + +typedef struct +{ + MAC_STRUCT dest_mac; + MAC_STRUCT source_mac; + unsigned short int type; +} ETH_HEADER; + + +#define FLAG_MF 0x2000 +#define GET_OFFSET(X) ((X & 0x1FFF)*8) + +typedef struct +{ + unsigned char ihl:4; + unsigned char ver:4; + unsigned char tos; + unsigned short int length; + unsigned short int identification; + unsigned short int flag_offset; +// unsigned short int offset:13; + unsigned char ttl; + unsigned char protocol; + unsigned short int checksum; + IP_STRUCT ucSource; + IP_STRUCT ucDestination; +} IP_HEADER; + +#define DHCP_SNAME_LEN 64 +#define DHCP_FILE_LEN 128 +#define DHCP_FIXED_NON_UDP 236 +#define DHCP_OPTION_LEN 1500 + +typedef struct +{ + byte op; /* 0: Message opcode/type */ + byte htype; /* 1: Hardware addr type (net/if_types.h) */ + byte hlen; /* 2: Hardware addr length */ + byte hops; /* 3: Number of relay agent hops from client */ + u32 xid; /* 4: Transaction ID */ + u16 secs; /* 8: Seconds since client started looking */ + u16 flags; /* 10: Flag bits */ + IP_STRUCT ciaddr; /* 12: Client IP address (if already in use) */ + IP_STRUCT yiaddr; /* 16: Client IP address */ + IP_STRUCT siaddr; /* 18: IP address of next server to talk to */ + IP_STRUCT giaddr; /* 20: DHCP relay agent IP address */ + unsigned char chaddr [16]; /* 24: Client hardware address */ + char sname [DHCP_SNAME_LEN]; /* 40: Server name */ + char file [DHCP_FILE_LEN]; /* 104: Boot filename */ + unsigned char options [DHCP_OPTION_LEN]; + /* 212: Optional parameters + (actual length dependent on MTU). */ +} DHCP_HEADER; + +typedef struct +{ + unsigned short src_port; + unsigned short dest_port; + unsigned int seq_number; + unsigned int ack_number; + unsigned char padding1:4; + unsigned char data_offset:4; + unsigned char flags; + +#define TCP_FIN (1 << 0) +#define TCP_SYN (1 << 1) +#define TCP_RST (1 << 2) +#define TCP_PSH (1 << 3) +#define TCP_ACK (1 << 4) +#define TCP_URG (1 << 5) + + unsigned short window; + unsigned short checksum; + unsigned short urgent_pointer; + unsigned int options; + +} TCP_HEADER; + +typedef struct +{ + u16 udp_src; + u16 udp_dst; + u16 udp_len; + u16 udp_chk; +} UDP_HEADER; + +typedef struct +{ +unsigned short id; // identification number +unsigned char rd :1; // recursion desired +unsigned char tc :1; // truncated message +unsigned char aa :1; // authoritive answer +unsigned char opcode :4; // purpose of message +unsigned char qr :1; // query/response flag +unsigned char rcode :4; // response code +unsigned char cd :1; // checking disabled +unsigned char ad :1; // authenticated data +unsigned char z :1; // its z! reserved +unsigned char ra :1; // recursion available +unsigned short q_count; // number of question entries +unsigned short ans_count; // number of answer entries +unsigned short auth_count; // number of authority entries +unsigned short add_count; // number of resource entries +} DNS_HEADER; + +typedef struct +{ +unsigned short qtype; +unsigned short qclass; +} QUESTION; + + +typedef struct +{ +unsigned short type; +unsigned short _class; +unsigned int ttl; +unsigned short data_len; +} R_DATA; + + +typedef struct +{ + char name[256]; +R_DATA *resource; + char rdata[256]; +} RES_RECORD; + +typedef struct +{ + char name[256]; +QUESTION *ques; +} QUERY; + + +#define TCPIP_CMD_STARTUP 1 // Initializes the network module +#define TCPIP_CMD_GET_DATAGRAM 2 // Called by GS to get a datagram from the network + // XXXXYYYY = pointer to buffer to receive datagram +#define TCPIP_CMD_SEND_DATAGRAM 3 // Called by GS to send a datagram + // XXXXYYYY = pointer to parameters: + // LONG pointer to data + // WORD datagram length in bytes +#define TCPIP_CMD_CONNECT 4 // Connects to the network +#define TCPIP_CMD_DISCONNECT 5 // Disconnects from the network +#define TCPIP_CMD_SHUTDOWN 6 // Shuts down the network support +#define TCPIP_SET_IP_ADDRESS 7 // Pass in XXXXYYYY a pointerto the + // six byte MAC address of the LL +#define TCPIP_GETIPADDRESS 9 // returns the Macs IP Address in X and Y + // if IP Address could not be obtained will return 0 + +u16 ip_sum_calc(u16 len_ip_header,const byte* _buf); +u16 udp_sum_calc(u16 proto,u16 len_udp, const byte* src_addr,const byte* dest_addr, const byte* buff); + +int dns_readname(const byte* reader,const byte* buffer,char outname[] ); + +extern IP_STRUCT client_ip_addr; +extern MAC_STRUCT client_mac_addr; +extern MAC_STRUCT gateway_mac_addr; +extern IP_STRUCT gateway_dns_addr; +extern const MAC_STRUCT broadcast_mac_addr; +extern IP_STRUCT local_ip_addr; +extern IP_STRUCT host_ip_addr; + +struct tcp_queue; + +enum PConnectionState +{ + PCS_INITIALIZED=300, + PCS_SYNSENT, + PCS_SYNCHING, + PCS_BEINGESTABLISHED, + PCS_ESTABLISHED, + PCS_CLOSING, + PCS_CLEARINGQUEUE, + PCS_LASTACK, + PCS_CLOSED +}; + +enum PConnectionType +{ + PCT_SERVER, + PCT_CLIENT, + PCT_HOST +}; + +struct PConnection +{ + int type; // UDP, TCP, //ARP + int dest_port; + int source_port; + IP_STRUCT dest_ip; + MAC_STRUCT dest_mac; + int window; + int already_sent; + int send_seq; + int last_ack; + int state_seq; + int tcpsocket; + + enum PConnectionState state; + enum PConnectionType socktype; + PConnection(); + ~PConnection(); + void Reset(); + + tcp_queue* sendtcppacket(int _flags, int len, byte* data); + int sendudppacket(int len,const byte* data); + +}; + +struct ARP_HEADER +{ + u16 hwaddr_format; // Ethernet, Token Ring, etc + u16 protoaddr_format; // Same as Ether Type field + byte hwaddr_length; // Lenght of hardware address + byte protoaddr_length; // Length of protocol address + u16 opcode; // Request or Response + MAC_STRUCT src_hwaddr; + IP_STRUCT src_protoaddr; + MAC_STRUCT dst_hwaddr; + IP_STRUCT dst_protoaddr; +}; + + +#define MAX_TCP_CONNECTION 100 +extern PConnection PConnections[MAX_TCP_CONNECTION]; +PConnection* init_connection( enum PConnectionType _socktype,int _type,int _srcport,IP_STRUCT _destip, int _destport, MAC_STRUCT _destmac, int _window); +void reset_connection( enum PConnectionType _socktype,int _type, int _srcport,IP_STRUCT _destip, int _destport); +PConnection* find_connection( enum PConnectionType _socktype,int _type, int _srcport,IP_STRUCT _destip, int _destport); + + +enum QUEUE_STATE +{ + QS_TOSEND=1000, + QS_TOSENDANDRETRY, + QS_SENT, + QS_WAITACK, + QS_IDLE, + QS_FRAGMENT +}; + +struct eth_queue +{ + // ne rien avoir ici! + struct + { + ETH_HEADER eth; + union + { + ARP_HEADER arp; + IP_HEADER ip; + byte padding[MTU]; + + }; + }; + + int queuelen; + + void print(); +}; + +#define ETH_MAX_SIZE ((MTU - sizeof(ETH_HEADER) - sizeof(IP_HEADER))&~7) + +struct tcp_queue +{ + int queuelen; + int queueseq; + double timeout; + int tcplen; // taille des donne tcp + int iplen; // taille du packet ip dfragment + enum QUEUE_STATE state; + PConnection* connection; + struct + { + ETH_HEADER eth; + IP_HEADER ip; + union + { + UDP_HEADER udp; + TCP_HEADER tcp; + byte padding[16384]; + }; + }; + void print(); + void Reset() { state=QS_IDLE; }; + int isDNS() + { + return (GET_INT_FROM_IP(gateway_dns_addr)== GET_INT_FROM_IP(this->ip.ucDestination)) + || (GET_INT_FROM_IP(gateway_dns_addr)== GET_INT_FROM_IP(this->ip.ucSource)) ; + }; + + int isDHCP() + { + if ( + ip.protocol == 17 // UDP + && ntohs(udp.udp_dst) == 67 + && !memcmp(eth.dest_mac.addr, broadcast_mac_addr.addr,6) + ) + return 1; + else + return 0; + }; + int check_tcp(); +}; + +eth_queue* findETHQueue(); +extern eth_queue ethqueues[MAX_ETH_QUEUE]; +tcp_queue* findTCPQueue(); +tcp_queue* findTCPQueueByFragment(eth_queue* q); +extern tcp_queue tcpqueues[MAX_TCP_QUEUE]; + + + +void print_ip(const IP_STRUCT p); +void print_mac(const MAC_STRUCT mac); +void print_dns(const byte* _ptr); +void print_udp(const UDP_HEADER *p); +void print_arp(const ARP_HEADER * p); +void print_tcp(TCP_HEADER* p); +void print_dhcp(const byte *); +void print_ip_packet( const IP_HEADER* _header); + +int init_server(void); +void server_loop(void); + + +int add_fragment(eth_queue* p); +int process_unfragmented(tcp_queue* p); +void reset_fragments(); + +#pragma pack(pop) +#endif diff --git a/kegs/Src/marinetti_helper.cpp b/kegs/Src/marinetti_helper.cpp new file mode 100644 index 0000000..eff13c2 --- /dev/null +++ b/kegs/Src/marinetti_helper.cpp @@ -0,0 +1,740 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "sim65816.h" +#include "marinetti.h" + +#ifndef NO_MARINETTI_SUPPORT + +const MAC_STRUCT broadcast_mac_addr={ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }; + + +void print_ip(IP_STRUCT _p) +{ +#ifdef _DEBUG + const byte*p = (const byte*)&_p; + printf("%3d.%3d.%3d.%3d",p[0],p[1],p[2],p[3]); +#endif +} + +void print_mac(MAC_STRUCT _p) +{ +#ifdef _DEBUG + const byte*mac = (const byte*)&_p; + printf("%0X.%0X.%0X.%0X.%0X.%0X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); +#endif +} + +int dns_readname(const byte* _reader,const byte* _buffer,char _outname[] ) +{ + unsigned char *name = (unsigned char*)_outname; + const unsigned char *reader = (const unsigned char*)_reader; + const unsigned char *buffer = (const unsigned char*)_buffer; + + unsigned int p=0,jumped=0,offset; + int i , j; + + int count = 1; + + name[0]='\0'; + + //read the names in 3www6google3com format + while(*reader!=0) + { + if(*reader>=192) + { + offset = (*reader)*256 + *(reader+1) - 49152; //49152 = 11000000 00000000 ;) + reader = buffer + offset - 1; + jumped = 1; //we have jumped to another location so counting wont go up! + } + else + { + name[p++]=*reader; + } + + reader=reader+1; + + if(jumped==0) count = count + 1; //if we havent jumped to another location then we can count up + } + + name[p]='\0'; //string complete + if(jumped==1) + { + count = count + 1; //number of steps we actually moved forward in the packet + } + + //now convert 3www6google3com0 to www.google.com + for(i=0;i<(int)strlen((const char*)name);i++) + { + p=name[i]; + for(j=0;j<(int)p;j++) + { + name[i]=name[i+1]; + i=i+1; + } + name[i]='.'; + } + + name[i-1]='\0'; //remove the last dot + return count; +} + + +u16 ip_sum_calc(u16 len_ip_header,const byte* _buf) +{ +u16 word16; +u32 sum=0; +u16 i; + + const byte* buff = _buf; + for (i=0;i>16) + sum = (sum & 0xFFFF)+(sum >> 16); + + sum = ~sum; + return ((u16) sum); +} + +u16 udp_sum_calc(u16 _proto,u16 len_udp, const byte* src_addr,const byte* dest_addr, const byte* buff) +{ +u16 word16; +u32 sum=0; + + int i; + for (i=0;i>16) + sum = (sum & 0xFFFF)+(sum >> 16); + + for (i=0;i<4;i=i+2) + { + word16 =((src_addr[i]<<8)&0xFF00)+(src_addr[i+1]&0xFF); + sum=sum+ (u32)word16; + word16 =((dest_addr[i]<<8)&0xFF00)+(dest_addr[i+1]&0xFF); + sum=sum+(u32)word16; + } + + sum = sum + _proto + len_udp; + while (sum>>16) + sum = (sum & 0xFFFF)+(sum >> 16); + sum = ~sum; + + + + return ((u16) sum); +} + + +void print_dns(const byte* _ptr) +{ + DNS_HEADER* dns = (DNS_HEADER*)_ptr; + + char namestr [256]; + const byte* name = (const byte*)(_ptr+sizeof(DNS_HEADER)); + dns_readname(name,_ptr, namestr); + +#ifdef _DEBUG + QUESTION* q = (QUESTION*)(_ptr+strlen((const char*)name)+1+sizeof(DNS_HEADER)); + + printf("nb_question:%d nb_answer;%d\n", ntohs(dns->q_count), ntohs(dns->ans_count)); + printf("dns query : %s\n",namestr); + printf("question type:%d class: %d\n", ntohs(q->qtype), ntohs(q->qclass)); +#endif + RES_RECORD answers[20];//s,auth[20],addit[20]; //the replies from the DNS server + + //reading answers + int stop=0; + int i; + byte* reader = (byte*)(_ptr+strlen((const char*)name)+1+sizeof(DNS_HEADER)+sizeof(QUESTION)); + byte* buf = (byte*)_ptr; + + for(i=0;ians_count);i++) + { + stop = dns_readname(reader,buf,answers[i].name); + reader+=stop; + answers[i].resource=(R_DATA*)(reader); + reader+=sizeof(R_DATA); + if(ntohs(answers[i].resource->type)==1) + { + for(int j=0;jdata_len);j++) + answers[i].rdata[j]=reader[j]; + answers[i].rdata[ntohs(answers[i].resource->data_len)]=0; + reader+=ntohs(answers[i].resource->data_len); + } + else + { + stop = dns_readname(reader,buf,answers[i].rdata); + reader+=stop; + } + } + + for(i=0;ians_count);i++) + { + printf(" ### [DNS] Reply -- Name : %s ",answers[i].name); + + if(ntohs(answers[i].resource->type)==1) //IPv4 address + { + long *p; + p=(long*)answers[i].rdata; + sockaddr_in a; + a.sin_addr.s_addr=(*p); //working without ntohl + printf("has IPv4 address : %s",inet_ntoa(a.sin_addr)); + } + if(ntohs(answers[i].resource->type)==5) //Canonical name for an alias + { + printf("has alias name : %s",answers[i].rdata); + } + + printf("\n"); + } + + if (i==0) + printf(" ### [DNS] Query -- %s",namestr); + +} + +void print_udp(const UDP_HEADER *p) +{ + printf(" ### [UDP] "); + printf("len:%d, src: %d, dest %d ",ntohs(p->udp_len),ntohs(p->udp_src),ntohs(p->udp_dst)); +} + + +void print_arp(const ARP_HEADER * p) +{ +#ifdef DEBUG_ARP + int arp_type = ntohs(p->opcode); + printf("[ARP] -- type %d, ",arp_type); + printf(", src:"); + print_ip(p->src_protoaddr); + printf("/"); + print_mac(p->src_hwaddr); + printf(", dest:"); + print_ip(p->dst_protoaddr); + printf("/"); + print_mac(p->dst_hwaddr); +#endif +} + +void print_tcp(TCP_HEADER* p) +{ + +#ifdef _DEBUG + printf(" ### [TCP]"); + printf(" src_port:%d dst_port:%d",ntohs(p->src_port),ntohs(p->dest_port)); + printf(" s:%x",ntohl(p->seq_number)); + + if (p->flags & TCP_SYN) + printf(" SYN"); + if (p->flags & TCP_ACK) + { + printf(" ACK"); + printf("%x ",ntohl(p->ack_number)); + } + if (p->flags & TCP_RST) + printf(" RST"); + if (p->flags & TCP_FIN) + printf(" FIN"); + if (p->flags & TCP_PSH) + printf(" PSH"); + if (p->flags & TCP_URG) + printf(" URG"); +#endif +} + + +int tcp_queue::check_tcp() +{ + TCP_HEADER* p = &this->tcp; + + int len = this->iplen; + + u16 chk = udp_sum_calc(6,len,(const byte*)&GET_INT_FROM_IP(this->ip.ucDestination),(const byte*)&GET_INT_FROM_IP(this->ip.ucSource),(const byte*)p); + if (chk!=0 && p->checksum) + { + printf("tcp checksum errror!"); + return 0; + } + + return 1; +} + + +void print_ip_packet(const IP_HEADER* p) +{ +#ifdef DEBUG_IP + int l =ntohs(p->length); + printf("[IP] -- len:%3d", l); + printf(" src_ip:"); + print_ip(p->ucSource); + printf(" dest_ip:"); + print_ip(p->ucDestination); + + short unsigned int flag_offset = ntohs(p->flag_offset); + if (flag_offset & FLAG_MG) + printf(" MF"); + printf("\n"); +#endif +} + + +PConnection::PConnection() +{ + memset(this,0,sizeof(PConnection)); + tcpsocket=-1; +} + +void PConnection::Reset() +{ + // regarde si il y a encore des donnes envoyer pour cette connection + + for(int q=0;qtcpsocket>0) + return p; + } + else + for(int tcpindex=0;tcpindexsource_port = _srcport; + p->dest_port = _destport; + p->dest_ip = _destip; + p->dest_mac = _destmac; + p->window = _window; + p->already_sent = 0; + p->type = _type; + p->socktype = _socktype; + p->state=PCS_CLOSED; + + static int la = 0x300; + + p->last_ack = la; + p->send_seq = p-> last_ack; + la += 0x010000; + + printf("\nconnection created "); + print_ip(_destip); + printf("\n"); + break; + } + } + if (p==NULL) + { + printf("\n *** too many open connections ****\n"); + return NULL; + } + + + if (_socktype == PCT_CLIENT) + { + p->tcpsocket = _window; + p->window = 16384; + p->state=PCS_SYNSENT; + p->state_seq = p->send_seq; + p->sendtcppacket(TCP_SYN,0,NULL); + + return p; + + } + + if (_type==RT_TCP) // TCP + { + p->tcpsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (p->tcpsocket < 0) + { + printf("cannot create socket\n"); + return NULL; + } + // envoie la commande + struct sockaddr_in server; + server.sin_family = AF_INET; + if (GET_INT_FROM_IP(_destip)==GET_INT_FROM_IP(host_ip_addr)) + server.sin_addr = local_ip_addr; // host loop back + else + server.sin_addr = _destip; + server.sin_port = htons( _destport ); + memset(&(server.sin_zero),0,8); + + int err = connect(p->tcpsocket,(struct sockaddr *) &server,sizeof(server) ); + if (err < 0) + { + printf("connect send failed with err:%d\n",SockLastError()); + p->Reset(); + return NULL; + } + p->state=PCS_INITIALIZED; + + } + else + { + // udp + p->tcpsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (p->tcpsocket < 0) + { + printf("cannot open udp socket\n"); + p->Reset(); + return NULL; + } + + p->state=PCS_INITIALIZED; + } + return p; + +}; + +int PConnection::sendudppacket(int _len, const byte* _data) +{ + tcp_queue* packet = findTCPQueue(); + if (!packet) return 0; + + // UDP + int udp_len = sizeof(UDP_HEADER)+_len; + packet->udp.udp_len = htons(udp_len); + packet->udp.udp_dst = htons(source_port); // inverse + packet->udp.udp_src = htons(dest_port); + memcpy((byte*)&packet->udp+sizeof(UDP_HEADER),_data,_len); + u16 chk = udp_sum_calc(17,udp_len,(const byte*)&dest_ip,(const byte*)&client_ip_addr,(const byte*)&packet->udp); + packet->udp.udp_chk = htons(chk); + + + // IP + packet->ip.ucSource = dest_ip; + packet->ip.ucDestination = client_ip_addr; + packet->ip.protocol = 17; // udp + packet->ip.ver = 4; + packet->ip.ihl = 5; + packet->ip.ttl = 64; + + + int iplen = sizeof(IP_HEADER) + udp_len ; + packet->ip.length = htons(iplen); + u16 chkip= ip_sum_calc(sizeof(IP_HEADER),(const byte*)&packet->ip); + packet->ip.checksum = htons(chkip); + + // ETH + packet->eth.dest_mac = client_mac_addr; + packet->eth.source_mac = dest_mac; + packet->eth.type = htons(0x0800); //IP + + int eth_len = iplen+sizeof(ETH_HEADER); + packet->queuelen = eth_len ; + packet->iplen = udp_len; + packet->state = QS_TOSEND; + return eth_len; + +} + +tcp_queue* PConnection::sendtcppacket(int _flags,int _len, byte* _data) +{ + + tcp_queue* packet = findTCPQueue(); + if (!packet) return 0; + + // TCP + const int offset = 5; + int tcp_header_len = offset*4; + int tcp_len = tcp_header_len + _len; + + packet->tcp.flags = _flags ; + packet->tcp.ack_number = htonl(last_ack); + + packet->tcp.seq_number = htonl (send_seq ); + packet->tcp.window = htons(16384); + packet->tcp.data_offset = offset; + packet->tcp.dest_port = htons(source_port); // inverse + packet->tcp.src_port = htons(dest_port); + memcpy((byte*)&packet->tcp+tcp_header_len,_data,_len); + + u16 chk = udp_sum_calc(6,tcp_len,(const byte*)&dest_ip,(const byte*)&client_ip_addr,(const byte*)&packet->tcp); + packet->tcp.checksum = htons(chk); + + // IP + packet->ip.ucSource = dest_ip; + packet->ip.ucDestination = client_ip_addr; + packet->ip.protocol = 6; + packet->ip.ver = 4; + packet->ip.ihl = 5; + packet->ip.ttl = 64; + + + int iplen = sizeof(IP_HEADER) + tcp_len ; + packet->ip.length = htons(iplen); + u16 chkip= ip_sum_calc(sizeof(IP_HEADER),(const byte*)&packet->ip); + packet->ip.checksum = htons(chkip); + + // ETH + packet->eth.dest_mac = client_mac_addr; + packet->eth.source_mac = dest_mac; + packet->eth.type = htons(0x0800); + + int eth_len = iplen+sizeof(ETH_HEADER); + packet->queuelen = eth_len ; + packet->queueseq = send_seq+_len; + packet->state = QS_TOSENDANDRETRY; + packet->connection = this; + + packet->tcplen = _len; + packet->iplen = tcp_len; + send_seq+=_len; + already_sent += _len; + + if (already_sent > window) + { + printf("****window error****\n"); + } + return packet; // nb d'octect envoys +} + +PConnection* find_connection(enum PConnectionType _socktype,int _type,int _srcport,IP_STRUCT _destip, int _destport) +{ + for(int i=0;itype == _type) + && + (p->source_port == _srcport) + && + (p->dest_port == _destport) + && + (GET_INT_FROM_IP(p->dest_ip) == GET_INT_FROM_IP(_destip)) + && + (p->state != PCS_CLOSED) + ) + return p; + } + return NULL ; + +} + +void reset_connection(enum PConnectionType _socktype, int _type,int _srcport,IP_STRUCT _destip, int _destport) +{ + PConnection* p = find_connection(_socktype,_type,_srcport,_destip,_destport); + if (p) + p->Reset(); + else + printf("ignoring reset on unknown connection\n"); +} + +void eth_queue::print() +{ + +#ifdef DEBUG_ETH + if (this->eth.type==htons(0x0806)) + print_arp(&this->arp); + else + { + print_ip_packet(&this->ip); + int frag_offset = ntohs(this->ip.flag_offset); + if (frag_offset & FLAG_MF) + printf(" F"); + + printf("id:%x offset:%d ",this->ip.identification,GET_OFFSET(frag_offset)); + switch(this->ip.protocol) + { + case 17: // udp + printf("/UDP"); + break; + case 6: // tcp + printf("/TCP"); + break; + default: + break; + } + } + printf("\n"); +#endif +} + + +void tcp_queue::print() +{ + + if (this->ip.protocol == 17 ) // UDP + { + print_udp(&this->udp); + if (isDNS()) + print_dns((const byte*)&this->udp+sizeof(UDP_HEADER)); + } + else + if (this->ip.protocol == 6 ) // TCP + { + + + print_tcp(&this->tcp); + + int offset =this->tcp.data_offset*4; + int l = ntohs(this->ip.length); + int tcplen = l - sizeof(IP_HEADER) - offset; + if (tcplen) + printf(" [tcplen:%d]",tcplen); + } + else + printf("unknown protocol : %d",this->ip.protocol); + printf("\n"); +} + + + +// SERVER + +int server_sock; + +int init_server(void) +{ + // nb_client = 0; + + server_sock = socket(AF_INET, SOCK_STREAM, 0); + + if(server_sock == SOCKET_ERROR) + { + printf("server init failed\n"); + return 0; + } + + struct sockaddr_in sin; + + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = htons(8080); + sin.sin_family = AF_INET; + + if(bind(server_sock,(struct sockaddr *)&sin, sizeof sin) == SOCKET_ERROR) + { + printf("cannot bind\n"); + return 0; + } + + if(listen(server_sock, 0) == SOCKET_ERROR) + { + printf("cannot listent\n"); + return 0; + } + + + + return 1; +} + +void server_loop(void) +{ + for(int i=0;istate != PCS_CLOSED) // *** ON ATTEND LA FIN DE LA CONNECTION => BCP PLUS RAPIDE?? + { + // server not ready to accept new connection + return ; + } + } + + int max = server_sock; + + fd_set rdfs; + + + FD_ZERO(&rdfs); + + // add the connection socket + FD_SET(server_sock, &rdfs); + + timeval timeout; + timeout.tv_usec = 1; + timeout.tv_sec = 0; + + if(select(max + 1, &rdfs, NULL, NULL, &timeout) == -1) + { + // printf("failed select\n"); + return ; + } + + if(FD_ISSET(server_sock, &rdfs)) + { + // new client + struct sockaddr csin = { 0 }; + socklen_t sinsize = sizeof(struct sockaddr); + int csock = accept(server_sock, &csin, &sinsize); + if(csock == SOCKET_ERROR) + { + printf("failed accept\n");; + return; + } + + + max = csock > max ? csock : max; + + FD_SET(csock, &rdfs); + IP_STRUCT *ip_client = (IP_STRUCT*)&csin.sa_data[0]; + MAC_STRUCT mac_client; + mac_client.SetFromIP(*ip_client); + + + for(int i=0;istate == PCS_SYNSENT) + { + printf("\n*** INGORING %d from ",csock); + print_ip(*ip_client); + printf("\n"); + return ; + } + } + + printf("\n*** connection %d from ",csock); + print_ip(*ip_client); + printf("\n"); + + // gnre un port random pour ne pallier le IPOPENUSER qui ne s base que sur les ports! + static int free_port=100; + init_connection(PCT_CLIENT,RT_TCP, 80, *ip_client, free_port++, mac_client,csock); + + } + +} + +#endif \ No newline at end of file diff --git a/kegs/Src/moremem.cpp b/kegs/Src/moremem.cpp new file mode 100644 index 0000000..1001e83 --- /dev/null +++ b/kegs/Src/moremem.cpp @@ -0,0 +1,2549 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "moremem.h" +#include "sim65816.h" +#include "iwm.h" +#include "video.h" +#include "protos_engine_c.h" +#include "graphcounter.h" + +s_moremem g_moremem; + + +extern const char* g_kegs_version_str; + +int x_fixed_framerate() +{ + static double lastfps = 0.0f; + +#ifdef ENABLE_GRAPH + g_graph.add_graph(2,(float)( 1.0/(get_dtime() - lastfps)),g_sim65816.g_vbl_count); +#endif + lastfps = get_dtime(); + addFrameRate(2); + return 0; +} + + +void s_sim65816::set_fixed_vblank(int _nbframe, speedenum _defaultspeed) +{ + + g_fixed_vblank = _nbframe; + if (g_fixed_vblank==0) + g_sim65816.set_limit_speed(_defaultspeed); + else + { + printf("gs speed with fixed vblank of %d\n",_nbframe); + g_sim65816.set_limit_speed(SPEED_GS); + } +} + + + +extern byte *g_memory_ptr; +extern byte *g_dummy_memory1_ptr; + +extern byte *g_rom_fc_ff_ptr; +extern byte *g_rom_cards_ptr; + +//extern word32 slow_mem_changed[]; + +//extern int g_num_breakpoints; +//extern word32 g_breakpts[]; + +//extern Page_info page_info_rd_wr[]; + +extern int g_user_page2_shadow; + + + +#define UNIMPL_READ \ + halt_printf("UNIMP READ to addr %08x\n", loc); \ + return 0; + +#define UNIMPL_WRITE \ + halt_printf("UNIMP WRITE to addr %08x, val: %04x\n", loc, val); \ + return; + +// OG Added Transwarp ROM +#define TRANSWARP +#ifdef _WIN32 +__declspec(align(256)) +#endif +unsigned char transwarpcode[][32] +#ifndef _WIN32 +__attribute__ ((aligned(256))) +#endif +={ +{ +/*0xBCFF00*/ 'T','W','G','S',0,0,0,0,0,0,0,0,0,0,0,0, +/*0xBCFF10*/ 0x5C,0x40,0xFF,0xBC, // JMP GetMaxSpeed +/*0xBCFF14*/ 0x5C,0x60,0xFF,0xBC, // JMP GetNumISpeed +/*0xBCFF18*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF1C*/ 0x6B,0x00,0x00,0x00 // ??? +}, +{ +/*0xBCFF20*/ 0x5C,0x80,0xFF,0xBC, // JMP GetCurSpeed +/*0xBCFF24*/ 0x5C,0xA0,0xFF,0xBC, // JMP SetCurSpeed +/*0xBCFF28*/ 0x5C,0xC0,0xFF,0xBC, // JMP GetCurISpeed +/*0xBCFF2C*/ 0x5C,0xE0,0xFF,0xBC, // JMP SetCurISpeed +/*0xBCFF30*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF34*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF38*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF3C*/ 0x6B,0x00,0x00,0x00 // GetTWConfig +}, +{ +/* 0xBCFF40*/ // GetMaxSpeed +#define ZIP_SPEED 8000 + +0xA9, ZIP_SPEED & 0xFF, (ZIP_SPEED >> 8) &0xFF, // LDA 0x1F40 // Max Speed = 8.0Mhz +0x6B, // RTL +0x00,0x00,0x00,0x00, //4 +0x00,0x00,0x00,0x00, //8 +0x6B,0x00,0x00,0x00, //C Space Shark calls this address ??? +}, +{ +/* 0xBCFF60*/ //GetNumISpeed +0xA9,0x02,0x00, // LDA 0x0002 // 0=slow, 1=normal, 2=warp +0x6B, // RTL +}, +{ +/* 0xBCFF80*/ //GetCurSpeed +0xAF, 0x6A, 0xC0, 0x00, // LDA 0xC06A (/6B) +0x6B, // RTL +}, +{ +/* 0xBCFFA0*/ //SetCurSpeed +0x8F, 0x6A, 0xC0, 0x00, // STA 0xC06A (/6B) +0x6B, // RTL +}, +{ +/* 0xBCFFC0*/ //GetCurISpeed +0x48, // PHA +0xAF, 0x6C, 0xC0, 0x00, // LDA 0xC06C (/6D) +0xAA, // TAX +0x68, // PLA +0x6B, // RTL +}, +{ +/* 0xBCFFE0*/ //SetCurISpeed +0x48, // PHA +0x8A, // TXA +0x8F, 0x6C, 0xC0, 0x00, // STA 0xC06C (/6D) +0x68, // PLA +0x6B, // RTL +}, +{ + /* 0xBCFFF0*/ //iPhone +0x20, 0x58, 0xFC, +0x4C, 0x59, 0xFF, + +} +} +; + +// OG Added moremem_init() +void moremem_init() +{ + g_moremem.g_em_emubyte_cnt = 0; + g_moremem.g_paddle_buttons = 0; + g_moremem.g_irq_pending = 0; + + g_moremem.g_c023_val = 0; + g_moremem.g_c029_val_some = 0x41; + g_moremem.g_c02b_val = 0x08; + g_moremem.g_c02d_int_crom = 0; + g_moremem.g_c031_disk35 = 0; + g_moremem.g_c034_val = 0; + g_moremem.g_c035_shadow_reg = 0x08; + g_moremem.g_c036_val_speed = 0x80; + g_moremem.g_c03ef_doc_ptr = 0; + g_moremem.g_c041_val = 0; /* C041_EN_25SEC_INTS, C041_EN_MOVE_INTS */ + g_moremem.g_c046_val = 0; + g_moremem.g_c05x_annuncs = 0; + g_moremem.g_c068_statereg = 0; + g_moremem.g_c08x_wrdefram = 0; + g_moremem.g_zipgs_unlock = 0; + g_moremem.g_zipgs_reg_c059 = 0x5f; +// g_moremem.g_zipgs_reg_c05a = 0x0f; // ne pas rinitializer la vitesse par default de la zipcard + g_moremem.g_zipgs_reg_c05b = 0x40; + g_moremem.g_zipgs_reg_c05c = 0x00; +} + +void +fixup_brks() +{ + word32 page; + word32 tmp, tmp2; + Pg_info val; + int is_wr_only; + int i, num; + + num = g_num_breakpoints; + for(i = 0; i < num; i++) { + page = (g_breakpts[i].addr >> 8) & 0xffff; + is_wr_only = (g_breakpts[i].addr >> 24) & 1; + if(!is_wr_only) { + val = GET_PAGE_INFO_RD(page); + tmp = PTR2WORD(val) & 0xff; + tmp2 = tmp | BANK_IO_TMP | BANK_BREAK; + SET_PAGE_INFO_RD(page, val - tmp + tmp2); + } + val = GET_PAGE_INFO_WR(page); + tmp = PTR2WORD(val) & 0xff; + tmp2 = tmp | BANK_IO_TMP | BANK_BREAK; + SET_PAGE_INFO_WR(page, val - tmp + tmp2); + } +} + +void +fixup_hires_on() +{ + if((g_video.g_cur_a2_stat & ALL_STAT_ST80) == 0) { + return; + } + + fixup_bank0_2000_4000(); + fixup_brks(); +} + +void +fixup_bank0_2000_4000() +{ + byte *mem0rd; + byte *mem0wr; + + mem0rd = &(g_memory_ptr[0x2000]); + mem0wr = mem0rd; + if((g_video.g_cur_a2_stat & ALL_STAT_ST80) && (g_video.g_cur_a2_stat & ALL_STAT_HIRES)){ + if(g_video.g_cur_a2_stat & ALL_STAT_PAGE2) { + mem0rd += 0x10000; + mem0wr += 0x10000; + if((g_moremem.g_c035_shadow_reg & 0x12) == 0 || + (g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } else if((g_moremem.g_c035_shadow_reg & 0x02) == 0) { + mem0wr += BANK_SHADOW; + } + + } else { + if(RAMRD) { + mem0rd += 0x10000; + } + if(RAMWRT) { + mem0wr += 0x10000; + if((g_moremem.g_c035_shadow_reg & 0x12) == 0 || + (g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } else if((g_moremem.g_c035_shadow_reg & 0x02) == 0) { + mem0wr += BANK_SHADOW; + } + } + + fixup_any_bank_any_page(0x20, 0x20, mem0rd, mem0wr); +} + +void +fixup_bank0_0400_0800() +{ + byte *mem0rd; + byte *mem0wr; + int shadow; + + mem0rd = &(g_memory_ptr[0x400]); + mem0wr = mem0rd; + shadow = BANK_SHADOW; + if(g_video.g_cur_a2_stat & ALL_STAT_ST80) { + if(g_video.g_cur_a2_stat & ALL_STAT_PAGE2) { + shadow = BANK_SHADOW2; + mem0rd += 0x10000; + mem0wr += 0x10000; + } + } else { + if(RAMWRT) { + shadow = BANK_SHADOW2; + mem0wr += 0x10000; + } + if(RAMRD) { + mem0rd += 0x10000; + } + } + if((g_moremem.g_c035_shadow_reg & 0x01) == 0) { + mem0wr += shadow; + } + + fixup_any_bank_any_page(0x4, 4, mem0rd, mem0wr); +} + +void +fixup_any_bank_any_page(int start_page, int num_pages, byte *mem0rd, + byte *mem0wr) +{ + int i; + + for(i = 0; i < num_pages; i++) { + SET_PAGE_INFO_RD(i + start_page, mem0rd); + mem0rd += 0x100; + } + + for(i = 0; i < num_pages; i++) { + SET_PAGE_INFO_WR(i + start_page, mem0wr); + mem0wr += 0x100; + } + +} + +void +fixup_intcx() +{ + byte *rom10000; + byte *rom_inc; + int no_io_shadow; + int off; + int start_k; + word32 mask; + int j, k; + + rom10000 = &(g_rom_fc_ff_ptr[0x30000]); + + no_io_shadow = (g_moremem.g_c035_shadow_reg & 0x40); + + start_k = 0; + if(no_io_shadow) { + /* if not shadowing, banks 0 and 1 are not affected by intcx */ + start_k = 2; + } + + for(k = start_k; k < 4; k++) { + off = k; + if(k >= 2) { + off += (0xe0 - 2); + } + /* step off through 0x00, 0x01, 0xe0, 0xe1 */ + + off = off << 8; + SET_PAGE_INFO_RD(0xc0 + off, SET_BANK_IO); + + for(j = 0xc1; j < 0xc8; j++) { + mask = 1 << (j & 0xf); + if(j < 0xc8) { + rom_inc = SET_BANK_IO; + if(((g_moremem.g_c02d_int_crom & mask) == 0) || INTCX) { + rom_inc = rom10000 + (j << 8); + } else { + // User-slot rom + rom_inc = &(g_rom_cards_ptr[0]) + + ((j - 0xc0) << 8); + } + SET_PAGE_INFO_RD(j + off, rom_inc); + } + } + for(j = 0xc8; j < 0xd0; j++) { + /* c800 - cfff */ + if(((g_moremem.g_c02d_int_crom & (1 << 3)) == 0) || INTCX) { + rom_inc = rom10000 + (j << 8); + } else { + /* c800 space not necessarily mapped */ + /* just map in ROM */ + rom_inc = rom10000 + (j << 8); + } + SET_PAGE_INFO_RD(j + off, rom_inc); + } + for(j = 0xc0; j < 0xd0; j++) { + SET_PAGE_INFO_WR(j + off, SET_BANK_IO); + } + } + + if(!no_io_shadow) { + SET_PAGE_INFO_RD(0xc7, SET_BANK_IO); /* smartport */ + } + + fixup_brks(); +} + +void +fixup_wrdefram(int new_wrdefram) +{ + byte *mem0wr; + byte *wrptr; + int j; + + g_moremem.g_c08x_wrdefram = new_wrdefram; + + if(g_moremem.g_c035_shadow_reg & 0x40) { + /* do nothing */ + return; + } + + /* if shadowing, banks 0 and 1 are affected by wrdefram */ + mem0wr = &(g_memory_ptr[0]); + if(!new_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + + wrptr = mem0wr + 0x1e000; + for(j = 0x1e0; j < 0x200; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + wrptr = mem0wr + 0x0e000; + if(ALTZP) { + wrptr += 0x10000; + } + for(j = 0xe0; j < 0x100; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + wrptr = mem0wr + 0x1d000; + if(! LCBANK2) { + wrptr -= 0x1000; + } + for(j = 0x1d0; j < 0x1e0; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + wrptr = mem0wr + 0xd000; + if(! LCBANK2) { + wrptr -= 0x1000; + } + if(ALTZP) { + wrptr += 0x10000; + } + for(j = 0xd0; j < 0xe0; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + fixup_brks(); +} + +void +fixup_st80col(double dcycs) +{ + int cur_a2_stat; + + cur_a2_stat = g_video.g_cur_a2_stat; + + fixup_bank0_0400_0800(); + + if(cur_a2_stat & ALL_STAT_HIRES) { + /* fixup no matter what PAGE2 since PAGE2 and RAMRD/WR */ + /* can work against each other */ + fixup_bank0_2000_4000(); + } + + if(cur_a2_stat & ALL_STAT_PAGE2) { + change_display_mode(dcycs); + } + + fixup_brks(); +} + +void +fixup_altzp() +{ + byte *mem0rd, *mem0wr; + int rdrom, c08x_wrdefram; + int altzp; + + altzp = ALTZP; + mem0rd = &(g_memory_ptr[0]); + if(altzp) { + mem0rd += 0x10000; + } + SET_PAGE_INFO_RD(0, mem0rd); + SET_PAGE_INFO_RD(1, mem0rd + 0x100); + SET_PAGE_INFO_WR(0, mem0rd); + SET_PAGE_INFO_WR(1, mem0rd + 0x100); + + mem0rd = &(g_memory_ptr[0xd000]); + mem0wr = mem0rd; + c08x_wrdefram = g_moremem.g_c08x_wrdefram; + rdrom = RDROM; + + if(g_moremem.g_c035_shadow_reg & 0x40) { + if(ALTZP) { + mem0rd += 0x10000; + } + fixup_any_bank_any_page(0xd0, 0x10, mem0rd - 0x1000, + mem0rd - 0x1000); + c08x_wrdefram = 1; + rdrom = 0; + } else { + if(!c08x_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + if(ALTZP) { + mem0rd += 0x10000; + mem0wr += 0x10000; + } + if(! LCBANK2) { + mem0rd -= 0x1000; + mem0wr -= 0x1000; + } + if(rdrom) { + mem0rd = &(g_rom_fc_ff_ptr[0x3d000]); + } + fixup_any_bank_any_page(0xd0, 0x10, mem0rd, mem0wr); + } + + mem0rd = &(g_memory_ptr[0xe000]); + mem0wr = mem0rd; + if(!c08x_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + if(ALTZP) { + mem0rd += 0x10000; + mem0wr += 0x10000; + } + if(rdrom) { + mem0rd = &(g_rom_fc_ff_ptr[0x3e000]); + } + fixup_any_bank_any_page(0xe0, 0x20, mem0rd, mem0wr); + + /* No need for fixup_brks since called from set_statereg() */ +} + +void +fixup_page2(double dcycs) +{ + if((g_video.g_cur_a2_stat & ALL_STAT_ST80)) { + fixup_bank0_0400_0800(); + if((g_video.g_cur_a2_stat & ALL_STAT_HIRES)) { + fixup_bank0_2000_4000(); + } + } else { + change_display_mode(dcycs); + } +} + +void +fixup_ramrd() +{ + byte *mem0rd; + int cur_a2_stat; + int j; + + cur_a2_stat = g_video.g_cur_a2_stat; + + if((cur_a2_stat & ALL_STAT_ST80) == 0) { + fixup_bank0_0400_0800(); + } + if( ((cur_a2_stat & ALL_STAT_ST80) == 0) || + ((cur_a2_stat & ALL_STAT_HIRES) == 0) ) { + fixup_bank0_2000_4000(); + } + + mem0rd = &(g_memory_ptr[0x0000]); + if(RAMRD) { + mem0rd += 0x10000; + } + + SET_PAGE_INFO_RD(2, mem0rd + 0x200); + SET_PAGE_INFO_RD(3, mem0rd + 0x300); + + for(j = 8; j < 0x20; j++) { + SET_PAGE_INFO_RD(j, mem0rd + j*0x100); + } + + for(j = 0x40; j < 0xc0; j++) { + SET_PAGE_INFO_RD(j, mem0rd + j*0x100); + } + + /* No need for fixup_brks since only called from set_statereg() */ +} + +void +fixup_ramwrt() +{ + byte *mem0wr; + int cur_a2_stat; + int shadow; + int ramwrt; + int j; + + cur_a2_stat = g_video.g_cur_a2_stat; + + if((cur_a2_stat & ALL_STAT_ST80) == 0) { + fixup_bank0_0400_0800(); + } + if( ((cur_a2_stat & ALL_STAT_ST80) == 0) || + ((cur_a2_stat & ALL_STAT_HIRES) == 0) ) { + fixup_bank0_2000_4000(); + } + + mem0wr = &(g_memory_ptr[0x0000]); + ramwrt = RAMWRT; + if(ramwrt) { + mem0wr += 0x10000; + } + + SET_PAGE_INFO_WR(2, mem0wr + 0x200); + SET_PAGE_INFO_WR(3, mem0wr + 0x300); + + shadow = BANK_SHADOW; + if(ramwrt) { + shadow = BANK_SHADOW2; + } + if( ((g_moremem.g_c035_shadow_reg & 0x20) != 0) || + ((g_sim65816.g_rom_version < 3) && !g_user_page2_shadow)) { + shadow = 0; + } + for(j = 8; j < 0x0c; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); + } + + for(j = 0xc; j < 0x20; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + shadow = 0; + if(ramwrt) { + if((g_moremem.g_c035_shadow_reg & 0x14) == 0 || + (g_moremem.g_c035_shadow_reg & 0x08) == 0) { + shadow = BANK_SHADOW2; + } + } else if((g_moremem.g_c035_shadow_reg & 0x04) == 0) { + shadow = BANK_SHADOW; + } + for(j = 0x40; j < 0x60; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); + } + + shadow = 0; + if(ramwrt && (g_moremem.g_c035_shadow_reg & 0x08) == 0) { + /* shr shadowing */ + shadow = BANK_SHADOW2; + } + for(j = 0x60; j < 0xa0; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); + } + + for(j = 0xa0; j < 0xc0; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* No need for fixup_brks() since only called from set_statereg() */ +} + +void +fixup_lcbank2() +{ + byte *mem0rd, *mem0wr; + int lcbank2, c08x_wrdefram, rdrom; + int off; + int k; + + for(k = 0; k < 4; k++) { + off = k; + if(k >= 2) { + off += (0xe0 - 2); + } + /* step off through 0x00, 0x01, 0xe0, 0xe1 */ + + if(k < 2) { + mem0rd = &(g_memory_ptr[k << 16]); + } else { + mem0rd = &(g_slow_memory_ptr[(k & 1) << 16]); + } + if((k == 0) && ALTZP) { + mem0rd += 0x10000; + } + lcbank2 = LCBANK2; + c08x_wrdefram = g_moremem.g_c08x_wrdefram; + rdrom = RDROM; + if((k < 2) && (g_moremem.g_c035_shadow_reg & 0x40)) { + lcbank2 = 0; + c08x_wrdefram = 1; + rdrom = 0; + } + if(! lcbank2) { + mem0rd -= 0x1000; /* lcbank1, use 0xc000-cfff */ + } + mem0wr = mem0rd; + if((k < 2) && !c08x_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + if((k < 2) && rdrom) { + mem0rd = &(g_rom_fc_ff_ptr[0x30000]); + } + fixup_any_bank_any_page(off*0x100 + 0xd0, 0x10, + mem0rd + 0xd000, mem0wr + 0xd000); + } + + /* No need for fixup_brks() since only called from set_statereg(), */ + /* or from other routines which will handle it */ +} + +void +fixup_rdrom() +{ + byte *mem0rd; + int j, k; + + /* fixup_lcbank2 handles 0xd000-dfff for rd & wr*/ + fixup_lcbank2(); + + for(k = 0; k < 2; k++) { + /* k is the bank */ + mem0rd = &(g_memory_ptr[k << 16]); + if((k == 0) && ALTZP) { + mem0rd += 0x10000; + } + if((g_moremem.g_c035_shadow_reg & 0x40) == 0) { + if(RDROM) { + mem0rd = &(g_rom_fc_ff_ptr[0x30000]); + } + } + for(j = 0xe0; j < 0x100; j++) { + SET_PAGE_INFO_RD(j + k*0x100, mem0rd + j*0x100); + } + } + + /* No need for fixup_brks() since only called from set_statereg() */ +} + +void +set_statereg(double dcycs, int val) +{ + int _xor; // OG renamed xor to _xor + + _xor = val ^ g_moremem.g_c068_statereg; + g_moremem.g_c068_statereg = val; + if(_xor == 0) { + return; + } + + if(_xor & 0x80) { + /* altzp */ + fixup_altzp(); + } + if(_xor & 0x40) { + /* page2 */ + g_video.g_cur_a2_stat = (g_video.g_cur_a2_stat & ~ALL_STAT_PAGE2) | + (val & ALL_STAT_PAGE2); + fixup_page2(dcycs); + } + + if(_xor & 0x20) { + /* RAMRD */ + fixup_ramrd(); + } + + if(_xor & 0x10) { + /* RAMWRT */ + fixup_ramwrt(); + } + + if(_xor & 0x08) { + /* RDROM */ + fixup_rdrom(); + } + + if(_xor & 0x04) { + /* LCBANK2 */ + fixup_lcbank2(); + } + + if(_xor & 0x02) { + /* ROMBANK */ + halt_printf("Just set rombank = %d\n", ROMB); + } + + if(_xor & 0x01) { + fixup_intcx(); + } + + if(_xor) { + fixup_brks(); + } +} + +void +fixup_shadow_txt1() +{ + byte *mem0wr; + int j; + + fixup_bank0_0400_0800(); + + mem0wr = &(g_memory_ptr[0x10000]); + if((g_moremem.g_c035_shadow_reg & 0x01) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 4; j < 8; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_txt2() +{ + byte *mem0wr; + int shadow; + int j; + + /* bank 0 */ + mem0wr = &(g_memory_ptr[0x00000]); + shadow = BANK_SHADOW; + if(RAMWRT) { + mem0wr += 0x10000; + shadow = BANK_SHADOW2; + } + if(((g_moremem.g_c035_shadow_reg & 0x20) == 0) && + ((g_sim65816.g_rom_version >= 3) || g_user_page2_shadow)) { + mem0wr += shadow; + } + for(j = 8; j < 0xc; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* and bank 1 */ + mem0wr = &(g_memory_ptr[0x10000]); + if(((g_moremem.g_c035_shadow_reg & 0x20) == 0) && + ((g_sim65816.g_rom_version >= 3) || g_user_page2_shadow)) { + mem0wr += BANK_SHADOW2; + } + for(j = 8; j < 0xc; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_hires1() +{ + byte *mem0wr; + int j; + + fixup_bank0_2000_4000(); + + /* and bank 1 */ + mem0wr = &(g_memory_ptr[0x10000]); + if((g_moremem.g_c035_shadow_reg & 0x12) == 0 || (g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 0x20; j < 0x40; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_hires2() +{ + byte *mem0wr; + int j; + + /* bank 0 */ + mem0wr = &(g_memory_ptr[0x00000]); + if(RAMWRT) { + mem0wr += 0x10000; + if((g_moremem.g_c035_shadow_reg & 0x14) == 0 || + (g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } else if((g_moremem.g_c035_shadow_reg & 0x04) == 0) { + mem0wr += BANK_SHADOW; + } + for(j = 0x40; j < 0x60; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* and bank 1 */ + mem0wr = &(g_memory_ptr[0x10000]); + if((g_moremem.g_c035_shadow_reg & 0x14) == 0 || (g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 0x40; j < 0x60; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_shr() +{ + byte *mem0wr; + int j; + + /* bank 0, only pages 0x60 - 0xa0 */ + mem0wr = &(g_memory_ptr[0x00000]); + if(RAMWRT) { + mem0wr += 0x10000; + if((g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } + for(j = 0x60; j < 0xa0; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* and bank 1, only pages 0x60 - 0xa0 */ + mem0wr = &(g_memory_ptr[0x10000]); + if((g_moremem.g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 0x60; j < 0xa0; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_iolc() +{ + byte *mem0rd; + int k; + + if(g_moremem.g_c035_shadow_reg & 0x40) { + /* Disable language card area */ + for(k = 0; k < 2; k++) { + mem0rd = &(g_memory_ptr[k << 16]); + fixup_any_bank_any_page((k << 8) + 0xc0, 0x10, + mem0rd + 0xd000, mem0rd + 0xd000); + if(k == 0 && ALTZP) { + mem0rd += 0x10000; + } + fixup_any_bank_any_page((k << 8) + 0xd0, 0x10, + mem0rd + 0xc000, mem0rd + 0xc000); + fixup_any_bank_any_page((k << 8) + 0xe0, 0x20, + mem0rd + 0xe000, mem0rd + 0xe000); + } + } else { + /* 0xc000 area */ + fixup_intcx(); + + /* 0xd000 area */ + /* fixup_lcbank2(); -- not needed since fixup_rdrom does it */ + + /* Fix 0xd000-0xffff for reads, banks 0 and 1 */ + fixup_rdrom(); /* which calls fixup_lcbank2 */ + + /* Fix 0xd000-0xffff for writes, banks 0 and 1 */ + fixup_wrdefram(g_moremem.g_c08x_wrdefram); + } +} + +void +update_shadow_reg(int val) +{ + int _xor; + + if(g_moremem.g_c035_shadow_reg == val) { + return; + } + + _xor = g_moremem.g_c035_shadow_reg ^ val; + g_moremem.g_c035_shadow_reg = val; + + if(_xor & 8) { + fixup_shadow_hires1(); + fixup_shadow_hires2(); + fixup_shadow_shr(); + _xor = _xor & (~0x16); + } + if(_xor & 0x10) { + fixup_shadow_hires1(); + fixup_shadow_hires2(); + _xor = _xor & (~0x6); + } + if(_xor & 2) { + fixup_shadow_hires1(); + } + if(_xor & 4) { + fixup_shadow_hires2(); + } + if(_xor & 1) { + fixup_shadow_txt1(); + } + if((_xor & 0x20) && ((g_sim65816.g_rom_version >= 3) || g_user_page2_shadow)) { + fixup_shadow_txt2(); + } + if(_xor & 0x40) { + fixup_shadow_iolc(); + } + if(_xor) { + fixup_brks(); + } +} + +void +fixup_shadow_all_banks() +{ + byte *mem0rd; + int shadow; + int num_banks; + int j, k; + + /* Assume Ninja Force Megademo */ + /* only do banks 3 - num_banks by 2, shadowing into e1 */ + + shadow = 0; + if((g_moremem.g_c036_val_speed & 0x10) && ((g_moremem.g_c035_shadow_reg & 0x08) == 0)) { + shadow = BANK_SHADOW2; + } + num_banks = g_sim65816.g_mem_size_total >> 16; + for(k = 3; k < num_banks; k += 2) { + mem0rd = &(g_memory_ptr[k*0x10000 + 0x2000]) + shadow; + for(j = 0x20; j < 0xa0; j++) { + SET_PAGE_INFO_WR(k*0x100 + j, mem0rd); + mem0rd += 0x100; + } + } + + fixup_brks(); +} + +void +setup_pageinfo() +{ + byte *mem0rd; + word32 mem_size_pages; + + /* first, set all of memory to point to itself */ + + mem_size_pages = g_sim65816.g_mem_size_total >> 8; + mem0rd = &(g_memory_ptr[0]); + fixup_any_bank_any_page(0, mem_size_pages, mem0rd, mem0rd); + + /* mark unused memory as BAD_MEM */ + fixup_any_bank_any_page(mem_size_pages, 0xfc00-mem_size_pages, + BANK_BAD_MEM, BANK_BAD_MEM); + + fixup_shadow_all_banks(); + + /* ROM */ + mem0rd = &(g_rom_fc_ff_ptr[0]); + fixup_any_bank_any_page(0xfc00, 0x400, mem0rd, + mem0rd + (BANK_IO_TMP | BANK_IO2_TMP)); + + /* banks e0, e1 */ + mem0rd = &(g_slow_memory_ptr[0]); + fixup_any_bank_any_page(0xe000, 0x04, mem0rd + 0x0000, mem0rd + 0x0000); + fixup_any_bank_any_page(0xe004, 0x08, mem0rd + 0x0400, + mem0rd + 0x0400 + BANK_SHADOW); + fixup_any_bank_any_page(0xe00c, 0x14, mem0rd + 0x0c00, mem0rd + 0x0c00); + fixup_any_bank_any_page(0xe020, 0x40, mem0rd + 0x2000, + mem0rd + 0x2000 + BANK_SHADOW); + fixup_any_bank_any_page(0xe060, 0xa0, mem0rd + 0x6000, mem0rd + 0x6000); + + mem0rd = &(g_slow_memory_ptr[0x10000]); + fixup_any_bank_any_page(0xe100, 0x04, mem0rd + 0x0000, mem0rd + 0x0000); + fixup_any_bank_any_page(0xe104, 0x08, mem0rd + 0x0400, + mem0rd + 0x0400 + BANK_SHADOW2); + fixup_any_bank_any_page(0xe10c, 0x14, mem0rd + 0x0c00, mem0rd + 0x0c00); + fixup_any_bank_any_page(0xe120, 0x80, mem0rd + 0x2000, + mem0rd + 0x2000 + BANK_SHADOW2); + fixup_any_bank_any_page(0xe1a0, 0x60, mem0rd + 0xa000, mem0rd + 0xa000); + + fixup_intcx(); /* correct banks 0xe0,0xe1, 0xc000-0xcfff area */ + fixup_lcbank2(); /* correct 0xd000-0xdfff area */ + + fixup_bank0_2000_4000(); + fixup_bank0_0400_0800(); + fixup_wrdefram(g_moremem.g_c08x_wrdefram); + fixup_altzp(); + fixup_ramrd(); + fixup_ramwrt(); + fixup_rdrom(); + fixup_shadow_txt1(); + fixup_shadow_txt2(); + fixup_shadow_hires1(); + fixup_shadow_hires2(); + fixup_shadow_shr(); + fixup_shadow_iolc(); + fixup_brks(); + +#ifdef TRANSWARP // OG adding Transwarp code + SET_PAGE_INFO_RD(0xBCFF,transwarpcode); +#endif +} + +void +show_bankptrs_bank0rdwr() +{ + show_bankptrs(0); + show_bankptrs(1); + show_bankptrs(0xe0); + show_bankptrs(0xe1); + printf("statereg: %02x\n", g_moremem.g_c068_statereg); +} + +void +show_bankptrs(int bnk) +{ + int i; + Pg_info rd, wr; + byte *ptr_rd, *ptr_wr; + + printf("g_memory_ptr: %p, dummy_mem: %p, slow_mem_ptr: %p\n", + g_memory_ptr, g_dummy_memory1_ptr, g_slow_memory_ptr); + printf("g_rom_fc_ff_ptr: %p\n", g_rom_fc_ff_ptr); + + printf("Showing bank_info array for %02x\n", bnk); + for(i = 0; i < 256; i++) { + rd = GET_PAGE_INFO_RD(bnk*0x100 + i); + wr = GET_PAGE_INFO_WR(bnk*0x100 + i); + ptr_rd = (byte *)rd; + ptr_wr = (byte *)wr; + printf("%04x rd: ", bnk*256 + i); + show_addr(ptr_rd); + printf(" wr: "); + show_addr(ptr_wr); + printf("\n"); + } +} + +void +show_addr(byte *ptr) +{ + word32 mem_size; + + mem_size = g_sim65816.g_mem_size_total; + if(ptr >= g_memory_ptr && ptr < &g_memory_ptr[mem_size]) { + printf("%p--memory[%06x]", ptr, + (word32)(ptr - g_memory_ptr)); + } else if(ptr >= g_rom_fc_ff_ptr && ptr < &g_rom_fc_ff_ptr[256*1024]) { + printf("%p--rom_fc_ff[%06x]", ptr, + (word32)(ptr - g_rom_fc_ff_ptr)); + } else if(ptr >= g_slow_memory_ptr && ptr<&g_slow_memory_ptr[128*1024]){ + printf("%p--slow_memory[%06x]", ptr, + (word32)(ptr - g_slow_memory_ptr)); + } else if(ptr >=g_dummy_memory1_ptr && ptr < &g_dummy_memory1_ptr[256]){ + printf("%p--dummy_memory[%06x]", ptr, + (word32)(ptr - g_dummy_memory1_ptr)); + } else { + printf("%p--unknown", ptr); + } +} + + +#define CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc) \ + dcycs = g_sim65816.g_last_vbl_dcycs + *cyc_ptr; + + +int +io_read(word32 loc, double *cyc_ptr) +{ + double dcycs; + word64 word64_tmp; +#if 0 + double fcyc, new_fcyc; +#endif + word32 mask; + int new_lcbank2; + int new_wrdefram; + int tmp; + int i; + + CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc); + +/* IO space */ + switch((loc >> 8) & 0xf) { + case 0: /* 0xc000 - 0xc0ff */ + switch(loc & 0xff) { + /* 0xc000 - 0xc00f */ + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + { + int r = adb_read_c000(); + // printf("c000=%x\n",r); + return r; + } + /* 0xc010 - 0xc01f */ + case 0x10: /* c010 */ + return(adb_access_c010()); + case 0x11: /* c011 = RDLCBANK2 */ + return IOR(LCBANK2); + case 0x12: /* c012= RDLCRAM */ + return IOR(!RDROM); + case 0x13: /* c013=rdramd */ + return IOR(RAMRD); + case 0x14: /* c014=rdramwrt */ + return IOR(RAMWRT); + case 0x15: /* c015 = INTCX */ + return IOR(INTCX); + case 0x16: /* c016: ALTZP */ + return IOR(ALTZP); + case 0x17: /* c017: rdc3rom */ + return IOR(g_moremem.g_c02d_int_crom & (1 << 3)); + case 0x18: /* c018: rd80c0l */ + return IOR((g_video.g_cur_a2_stat & ALL_STAT_ST80)); + case 0x19: /* c019: rdvblbar */ + tmp = in_vblank(dcycs); + return IOR(tmp); + case 0x1a: /* c01a: rdtext */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_TEXT); + case 0x1b: /* c01b: rdmix */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_MIX_T_GR); + case 0x1c: /* c01c: rdpage2 */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_PAGE2); + case 0x1d: /* c01d: rdhires */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_HIRES); + case 0x1e: /* c01e: altcharset on? */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_ALTCHARSET); + case 0x1f: /* c01f: rd80vid */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_VID80); + + /* 0xc020 - 0xc02f */ + case 0x20: /* 0xc020 */ + /* Click cassette port */ + return 0x00; + case 0x21: /* 0xc021 */ + /* Not documented, but let's return COLOR_C021 */ + return IOR(g_video.g_cur_a2_stat & ALL_STAT_COLOR_C021); + case 0x22: /* 0xc022 */ + return (g_video.g_cur_a2_stat >> BIT_ALL_STAT_BG_COLOR) & 0xff; + case 0x23: /* 0xc023 */ + /* + { + extern Engine_reg engine; + // printf("c023=%X (%X)\n",g_moremem.g_c023_val,engine.kpc); + if (engine.kpc==0xB7D84) __asm int 3; + } + */ + return g_moremem.g_c023_val; + case 0x24: /* 0xc024 */ + return mouse_read_c024(dcycs); + case 0x25: /* 0xc025 */ + return adb_read_c025(); + case 0x26: /* 0xc026 */ + return adb_read_c026(); + case 0x27: /* 0xc027 */ + return adb_read_c027(); + case 0x28: /* 0xc028 */ + UNIMPL_READ; + case 0x29: /* 0xc029 */ + return((g_video.g_cur_a2_stat & 0xa0) | g_moremem.g_c029_val_some); + case 0x2a: /* 0xc02a */ +#if 0 + printf("Reading c02a...returning 0\n"); +#endif + return 0; + case 0x2b: /* 0xc02b */ + return g_moremem.g_c02b_val; + case 0x2c: /* 0xc02c */ + /* printf("reading c02c, returning 0\n"); */ + return 0; + case 0x2d: /* 0xc02d */ + tmp = g_moremem.g_c02d_int_crom; + return tmp; + case 0x2e: /* 0xc02e */ + case 0x2f: /* 0xc02f */ + return read_vid_counters(loc, dcycs); + + /* 0xc030 - 0xc03f */ + case 0x30: /* 0xc030 */ + /* click speaker */ + /* + if (g_moremem.g_c036_val_speed & 0x80) + printf("fast sound at : %x\n",g_sim65816.engine.kpc); + */ + return doc_read_c030(dcycs); + case 0x31: /* 0xc031 */ + /* 3.5" control */ + return g_moremem.g_c031_disk35; + case 0x32: /* 0xc032 */ + /* scan int */ + return 0; + case 0x33: /* 0xc033 = CLOCKDATA*/ + return g_moremem.g_c033_data; + case 0x34: /* 0xc034 = CLOCKCTL */ + return g_moremem.g_c034_val; + case 0x35: /* 0xc035 */ + return g_moremem.g_c035_shadow_reg; + case 0x36: /* 0xc036 = CYAREG */ + return g_moremem.g_c036_val_speed; + case 0x37: /* 0xc037 */ + return 0; + case 0x38: /* 0xc038 */ + return scc_read_reg(1, dcycs); + case 0x39: /* 0xc039 */ + return scc_read_reg(0, dcycs); + case 0x3a: /* 0xc03a */ + return scc_read_data(1, dcycs); + case 0x3b: /* 0xc03b */ + return scc_read_data(0, dcycs); + case 0x3c: /* 0xc03c */ + /* doc control */ + return doc_read_c03c(dcycs); + case 0x3d: /* 0xc03d */ + return doc_read_c03d(dcycs); + case 0x3e: /* 0xc03e */ + return (g_moremem.g_c03ef_doc_ptr & 0xff); + case 0x3f: /* 0xc03f */ + return (g_moremem.g_c03ef_doc_ptr >> 8); + + /* 0xc040 - 0xc04f */ + case 0x40: /* 0xc040 */ + /* cassette */ + return 0; + case 0x41: /* 0xc041 */ + return g_moremem.g_c041_val; + case 0x45: /* 0xc045 */ + halt_printf("Mega II mouse read: c045\n"); + return 0; + case 0x46: /* 0xc046 */ + tmp = g_moremem.g_c046_val; + g_moremem.g_c046_val = (tmp & 0xbf) + ((tmp & 0x80) >> 1); + return tmp; + case 0x47: /* 0xc047 */ + remove_irq(IRQ_PENDING_C046_25SEC | + IRQ_PENDING_C046_VBL); + g_moremem.g_c046_val &= 0xe7; /* clear vbl_int, 1/4sec int*/ + return 0; + case 0x42: /* 0xc042 */ + case 0x43: /* 0xc043 */ + return 0; + case 0x4f: /* 0xc04f */ + /* for information on c04f, see: */ + /* www.sheppyware.net/tech/hardware/softswitches.html */ + /* write to $c04f to start. Then read $c04f to get */ + /* emulator ($16=sweet16, $fe=bernie II). */ + /* Then read again to get version: $21 == 2.1 */ + switch(g_moremem.g_em_emubyte_cnt) { + case 1: + g_moremem.g_em_emubyte_cnt = 2; + return 'K'; + case 2: + g_moremem.g_em_emubyte_cnt = 0; + tmp = g_kegs_version_str[0] - '0'; + i = g_kegs_version_str[2] - '0'; + return ((tmp & 0xf) << 4) + (i & 0xf); + default: + g_moremem.g_em_emubyte_cnt = 0; + return 0; + } + case 0x44: /* 0xc044 */ + // OG + // Detecting which program is trying to detect the hardware + if (g_sim65816.engine.kpc >= 0xb00 && g_sim65816.engine.kpc <= 0xb10) + { + if (g_sim65816.g_6502_emulation && g_sim65816.g_rom_version == 1) + { + printf("reverting to 65C816 emulation for Zoyon Patrol!"); + g_sim65816.g_6502_emulation=0; // 2GS Operands are back to normal + g_rom_fc_ff_ptr[0x03fe28]=0x18; // CLC => 2GS can now be detected + } + } + // return LDA FB55 + return g_rom_fc_ff_ptr[0x03fb55]; + + case 0x48: /* 0xc048 */ + case 0x49: /* 0xc049 */ + case 0x4a: /* 0xc04a */ + case 0x4b: /* 0xc04b */ + case 0x4c: /* 0xc04c */ + case 0x4d: /* 0xc04d */ + case 0x4e: /* 0xc04e */ + UNIMPL_READ; + + /* 0xc050 - 0xc05f */ + case 0x50: /* 0xc050 */ + if(g_video.g_cur_a2_stat & ALL_STAT_TEXT) { + g_video.g_cur_a2_stat &= (~ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x51: /* 0xc051 */ + if((g_video.g_cur_a2_stat & ALL_STAT_TEXT) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x52: /* 0xc052 */ + if(g_video.g_cur_a2_stat & ALL_STAT_MIX_T_GR) { + g_video.g_cur_a2_stat &= (~ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x53: /* 0xc053 */ + if((g_video.g_cur_a2_stat & ALL_STAT_MIX_T_GR) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x54: /* 0xc054 */ + x_fixed_framerate(); + set_statereg(dcycs, g_moremem.g_c068_statereg & (~0x40)); + return float_bus(dcycs); + case 0x55: /* 0xc055 */ + x_fixed_framerate(); + set_statereg(dcycs, g_moremem.g_c068_statereg | 0x40); + return float_bus(dcycs); + case 0x56: /* 0xc056 */ + if(g_video.g_cur_a2_stat & ALL_STAT_HIRES) { + g_video.g_cur_a2_stat &= (~ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x57: /* 0xc057 */ + if((g_video.g_cur_a2_stat & ALL_STAT_HIRES) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x58: /* 0xc058 */ + if(g_moremem.g_zipgs_unlock < 4) { + g_moremem.g_c05x_annuncs &= (~1); + } + return 0; + case 0x59: /* 0xc059 */ + if(g_moremem.g_zipgs_unlock >= 4) { + return g_moremem.g_zipgs_reg_c059; + } else { + g_moremem.g_c05x_annuncs |= 1; + } + return 0; + case 0x5a: /* 0xc05a */ + if(g_moremem.g_zipgs_unlock >= 4) { + return g_moremem.g_zipgs_reg_c05a; + } else { + g_moremem.g_c05x_annuncs &= (~2); + } + return 0; + case 0x5b: /* 0xc05b */ + if(g_moremem.g_zipgs_unlock >= 4) { + word64_tmp = (word64)dcycs; + tmp = (word64_tmp >> 9) & 1; + return (tmp << 7) + (g_moremem.g_zipgs_reg_c05b & 0x7f); + } else { + g_moremem.g_c05x_annuncs |= 2; + } + return 0; + case 0x5c: /* 0xc05c */ + if(g_moremem.g_zipgs_unlock >= 4) { + return g_moremem.g_zipgs_reg_c05c; + } else { + g_moremem.g_c05x_annuncs &= (~4); + } + return 0; + case 0x5d: /* 0xc05d */ + if(g_moremem.g_zipgs_unlock >= 4) { + halt_printf("Reading ZipGS $c05d!\n"); + } else { + g_moremem.g_c05x_annuncs |= 4; + } + return 0; + case 0x5e: /* 0xc05e */ + if(g_moremem.g_zipgs_unlock >= 4) { + halt_printf("Reading ZipGS $c05e!\n"); + } else if(g_video.g_cur_a2_stat & ALL_STAT_ANNUNC3) { + g_video.g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return 0; + case 0x5f: /* 0xc05f */ + if(g_moremem.g_zipgs_unlock >= 4) { + halt_printf("Reading ZipGS $c05f!\n"); + } else if((g_video.g_cur_a2_stat & ALL_STAT_ANNUNC3) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return 0; + + + /* 0xc060 - 0xc06f */ + case 0x60: /* 0xc060 */ + return IOR(g_moremem.g_paddle_buttons & 8); + case 0x61: /* 0xc061 */ + return IOR(adb_is_cmd_key_down() || + g_moremem.g_paddle_buttons & 1); + case 0x62: /* 0xc062 */ + return IOR(adb_is_option_key_down() || + g_moremem.g_paddle_buttons & 2); + case 0x63: /* 0xc063 */ + return IOR(g_moremem.g_paddle_buttons & 4); + case 0x64: /* 0xc064 */ + return read_paddles(dcycs, 0); + case 0x65: /* 0xc065 */ + return read_paddles(dcycs, 1); + case 0x66: /* 0xc066 */ + return read_paddles(dcycs, 2); + case 0x67: /* 0xc067 */ + return read_paddles(dcycs, 3); + case 0x68: /* 0xc068 = STATEREG */ + return g_moremem.g_c068_statereg; + case 0x69: /* 0xc069 */ + /* Reserved reg, return 0 */ + return 0; + + // OG Transwarp Read Interface + #ifdef TRANSWARP + case 0x6a: /* 0xc06a */ + { + // extern double g_zip_pmhz; + return (int)(g_sim65816.g_zip_pmhz*1000)&0xFF; + } + case 0x6b: /* 0xc06b */ + { + //extern double g_zip_pmhz; + return (((int)(g_sim65816.g_zip_pmhz*1000))>>8)&0xFF; + } + case 0x6c: /* 0xc06c */ + { + // extern double g_zip_pmhz; + if (g_sim65816.g_zip_pmhz==1.0) return 0; // slow + else if (g_sim65816.g_zip_pmhz>=2.6) return 2; // warp + else return 1; // zip + } + #else + case 0x6a: /* 0xc06a */ + case 0x6b: /* 0xc06b */ + case 0x6c: /* 0xc06c */ + #endif + case 0x6d: /* 0xc06d */ + case 0x6e: /* 0xc06e */ + case 0x6f: /* 0xc06f */ + UNIMPL_READ; + + /* 0xc070 - 0xc07f */ + case 0x70: /* c070 */ + paddle_trigger(dcycs); + return 0; + case 0x71: /* 0xc071 */ + case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + return g_rom_fc_ff_ptr[3*65536 + 0xc000 + (loc & 0xff)]; + + /* 0xc080 - 0xc08f */ + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + new_lcbank2 = ((loc & 0x8) >> 1) ^ 0x4; + new_wrdefram = (loc & 1); + if(new_wrdefram != g_moremem.g_c08x_wrdefram) { + fixup_wrdefram(new_wrdefram); + } + switch(loc & 0x3) { + case 0x1: /* 0xc081 */ + case 0x2: /* 0xc082 */ + /* Read rom, set lcbank2 */ + set_statereg(dcycs, (g_moremem.g_c068_statereg & ~(0x04))| + (new_lcbank2 | 0x08)); + break; + case 0x0: /* 0xc080 */ + case 0x3: /* 0xc083 */ + /* Read ram (clear RDROM), set lcbank2 */ + set_statereg(dcycs, (g_moremem.g_c068_statereg & ~(0x0c))| + (new_lcbank2)); + break; + } + return float_bus(dcycs); + /* 0xc090 - 0xc09f */ + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + /* UNIMPL_READ; */ + return 0; + /* 0xc0a0 - 0xc0af */ + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + return 0; + /* UNIMPL_READ; */ + + /* 0xc0b0 - 0xc0bf */ + case 0xb0: + /* c0b0: female voice tool033 look at this */ + return 0; + case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + /* UNIMPL_READ; */ + return 0; + /* c0b8: Second Sight card stuff: return 0 */ + case 0xb8: + return 0; + break; + + /* 0xc0c0 - 0xc0cf */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return 0; + /* 0xc0d0 - 0xc0df */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + return 0; + /* 0xc0e0 - 0xc0ef */ + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xed: case 0xee: case 0xef: + return read_iwm(loc, dcycs); + case 0xec: + return iwm_read_c0ec(dcycs); + /* 0xc0f0 - 0xc0ff */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return 0; + + default: + printf("loc: %04x bad\n", loc); + UNIMPL_READ; + } + case 1: case 2: case 3: case 4: case 5: case 6: + /* c100 - c6ff */ + mask = (1 << ((loc >> 8) & 7)); + if(INTCX || ((g_moremem.g_c02d_int_crom & mask) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + return float_bus(dcycs); + case 7: + /* c700 */ + if(INTCX || ((g_moremem.g_c02d_int_crom & (1 << 7)) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + tmp = g_rom_fc_ff_ptr[0x3c500 + (loc & 0xff)]; + if((loc & 0xff) == 0xfb) { + tmp = tmp & 0xbf; /* clear bit 6 for ROM 03 */ + } + return tmp; + case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: + if(INTCX || ((g_moremem.g_c02d_int_crom & (1 << 3)) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + UNIMPL_READ; + case 0xf: + if(INTCX || ((g_moremem.g_c02d_int_crom & (1 << 3)) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + if((loc & 0xfff) == 0xfff) { + return g_rom_fc_ff_ptr[0x3cfff]; + } + UNIMPL_READ; + } + + halt_printf("io_read: hit end, loc: %06x\n", loc); + + return 0xff; +} + +void +io_write(word32 loc, int val, double *cyc_ptr) +{ + double dcycs; +#if 0 + double fcyc, new_fcyc; +#endif + int new_tmp; + int new_lcbank2; + int new_wrdefram; + int tmp; + int fixup; + + CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc); + + val = val & 0xff; + switch((loc >> 8) & 0xf) { + case 0: /* 0xc000 - 0xc0ff */ + switch(loc & 0xff) { + /* 0xc000 - 0xc00f */ + case 0x00: /* 0xc000 */ + if(g_video.g_cur_a2_stat & ALL_STAT_ST80) { + g_video.g_cur_a2_stat &= (~ALL_STAT_ST80); + fixup_st80col(dcycs); + } + return; + case 0x01: /* 0xc001 */ + if((g_video.g_cur_a2_stat & ALL_STAT_ST80) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_ST80); + fixup_st80col(dcycs); + } + return; + case 0x02: /* 0xc002 */ + set_statereg(dcycs, g_moremem.g_c068_statereg & ~0x20); + return; + case 0x03: /* 0xc003 */ + set_statereg(dcycs, g_moremem.g_c068_statereg | 0x20); + return; + case 0x04: /* 0xc004 */ + set_statereg(dcycs, g_moremem.g_c068_statereg & ~0x10); + return; + case 0x05: /* 0xc005 */ + set_statereg(dcycs, g_moremem.g_c068_statereg | 0x10); + return; + case 0x06: /* 0xc006 */ + set_statereg(dcycs, g_moremem.g_c068_statereg & ~0x01); + return; + case 0x07: /* 0xc007 */ + set_statereg(dcycs, g_moremem.g_c068_statereg | 0x01); + return; + case 0x08: /* 0xc008 */ + set_statereg(dcycs, g_moremem.g_c068_statereg & ~0x80); + return; + case 0x09: /* 0xc009 */ + set_statereg(dcycs, g_moremem.g_c068_statereg | 0x80); + return; + case 0x0a: /* 0xc00a */ + tmp = 1 << 3; + if((g_moremem.g_c02d_int_crom & tmp) != 0) { + g_moremem.g_c02d_int_crom &= ~tmp; + fixup_intcx(); + } + return; + case 0x0b: /* 0xc00b */ + tmp = 1 << 3; + if((g_moremem.g_c02d_int_crom & tmp) == 0) { + g_moremem.g_c02d_int_crom |= tmp; + fixup_intcx(); + } + return; + case 0x0c: /* 0xc00c */ + if(g_video.g_cur_a2_stat & ALL_STAT_VID80) { + g_video.g_cur_a2_stat &= (~ALL_STAT_VID80); + change_display_mode(dcycs); + } + return; + case 0x0d: /* 0xc00d */ + if((g_video.g_cur_a2_stat & ALL_STAT_VID80) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_VID80); + change_display_mode(dcycs); + } + return; + case 0x0e: /* 0xc00e */ + if(g_video.g_cur_a2_stat & ALL_STAT_ALTCHARSET) { + g_video.g_cur_a2_stat &= (~ALL_STAT_ALTCHARSET); + change_display_mode(dcycs); + } + return; + case 0x0f: /* 0xc00f */ + if((g_video.g_cur_a2_stat & ALL_STAT_ALTCHARSET) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_ALTCHARSET); + change_display_mode(dcycs); + } + return; + /* 0xc010 - 0xc01f */ + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + adb_access_c010(); + return; + /* 0xc020 - 0xc02f */ + case 0x20: /* 0xc020 */ + /* WRITE CASSETTE?? */ + return; + case 0x21: /* 0xc021 */ + new_tmp = ((val >> 7) & 1) << + (31 - BIT_ALL_STAT_COLOR_C021); + if((g_video.g_cur_a2_stat & ALL_STAT_COLOR_C021) != new_tmp) { + g_video.g_cur_a2_stat ^= new_tmp; + change_display_mode(dcycs); + } + return; + case 0x22: /* 0xc022 */ + /* change text color */ + tmp = (g_video.g_cur_a2_stat >> BIT_ALL_STAT_BG_COLOR) & 0xff; + if(val != tmp) { + /* change text/bg color! */ + g_video.g_cur_a2_stat &= ~(ALL_STAT_TEXT_COLOR | + ALL_STAT_BG_COLOR); + g_video.g_cur_a2_stat += (val << BIT_ALL_STAT_BG_COLOR); + change_display_mode(dcycs); + } + return; + case 0x23: /* 0xc023 */ + if((val & 0x19) != 0) { + halt_printf("c023 write of %02x!!!\n", val); + } + tmp = (g_moremem.g_c023_val & 0x70) | (val & 0x0f); + if((tmp & 0x22) == 0x22) { + //printf("adding scanline irq\n"); + add_irq(IRQ_PENDING_C023_SCAN); + } + if(!(tmp & 2)) { + //printf("remove scanline irq\n"); + remove_irq(IRQ_PENDING_C023_SCAN); + } + if((tmp & 0x44) == 0x44) { + add_irq(IRQ_PENDING_C023_1SEC); + } + if(!(tmp & 0x4)) { + remove_irq(IRQ_PENDING_C023_1SEC); + } + + if(g_moremem.g_irq_pending & (IRQ_PENDING_C023_SCAN | + IRQ_PENDING_C023_1SEC)) { + tmp |= 0x80; + } + //printf("old c023: %X new: %X\n",g_moremem.g_c023_val,tmp); + + g_moremem.g_c023_val = tmp; + return; + case 0x24: /* 0xc024 */ + /* Write to mouse reg: Throw it away */ + return; + case 0x26: /* 0xc026 */ + adb_write_c026(val); + return; + case 0x27: /* 0xc027 */ + adb_write_c027(val); + return; + case 0x29: /* 0xc029 */ + g_moremem.g_c029_val_some = val & 0x41; + if((val & 1) == 0) { + halt_printf("c029: %02x\n", val); + } + new_tmp = val & 0xa0; + if(new_tmp != (g_video.g_cur_a2_stat & 0xa0)) { + g_video.g_cur_a2_stat = (g_video.g_cur_a2_stat & (~0xa0)) + + new_tmp; + change_display_mode(dcycs); + } + return; + case 0x2a: /* 0xc02a */ +#if 0 + printf("Writing c02a with %02x\n", val); +#endif + return; + case 0x2b: /* 0xc02b */ + g_moremem.g_c02b_val = val; + if(val != 0x08 && val != 0x00) { + printf("Writing c02b with %02x\n", val); + } + return; + case 0x2d: /* 0xc02d */ + if((val & 0x9) != 0) { + halt_printf("Illegal c02d write: %02x!\n", val); + } + fixup = (val != g_moremem.g_c02d_int_crom); + g_moremem.g_c02d_int_crom = val; + if(fixup) { + vid_printf("Write c02d of %02x\n", val); + fixup_intcx(); + } + return; + case 0x28: /* 0xc028 */ + case 0x2c: /* 0xc02c */ + UNIMPL_WRITE; + case 0x25: /* 0xc025 */ + /* Space Shark writes to c025--ignore */ + case 0x2e: /* 0xc02e */ + case 0x2f: /* 0xc02f */ + /* Modulae writes to this--just ignore them */ + return; + break; + + /* 0xc030 - 0xc03f */ + case 0x30: /* 0xc030 */ +#if 0 + printf("Write speaker?\n"); +#endif + (void)doc_read_c030(dcycs); + return; + case 0x31: /* 0xc031 */ + tmp = val ^ g_moremem.g_c031_disk35; + if(tmp & 0x40) { + /* apple35_sel changed, maybe speed change */ + set_halt(HALT_EVENT); + } + g_moremem.g_c031_disk35 = val & 0xc0; + return; + case 0x32: /* 0xc032 */ + tmp = g_moremem.g_c023_val & 0x7f; + if(((val & 0x40) == 0) && (tmp & 0x40)) { + /* clear 1 sec int */ + remove_irq(IRQ_PENDING_C023_1SEC); + tmp &= 0xbf; + //printf("c032 (1s) old: %X new: %X\n",g_moremem.g_c023_val,tmp & 0xbf); + g_moremem.g_c023_val = tmp; + } + if( (val & 0x20) == 0 && !(tmp & 0x20) ) + { + irq_printf("no scan int irq to clear\n"); + } + else + if(((val & 0x20) == 0) && (tmp & 0x20)) { + + /* clear scan line int */ + remove_irq(IRQ_PENDING_C023_SCAN); + +#if 0 + // OG delayed write C023 (wait end of line before clearing value) + + { + extern word32 kpc; + printf("(%X) delayed clearing scanline irq old: %X new: %X\n",kpc,g_moremem.g_c023_val,tmp & 0xdf); + // add_event_entry(dcycs+ (DCYCS_IN_16MS/262.0)/2, 8 /*EV_DELAY_WRITE_C023*/ ); + g_delayed_c023_val = 1; + } +#else + //printf("clearing g_moremem.g_c023_val\n"); + g_moremem.g_c023_val = tmp & 0xdf; + check_for_new_scan_int(dcycs); +#endif + + + } + if(g_moremem.g_irq_pending & (IRQ_PENDING_C023_1SEC | + IRQ_PENDING_C023_SCAN)) { + irq_printf("c032 pending: %X\n",g_moremem.g_c023_val); + g_moremem.g_c023_val |= 0x80; + } + if((val & 0x9f) != 0x9f) { + irq_printf("c032: wrote %02x!\n", val); + } + return; + case 0x33: /* 0xc033 = CLOCKDATA*/ + g_moremem.g_c033_data = val; + return; + case 0x34: /* 0xc034 = CLOCKCTL */ + tmp = val ^ g_moremem.g_c034_val; + clock_write_c034(val); + if(tmp & 0xf) { + change_border_color(dcycs, val & 0xf); + } + return; + case 0x35: /* 0xc035 */ + update_shadow_reg(val); + return; + case 0x36: /* 0xc036 = CYAREG */ + tmp = val ^ g_moremem.g_c036_val_speed; + g_moremem.g_c036_val_speed = (val & ~0x20); /* clr bit 5 */ + if(tmp & 0x80) { + /* to recalculate times since speed changing */ + set_halt(HALT_EVENT); + } + if(tmp & 0xf) { + /* slot_motor_detect changed */ + set_halt(HALT_EVENT); + } + + if((val & 0x60) != 0) { + /* for ROM 03, 0x40 is the power-on status */ + /* and can be read/write */ + if(((val & 0x60) != 0x40) || + (g_sim65816.g_rom_version < 3)) { + g_moremem.g_c036_val_speed &= (~0x60); + halt_printf("c036: %2x\n", val); + } + } + if(tmp & 0x10) { /* shadow in all banks! */ + if(g_moremem.g_num_shadow_all_banks++ == 0) { + printf("Shadowing all banks...This " + "must be the NFC Megademo\n"); + } + fixup_shadow_all_banks(); + } + return; + case 0x37: /* 0xc037 */ + /* just ignore, probably someone writing c036 m=0 */ + return; + case 0x38: /* 0xc038 */ + scc_write_reg(1, val, dcycs); + return; + case 0x39: /* 0xc039 */ + scc_write_reg(0, val, dcycs); + return; + case 0x3a: /* 0xc03a */ + scc_write_data(1, val, dcycs); + return; + case 0x3b: /* 0xc03b */ + scc_write_data(0, val, dcycs); + return; + case 0x3c: /* 0xc03c */ + /* doc ctl */ + doc_write_c03c(val, dcycs); + return; + case 0x3d: /* 0xc03d */ + /* doc data reg */ + doc_write_c03d(val, dcycs); + return; + case 0x3e: /* 0xc03e */ + g_moremem.g_c03ef_doc_ptr = (g_moremem.g_c03ef_doc_ptr & 0xff00) + val; + return; + case 0x3f: /* 0xc03f */ + g_moremem.g_c03ef_doc_ptr = (g_moremem.g_c03ef_doc_ptr & 0xff) + (val << 8); + return; + + /* 0xc040 - 0xc04f */ + case 0x41: /* c041 */ + g_moremem.g_c041_val = val & 0x1f; + + if((val & 0xe7) != 0) { + halt_printf("write c041: %02x\n", val); + } + + if(!(val & C041_EN_VBL_INTS)) { + /* no more vbl interrupt */ + remove_irq(IRQ_PENDING_C046_VBL); + } + if(!(val & C041_EN_25SEC_INTS)) { + remove_irq(IRQ_PENDING_C046_25SEC); + } + return; + case 0x46: /* c046 */ + /* ignore writes to c046 */ + return; + case 0x47: /* c047 */ + remove_irq(IRQ_PENDING_C046_VBL | + IRQ_PENDING_C046_25SEC); + g_moremem.g_c046_val &= 0xe7; /* clear vblint, 1/4sec int*/ + return; + case 0x48: /* c048 */ + /* diversitune writes this--ignore it */ + return; + case 0x42: /* c042 */ + case 0x43: /* c043 */ + return; + case 0x4f: /* c04f */ + g_moremem.g_em_emubyte_cnt = 1; + return; + case 0x40: /* c040 */ + case 0x44: /* c044 */ + case 0x45: /* c045 */ + case 0x49: /* c049 */ + case 0x4a: /* c04a */ + case 0x4b: /* c04b */ + case 0x4c: /* c04c */ + case 0x4d: /* c04d */ + case 0x4e: /* c04e */ + UNIMPL_WRITE; + + /* 0xc050 - 0xc05f */ + case 0x50: /* 0xc050 */ + if(g_video.g_cur_a2_stat & ALL_STAT_TEXT) { + g_video.g_cur_a2_stat &= (~ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return; + case 0x51: /* 0xc051 */ + if((g_video.g_cur_a2_stat & ALL_STAT_TEXT) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return; + case 0x52: /* 0xc052 */ + if(g_video.g_cur_a2_stat & ALL_STAT_MIX_T_GR) { + g_video.g_cur_a2_stat &= (~ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return; + case 0x53: /* 0xc053 */ + if((g_video.g_cur_a2_stat & ALL_STAT_MIX_T_GR) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return; + case 0x54: /* 0xc054 */ + // printf("*"); + // addFrameRate(3); + set_statereg(dcycs, g_moremem.g_c068_statereg & (~0x40)); + return; + case 0x55: /* 0xc055 */ + // addFrameRate(4); + set_statereg(dcycs, g_moremem.g_c068_statereg | 0x40); + return; + case 0x56: /* 0xc056 */ + if(g_video.g_cur_a2_stat & ALL_STAT_HIRES) { + g_video.g_cur_a2_stat &= (~ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return; + case 0x57: /* 0xc057 */ + if((g_video.g_cur_a2_stat & ALL_STAT_HIRES) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return; + case 0x58: /* 0xc058 */ + if(g_moremem.g_zipgs_unlock >= 4) { + g_moremem.g_zipgs_reg_c059 &= 0x4; /* last reset cold */ + } else { + g_moremem.g_c05x_annuncs &= (~1); + } + return; + case 0x59: /* 0xc059 */ + if(g_moremem.g_zipgs_unlock >= 4) + { + if (g_sim65816.get_limit_speed() == SPEED_ZIP || g_sim65816.get_limit_speed() ==SPEED_UNLIMITED) + g_moremem.g_zipgs_reg_c059 = (val & 0xf8) | (g_moremem.g_zipgs_reg_c059 & 0x7); + else + { + printf("discarding zipgs detection in 2GS mode!\n"); + g_moremem.g_zipgs_reg_c059 ^= (0xaa); + } + } else { + g_moremem.g_c05x_annuncs |= 1; + } + return; + case 0x5a: /* 0xc05a */ + g_moremem.g_c05x_annuncs &= (~2); + if((val & 0xf0) == 0x50) { + g_moremem.g_zipgs_unlock++; + } else if((val & 0xf0) == 0xa0) { + g_moremem.g_zipgs_unlock = 0; + } else if(g_moremem.g_zipgs_unlock >= 4) { + if((g_moremem.g_zipgs_reg_c05b & 0x10) == 0) { + /* to recalculate times */ + set_halt(HALT_EVENT); + } + g_moremem.g_zipgs_reg_c05b |= 0x10; // disable + } + return; + case 0x5b: /* 0xc05b */ + if(g_moremem.g_zipgs_unlock >= 4) { + if((g_moremem.g_zipgs_reg_c05b & 0x10) != 0) { + /* to recalculate times */ + set_halt(HALT_EVENT); + } + g_moremem.g_zipgs_reg_c05b &= (~0x10); // enable + } else { + g_moremem.g_c05x_annuncs |= 2; + } + return; + case 0x5c: /* 0xc05c */ + if(g_moremem.g_zipgs_unlock >= 4) { + g_moremem.g_zipgs_reg_c05c = val; + } else { + g_moremem.g_c05x_annuncs &= (~4); + } + return; + case 0x5d: /* 0xc05d */ + if(g_moremem.g_zipgs_unlock >= 4) { + if(((g_moremem.g_zipgs_reg_c05a ^ val) >= 0x10) && + ((g_moremem.g_zipgs_reg_c05b & 0x10) == 0)) { + set_halt(HALT_EVENT); + } + g_moremem.g_zipgs_reg_c05a = val | 0xf; + } else { + g_moremem.g_c05x_annuncs |= 4; + } + return; + case 0x5e: /* 0xc05e */ + if(g_moremem.g_zipgs_unlock >= 4) { + /* Zippy writes 0x80 and 0x00 here... */ + } else if(g_video.g_cur_a2_stat & ALL_STAT_ANNUNC3) { + g_video.g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return; + case 0x5f: /* 0xc05f */ + if(g_moremem.g_zipgs_unlock >= 4) { + halt_printf("Wrote ZipGS $c05f: %02x\n", val); + } else if((g_video.g_cur_a2_stat & ALL_STAT_ANNUNC3) == 0) { + g_video.g_cur_a2_stat |= (ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return; + + + /* 0xc060 - 0xc06f */ + case 0x60: /* 0xc060 */ + case 0x61: /* 0xc061 */ + case 0x62: /* 0xc062 */ + case 0x63: /* 0xc063 */ + case 0x64: /* 0xc064 */ + case 0x65: /* 0xc065 */ + case 0x66: /* 0xc066 */ + case 0x67: /* 0xc067 */ + /* all the above do nothing--return */ + return; + case 0x68: /* 0xc068 = STATEREG */ + set_statereg(dcycs, val); + return; + case 0x69: /* 0xc069 */ + /* just ignore, someone writing c068 with m=0 */ + return; + + +#ifdef TRANSWARP + // OG writeTranswarp pseudo-register + case 0x6a: /* 0xc06a */ + g_moremem.transwarp_low_val = val; + return ; + case 0x6b: /* 0xc06b */ + val = (val<<8) + g_moremem.transwarp_low_val; + if ((val==2600) || (val==0x0028)) // Bug for demo ... + { + printf("Disabling Transwarp!\n"); + g_moremem.g_zipgs_reg_c05b |= 0x10; // disable + set_halt(HALT_EVENT); + } + else if (val==8000) + { + printf("Enabling Transwarp!\n"); + g_moremem.g_zipgs_reg_c05b &= ~0x10; // enable + set_halt(HALT_EVENT); + } + else + printf("unknown twgs speed:%d\n",val); + return; + case 0x6c: /* 0xc06c */ + if (val==0) + ; // set slow ? + else if (val==1) + { + // disable zip + g_moremem.g_zipgs_reg_c05b |= 0x10; // disable + set_halt(HALT_EVENT); + } + else if (val==2) + { + // enable zip + g_moremem.g_zipgs_reg_c05b &= ~0x10; // enable + set_halt(HALT_EVENT); + } + else + printf("unknown twgs index:%d\n",val); + return ; +#else + case 0x6a: /* 0xc06a */ + case 0x6b: /* 0xc06b */ + case 0x6c: /* 0xc06c */ +#endif + case 0x6d: /* 0xc06d */ + case 0x6e: /* 0xc06e */ + case 0x6f: /* 0xc06f */ + UNIMPL_WRITE; + + /* 0xc070 - 0xc07f */ + case 0x70: /* 0xc070 = Trigger paddles */ + paddle_trigger(dcycs); + return; + case 0x73: /* 0xc073 = multibank ram card bank addr? */ + return; + case 0x71: /* 0xc071 = another multibank ram card enable? */ + case 0x7e: /* 0xc07e */ + case 0x7f: /* 0xc07f */ + return; + case 0x72: /* 0xc072 */ + case 0x74: /* 0xc074 */ + case 0x75: /* 0xc075 */ + case 0x76: /* 0xc076 */ + case 0x77: /* 0xc077 */ + case 0x78: /* 0xc078 */ + case 0x79: /* 0xc079 */ + case 0x7a: /* 0xc07a */ + case 0x7b: /* 0xc07b */ + case 0x7c: /* 0xc07c */ + case 0x7d: /* 0xc07d */ + UNIMPL_WRITE; + + /* 0xc080 - 0xc08f */ + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + new_lcbank2 = ((loc >> 1) & 0x4) ^ 0x4; + new_wrdefram = (loc & 1); + if(new_wrdefram != g_moremem.g_c08x_wrdefram) { + fixup_wrdefram(new_wrdefram); + } + switch(loc & 0xf) { + case 0x1: /* 0xc081 */ + case 0x2: /* 0xc082 */ + case 0x5: /* 0xc085 */ + case 0x6: /* 0xc086 */ + case 0x9: /* 0xc089 */ + case 0xa: /* 0xc08a */ + case 0xd: /* 0xc08d */ + case 0xe: /* 0xc08e */ + /* Read rom, set lcbank2 */ + set_statereg(dcycs, (g_moremem.g_c068_statereg & ~(0x04))| + (new_lcbank2 | 0x08)); + break; + case 0x0: /* 0xc080 */ + case 0x3: /* 0xc083 */ + case 0x4: /* 0xc084 */ + case 0x7: /* 0xc087 */ + case 0x8: /* 0xc088 */ + case 0xb: /* 0xc08b */ + case 0xc: /* 0xc08c */ + case 0xf: /* 0xc08f */ + /* Read ram (clear RDROM), set lcbank2 */ + set_statereg(dcycs, (g_moremem.g_c068_statereg & ~(0x0c))| + (new_lcbank2)); + break; + } + return; + + /* 0xc090 - 0xc09f */ + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + UNIMPL_WRITE; + + /* 0xc0a0 - 0xc0af */ + case 0xa0: case 0xa1: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + UNIMPL_WRITE; + case 0xa2: /* Burger Times writes here on error */ + case 0xa8: + /* Kurzweil SMP writes to 0xc0a8, ignore it */ + return; + + /* 0xc0b0 - 0xc0bf */ + case 0xb0: + /* Second sight stuff--ignore it */ + return; + case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + UNIMPL_WRITE; + + /* 0xc0c0 - 0xc0cf */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + UNIMPL_WRITE; + + /* 0xc0d0 - 0xc0df */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + UNIMPL_WRITE; + + /* 0xc0e0 - 0xc0ef */ + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + write_iwm(loc, val, dcycs); + return; + + /* 0xc0f0 - 0xc0ff */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + UNIMPL_WRITE; + default: + printf("WRite loc: %x\n",loc); + x_exit(-300); + } + break; + case 1: case 2: case 3: case 4: case 5: case 6: case 7: + /* c1000 - c7ff */ + UNIMPL_WRITE; + case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: + UNIMPL_WRITE; + case 0xf: + if((loc & 0xfff) == 0xfff) { + /* cfff */ + return; + } + UNIMPL_WRITE; + } + printf("Huh2? Write loc: %x\n", loc); + x_exit(-290); +} + + + +#if 0 +int +get_slow_mem(word32 loc, int duff_cycles) +{ + int val; + + loc = loc & 0x1ffff; + + if((loc &0xf000) == 0xc000) { + return(io_read(loc &0xfff, duff_cycles)); + } + if((loc & 0xf000) >= 0xd000) { + if((loc & 0xf000) == 0xd000) { + if(!LCBANK2) { + /* Not LCBANK2 == be 0xc000 - 0xd000 */ + loc = loc - 0x1000; + } + } + } + + val = g_slow_memory_ptr[loc]; + + halt_printf("get_slow_mem: %06x = %02x\n", loc, val); + + return val; +} + +int +set_slow_mem(word32 loc, int val, int duff_cycles) +{ + int or_pos; + word32 or_val; + + loc = loc & 0x1ffff; + if((loc & 0xf000) == 0xc000) { + return(io_write(loc & 0xfff, val, duff_cycles)); + } + + if((loc & 0xf000) == 0xd000) { + if(!LCBANK2) { + /* Not LCBANK2 == be 0xc000 - 0xd000 */ + loc = loc - 0x1000; + } + } + + if(g_slow_memory_ptr[loc] != val) { + or_pos = (loc >> SHIFT_PER_CHANGE) & 0x1f; + or_val = DEP1(1, or_pos, 0); + if((loc >> CHANGE_SHIFT) >= SLOW_MEM_CH_SIZE || loc < 0) { + printf("loc: %08x!!\n", loc); + x_exit(11); + } + g_video.slow_mem_changed[(loc & 0xffff) >> CHANGE_SHIFT] |= or_val; + } + +/* doesn't shadow text/hires graphics properly! */ + g_slow_memory_ptr[loc] = val; + + return val; +} +#endif + +/* IIgs vertical line counters */ +/* 0x7d - 0x7f: in vbl, top of screen? */ +/* 0x80 - 0xdf: not in vbl, drawing screen */ +/* 0xe0 - 0xff: in vbl, bottom of screen */ + +/* Note: lines are then 0-0x60 effectively, for 192 lines */ +/* vertical blanking engages on line 192, even if in super hires mode */ +/* (Last 8 lines in SHR are drawn with vbl_active set */ + +word32 +get_lines_since_vbl(double dcycs) +{ + double dcycs_since_last_vbl; + double dlines_since_vbl; + double dcyc_line_start; + word32 lines_since_vbl; + int offset; + + dcycs_since_last_vbl = dcycs - g_sim65816.g_last_vbl_dcycs; + + dlines_since_vbl = dcycs_since_last_vbl * (1.0 / 65.0); + lines_since_vbl = (int)dlines_since_vbl; + dcyc_line_start = (double)lines_since_vbl * 65.0; + + offset = ((int)(dcycs_since_last_vbl - dcyc_line_start)) & 0xff; + + lines_since_vbl = (lines_since_vbl << 8) + offset; + + if(lines_since_vbl < 0x10680) { + return lines_since_vbl; + } else { + halt_printf("lines_since_vbl: %08x!\n", lines_since_vbl); + printf("dc_s_l_v: %f, dcycs: %f, last_vbl_cycs: %f\n", + dcycs_since_last_vbl, dcycs, g_sim65816.g_last_vbl_dcycs); + show_dtime_array(); + show_all_events(); + /* U_STACK_TRACE(); */ + } + + return lines_since_vbl; +} + + +int +in_vblank(double dcycs) +{ + int lines_since_vbl; + if (g_sim65816.g_fixed_vblank != 0) + { + if (g_sim65816.g_vbl_count < ( g_sim65816.g_vbl_count_since_lastvblank + g_sim65816.g_fixed_vblank) ) + return 0; + } + + lines_since_vbl = get_lines_since_vbl(dcycs); + + if(lines_since_vbl >= 0xc000) + { + g_sim65816.g_vbl_count_since_lastvblank = g_sim65816.g_vbl_count ; + return 1; + } + + return 0; +} + +/* horizontal video counter goes from 0x00,0x40 - 0x7f, then 0x80,0xc0-0xff */ +/* over 2*65 cycles. The last visible screen pos is 0x7f and 0xff */ +/* This matches KEGS starting line 0 at the border for line -1 */ +int +read_vid_counters(int loc, double dcycs) +{ + word32 mask; + int lines_since_vbl; + + loc = loc & 0xf; + + lines_since_vbl = get_lines_since_vbl(dcycs); + + lines_since_vbl += 0x10000; + if(lines_since_vbl >= 0x20000) { + lines_since_vbl = lines_since_vbl - 0x20000 + 0xfa00; + } + + if(lines_since_vbl > 0x1ffff) { + halt_printf("lines_since_vbl: %04x, dcycs: %f, last_vbl: %f\n", + lines_since_vbl, dcycs, g_sim65816.g_last_vbl_dcycs); + } + + if(loc == 0xe) { + /* Vertical count */ + // OxF0 never returned ('stopped at E3'), causing Noisetracker screen saver to freeze + int l = (lines_since_vbl >> 9) & 0xff ; + /* + + static int min=100000; + static int max=0; + + if (lmax) + { + max = l; + printf("max vlb:%x\n",l); + } + if (l==0xF0) + printf("*"); + */ + + return l; + } + + mask = (lines_since_vbl >> 1) & 0x80; + + lines_since_vbl = (lines_since_vbl & 0xff); + if(lines_since_vbl >= 0x01) { + lines_since_vbl = (lines_since_vbl + 0x3f) & 0x7f; + } + return (mask | (lines_since_vbl & 0xff)); +} + diff --git a/kegs/Src/moremem.h b/kegs/Src/moremem.h new file mode 100644 index 0000000..3830681 --- /dev/null +++ b/kegs/Src/moremem.h @@ -0,0 +1,93 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#define IOR(val) ( (val) ? 0x80 : 0x00 ) + +#define ALTZP (g_moremem.g_c068_statereg & 0x80) +/* #define PAGE2 (g_c068_statereg & 0x40) */ +#define RAMRD (g_moremem.g_c068_statereg & 0x20) +#define RAMWRT (g_moremem.g_c068_statereg & 0x10) +#define RDROM (g_moremem.g_c068_statereg & 0x08) +#define LCBANK2 (g_moremem.g_c068_statereg & 0x04) +#define ROMB (g_moremem.g_c068_statereg & 0x02) +#define INTCX (g_moremem.g_c068_statereg & 0x01) + + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +class s_moremem : public serialized +{ +public: + int g_num_shadow_all_banks ; + int g_em_emubyte_cnt ; + int g_paddle_buttons ; + int g_irq_pending ; + + int g_c023_val; + + int g_c029_val_some ; + int g_c02b_val ; + int g_c02d_int_crom ; + int g_c031_disk35 ; + int g_c033_data ; + int g_c034_val ; + int g_c035_shadow_reg ; + int g_c036_val_speed ; + int g_c03ef_doc_ptr ; + + int g_c041_val ; /* C041_EN_25SEC_INTS, C041_EN_MOVE_INTS */ + int g_c046_val ; + int g_c05x_annuncs ; + int g_c068_statereg ; + int g_c08x_wrdefram ; + int g_zipgs_unlock ; + int g_zipgs_reg_c059 ; + // 7=LC cache dis, 6==5ms paddle del en, 5==5ms ext del en, + // 4==5ms c02e enab, 3==CPS follow enab, 2-0: 111 + int g_zipgs_reg_c05a ; + // 7:4 = current ZIP speed, 0=100%, 1=93.75%, F=6.25% + // 3:0: always 1111 + int g_zipgs_reg_c05b; + // 7==1ms clock, 6==cshupd: tag data at c05f updated + // 5==LC cache disable, 4==bd is disabled, 3==delay in effect, + // 2==rombank, 1-0==ram size (00:8K, 01=16K, 10=32K, 11=64K) + int g_zipgs_reg_c05c ; + // 7:1==slot delay enable (for 52-54ms), 0==speaker 5ms delay + int transwarp_low_val ; + + // from engine_c.cpp + int g_ret1; + int g_ret2; + + + s_moremem() + { + + INIT_SERIALIZED(); + + g_c029_val_some = 0x41; + g_c02b_val = 0x08; + g_c035_shadow_reg = 0x08; + g_c036_val_speed = 0x80; + g_zipgs_reg_c059 = 0x5f; + g_zipgs_reg_c05a = 0x0f; + g_zipgs_reg_c05b = 0x40; + } + + DEFAULT_SERIALIZE_IN_OUT ; + +} XCODE_PRAGMA_PACK; + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +extern s_moremem g_moremem; + diff --git a/kegs/Src/op_routs.h b/kegs/Src/op_routs.h new file mode 100644 index 0000000..29ad1d4 --- /dev/null +++ b/kegs/Src/op_routs.h @@ -0,0 +1,462 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef ASM +# ifdef INCLUDE_RCSID_S + .data + .export rcsdif_op_routs_h,data +rcsdif_op_routs_h + .stringz "@(#)$KmKId: op_routs.h,v 1.40 2004-01-10 15:49:46-05 kentd Exp $" + .code +# endif + + .import get_mem_b0_16,code + .import get_mem_b0_8,code + + .export op_routs_start,data +op_routs_start .word 0 +#endif /* ASM */ + +#ifdef ASM +# define CMP_INDEX_REG_MEAT8(index_reg) \ + extru ret0,31,8,ret0 ! \ + ldi 0xff,scratch3 ! \ + subi 0x100,ret0,ret0 ! \ + add index_reg,ret0,ret0 ! \ + extru ret0,23,1,scratch1 ! \ + and ret0,scratch3,zero ! \ + extru ret0,24,1,neg ! \ + b dispatch ! \ + dep scratch1,31,1,psr + +# define CMP_INDEX_REG_MEAT16(index_reg) \ + extru ret0,31,16,ret0 ! \ + ldil l%0x10000,scratch2 ! \ + zdepi -1,31,16,scratch3 ! \ + sub scratch2,ret0,ret0 ! \ + add index_reg,ret0,ret0 ! \ + extru ret0,15,1,scratch1 ! \ + and ret0,scratch3,zero ! \ + extru ret0,16,1,neg ! \ + b dispatch ! \ + dep scratch1,31,1,psr + +# define CMP_INDEX_REG_LOAD(new_label, index_reg) \ + bb,>=,n psr,27,new_label ! \ + bl get_mem_long_8,link ! \ + nop ! \ + CMP_INDEX_REG_MEAT8(index_reg) ! \ + .label new_label ! \ + bl get_mem_long_16,link ! \ + nop ! \ + CMP_INDEX_REG_MEAT16(index_reg) +#endif + + +#ifdef ASM +#define GET_DLOC_X_IND_WR() \ + CYCLES_PLUS_1 ! \ + add xreg,direct,scratch2 ! \ + INC_KPC_2 ! \ + add scratch2,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + dep dbank,15,8,arg0 +#else /* C */ +# define GET_DLOC_X_IND_WR() \ + CYCLES_PLUS_1; \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + arg = arg + xreg + direct; \ + GET_MEMORY_DIRECT_PAGE16(arg & 0xffff, arg); \ + arg = (dbank << 16) + arg; +#endif + + +#ifdef ASM +# define GET_DLOC_X_IND_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_X_IND_WR() +#else /* C */ +# define GET_DLOC_X_IND_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_X_IND_WR() +#endif + +#ifdef ASM +# define GET_DISP8_S_WR() \ + CYCLES_PLUS_1 ! \ + add stack,arg0,arg0 ! \ + INC_KPC_2 ! \ + extru arg0,31,16,arg0 +#else /* C */ +#define GET_DISP8_S_WR() \ + CYCLES_PLUS_1; \ + arg = (arg + stack) & 0xffff; \ + INC_KPC_2; +#endif + + +#ifdef ASM +# define GET_DISP8_S_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_WR() +#else /* C */ +# define GET_DISP8_S_ADDR() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_WR() +#endif + +#ifdef ASM +# define GET_DLOC_WR() \ + INC_KPC_2 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + add direct,arg0,arg0 ! \ + extru arg0,31,16,arg0 +#else /* C */ +# define GET_DLOC_WR() \ + arg = (arg + direct) & 0xffff; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; +#endif + +#ifdef ASM +# define GET_DLOC_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_WR() +#else /* C */ +# define GET_DLOC_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_WR() +#endif + +#ifdef ASM +# define GET_DLOC_L_IND_WR() \ + INC_KPC_2 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_24,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 +#else /* C */ +# define GET_DLOC_L_IND_WR() \ + arg = (arg + direct) & 0xffff; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + GET_MEMORY24(arg, arg, 1); +#endif + + +#ifdef ASM +# define GET_DLOC_L_IND_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_WR() +#else /* C */ +# define GET_DLOC_L_IND_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_WR() +#endif + +#ifdef ASM +# define GET_DLOC_IND_Y_ADDR_FOR_WR() \ + ldb 1(scratch1),arg0 ! \ + CYCLES_PLUS_1 ! \ + GET_DLOC_IND_Y_WR_SPECIAL() +#else /* C */ +# define GET_DLOC_IND_Y_ADDR_FOR_WR() \ + GET_1BYTE_ARG; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, tmp1); \ + tmp1 += (dbank << 16); \ + arg = tmp1 + yreg; \ + CYCLES_PLUS_1; \ + INC_KPC_2; +#endif + + +#ifdef ASM +# define GET_DLOC_IND_WR() \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 ! \ + dep dbank,15,16,arg0 +#else /* C */ +# define GET_DLOC_IND_WR() \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, arg); \ + arg = (dbank << 16) + arg; +#endif + + +#ifdef ASM +# define GET_DLOC_IND_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_IND_WR() +#else +# define GET_DLOC_IND_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_IND_WR(); +#endif + +#ifdef ASM +#define GET_DLOC_INDEX_WR(index_reg) \ + GET_DLOC_INDEX_WR_A(index_reg) ! GET_DLOC_INDEX_WR_B(index_reg) + +#define GET_DLOC_INDEX_WR_A(index_reg) \ + CYCLES_PLUS_1 ! \ + add index_reg,direct,scratch2 ! \ + extru direct,23,8,scratch1 ! \ + INC_KPC_2 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + bb,>= psr,23,.+16 ! \ +/* 4*/ add scratch2,arg0,arg0 ! \ +/* 8*/ extru,<> direct,31,8,0 ! \ +/*12*/ dep scratch1,23,8,arg0 + +/* GET_DLOC_INDeX_WR_B must be exactly one instruction! */ +#define GET_DLOC_INDEX_WR_B(index_reg) \ +/*16*/ extru arg0,31,16,arg0 + +#define GET_DLOC_Y_WR() \ + GET_DLOC_INDEX_WR(yreg) + +#define GET_DLOC_X_WR() \ + GET_DLOC_INDEX_WR(xreg) + +#define GET_DLOC_Y_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_Y_WR() + +# define GET_DLOC_X_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_X_WR() + +#else +# define GET_DLOC_INDEX_WR(index_reg) \ + CYCLES_PLUS_1; \ + arg = (arg & 0xff) + index_reg; \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + if((psr & 0x100) && ((direct & 0xff) == 0)) { \ + arg = (arg & 0xff); \ + } \ + arg = (arg + direct) & 0xffff; + +# define GET_DLOC_X_WR() \ + GET_DLOC_INDEX_WR(xreg) +# define GET_DLOC_Y_WR() \ + GET_DLOC_INDEX_WR(yreg) + +# define GET_DLOC_X_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_INDEX_WR(xreg) + +# define GET_DLOC_Y_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_INDEX_WR(yreg) +#endif + + +#ifdef ASM +# define GET_DISP8_S_IND_Y_WR() \ + add stack,arg0,arg0 ! \ + bl get_mem_b0_16,link ! \ + extru arg0,31,16,arg0 ! \ + dep dbank,15,16,ret0 ! \ + CYCLES_PLUS_2 ! \ + add ret0,yreg,arg0 ! \ + INC_KPC_2 ! \ + extru arg0,31,24,arg0 + +# define GET_DISP8_S_IND_Y_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_IND_Y_WR() +#else /* C */ + +# define GET_DISP8_S_IND_Y_WR() \ + arg = (stack + arg) & 0xffff; \ + GET_MEMORY16(arg,arg,1); \ + CYCLES_PLUS_2; \ + arg += (dbank << 16); \ + INC_KPC_2; \ + arg = (arg + yreg) & 0xffffff; + +# define GET_DISP8_S_IND_Y_ADDR() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_IND_Y_WR() +#endif + + +#ifdef ASM +# define GET_DLOC_L_IND_Y_WR() \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_24,link ! \ + extru arg0,31,16,arg0 ! \ + add ret0,yreg,arg0 ! \ + extru arg0,31,24,arg0 + +# define GET_DLOC_L_IND_Y_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_Y_WR() +#else /* C */ + +# define GET_DLOC_L_IND_Y_WR() \ + arg = (direct + arg) & 0xffff; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY24(arg,arg,1); \ + INC_KPC_2; \ + arg = (arg + yreg) & 0xffffff; + +# define GET_DLOC_L_IND_Y_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_Y_WR() +#endif + + +#ifdef ASM +# define GET_ABS_ADDR() \ + ldb 1(scratch1),arg0 ! \ + ldb 2(scratch1),scratch1 ! \ + CYCLES_PLUS_1 ! \ + dep dbank,15,8,arg0 ! \ + INC_KPC_3 ! \ + dep scratch1,23,8,arg0 + +# define GET_LONG_ADDR() \ + ldb 1(scratch1),arg0 ! \ + ldb 2(scratch1),scratch2 ! \ + CYCLES_PLUS_2 ! \ + ldb 3(scratch1),scratch1 ! \ + INC_KPC_4 ! \ + dep scratch2,23,8,arg0 ! \ + dep scratch1,15,8,arg0 +#else /* C */ + +# define GET_ABS_ADDR() \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + arg = arg + (dbank << 16); \ + INC_KPC_3; + +# define GET_LONG_ADDR() \ + GET_3BYTE_ARG; \ + CYCLES_PLUS_2; \ + INC_KPC_4; +#endif + +#ifdef ASM +#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \ + ldb 1(scratch1),arg0 ! \ + copy index_reg,scratch3 ! \ + ldb 2(scratch1),scratch2 ! \ + dep dbank,15,8,scratch3 ! \ + INC_KPC_3 ! \ + dep scratch2,23,8,arg0 ! \ + CYCLES_PLUS_2 ! \ + add arg0,scratch3,arg0 ! \ + extru arg0,31,24,arg0 + +#define GET_LONG_X_ADDR_FOR_WR() \ + ldb 3(scratch1),scratch2 ! \ + copy xreg,scratch3 ! \ + ldb 1(scratch1),arg0 ! \ + ldb 2(scratch1),scratch1 ! \ + CYCLES_PLUS_2 ! \ + dep scratch2,15,8,scratch3 ! \ + INC_KPC_4 ! \ + dep scratch1,23,8,arg0 ! \ + add arg0,scratch3,arg0 ! \ + extru arg0,31,24,arg0 +#else /* C */ + +#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \ + GET_2BYTE_ARG; \ + arg = arg + (dbank << 16); \ + INC_KPC_3; \ + CYCLES_PLUS_2; \ + arg = (arg + index_reg) & 0xffffff; + +#define GET_LONG_X_ADDR_FOR_WR() \ + GET_3BYTE_ARG; \ + INC_KPC_4; \ + arg = (arg + xreg) & 0xffffff; \ + CYCLES_PLUS_2; + +#endif /* ASM */ + + +#ifdef ASM + .export op_routs_end,data +op_routs_end .word 0 + + +#define GET_DLOC_IND_Y_WR_SPECIAL() \ + add direct,arg0,arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + dep dbank,15,8,ret0 ! \ + INC_KPC_2 ! \ + add yreg,ret0,arg0 /* don't change this instr */ + /* or add any after */ + /* to preserve ret0 & arg0 */ + + +/* cycle calc: if yreg is 16bit or carry into 2nd byte, inc cycle */ +/* So, if y==16bit, add 1. If x==8bit, add 1 if carry */ +get_dloc_ind_y_rd_8 + stw link,STACK_SAVE_OP_LINK(sp) + GET_DLOC_IND_Y_WR_SPECIAL() + xor arg0,ret0,scratch1 + extru,= psr,27,1,0 + extru,= scratch1,23,8,0 + CYCLES_PLUS_1 + b get_mem_long_8 + ldw STACK_SAVE_OP_LINK(sp),link + +get_dloc_ind_y_rd_16 + stw link,STACK_SAVE_OP_LINK(sp) + GET_DLOC_IND_Y_WR_SPECIAL() + xor arg0,ret0,scratch1 + extru,= psr,27,1,0 + extru,= scratch1,23,8,0 + CYCLES_PLUS_1 + b get_mem_long_16 + ldw STACK_SAVE_OP_LINK(sp),link + + + +#endif /* ASM */ + diff --git a/kegs/Src/openalasync_snddriver.cpp b/kegs/Src/openalasync_snddriver.cpp new file mode 100644 index 0000000..746e3a7 --- /dev/null +++ b/kegs/Src/openalasync_snddriver.cpp @@ -0,0 +1,657 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" + +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) +# include +# import +# import +# include +#else +# include "../OpenAL/AL/alc.h" +# include "../OpenAL/AL/al.h" +#endif + +#include "sound.h" + +//extern int g_audio_rate; + +#define AL_NUM_BUFFERS 8 +#define AL_BUFFER_SIZE (SOUND_SHM_SAMP_SIZE*4*2) +ALuint source=0, buffers[AL_NUM_BUFFERS]; +int sndQueues[AL_NUM_BUFFERS]; + +const ALenum format = AL_FORMAT_STEREO16; +unsigned char *al_tmp_buf[AL_NUM_BUFFERS][AL_BUFFER_SIZE]; +ALCdevice *dev=NULL; +ALCcontext *ctx=NULL; + +int nblog = 2000; +//#define SNDLOG(STR,VAL) if (nblog){outputInfo(STR,VAL); nblog--;} +//#define SNDLOG(STR,VAL) if (nblog){printf(STR,VAL); nblog--;} +#define SNDLOG(STR,VAL) + + +// http://www.subfurther.com/blog/?p=602 + +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) +typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq); + + +ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq) +{ + + static alBufferDataStaticProcPtr proc = NULL; + + if (proc == NULL) { + proc = (alBufferDataStaticProcPtr) alGetProcAddress((const ALCchar*) "alBufferDataStatic"); + } + + if (proc) + proc(bid, format, data, size, freq); + + return; +} +#endif + +void resetQueues() +{ + + for(int i=0;i 0)) + { + if(l_DataBuffer == NULL) + { + printf("*** DataBuffer NULL!!! *** \n"); + } + // grab a buffer ID from openAL + alGenBuffers(1, (ALuint*)&sound.m_BufferId); + + ALenum l_error = alGetError(); + + if(l_error != AL_NO_ERROR) + { + printf("**** OpenAL ERROR buffer%i\n", l_error); + return sound; + } + else + { + printf("**** OpenAL OK buffer %i\n", sound.m_BufferId); + } + + ALuint f; + if (sound.depth==16) + { + if (sound.nbchannel == 1) + f = AL_FORMAT_MONO16; + else + f = AL_FORMAT_STEREO16; + } + else + { + if (sound.nbchannel == 1) + f = AL_FORMAT_MONO8; + else + f = AL_FORMAT_STEREO8; + + } + + + alBufferData(sound.m_BufferId, f, l_DataBuffer, l_FileSize, sound.frequency); + + l_error = alGetError(); + if(l_error != AL_NO_ERROR) + { + printf("**** OpenAL ERROR format\n"); + return sound; + } + + // create Source + alGenSources(1, (ALuint*)&sound.m_SourceId); + l_error = alGetError(); + if(l_error != AL_NO_ERROR) + { + printf("**** OpenAL ERROR source\n"); + return sound; + } + + alSourcei(sound.m_SourceId, AL_BUFFER, sound.m_BufferId); + + l_error = alGetError(); + if(l_error != AL_NO_ERROR) + { + printf("**** OpenAL ERROR source buffer\n"); + return sound; + } + + // if loop: + //alSourcei(m_SourceId, AL_LOOPING, AL_TRUE); + + alSourcef(sound.m_SourceId, AL_PITCH, 1.0f); + //l_error = alGetError(); + + //ASSERTC(l_error == AL_NO_ERROR,"**** OpenAL ERROR buffer\n"); + //if(l_error != AL_NO_ERROR) + //{ + // CONSOLEMSG("**** OpenAL ERROR properties\n"); + // return FAILURE; + //} + + alSourcef(sound.m_SourceId, AL_GAIN, 1.0f); + + l_error = alGetError(); + + if(l_error != AL_NO_ERROR) + { + printf("**** OpenAL ERROR properties\n"); + return sound; + } + } + else + { + return sound; + } + + if (l_DataBuffer) + { + free(l_DataBuffer); + l_DataBuffer = NULL; + } + + //printf("**** OpenAL Resource load SUCCESS\n"); + sound.successfullyLoaded = 1; + return sound; +} + +int async_release_wav(OASound* _pSound) +{ + if (!_pSound) + return 0; + + + if(_pSound->m_SourceId) + { + + alDeleteSources(1, (ALuint*)&_pSound->m_SourceId); + _pSound->m_SourceId = 0; + + } + if(_pSound->m_BufferId) + { + alDeleteBuffers(1, (ALuint*)&_pSound->m_BufferId); + _pSound->m_BufferId = 0; + } + _pSound->successfullyLoaded=0; + return 1; +} + + +// **************************************************************************** +// +// **************************************************************************** +int async_play_wav(OASound* _pSound, int _Loop, float _Attenuation, float _StartAt ) +{ + if (!_pSound) + return 0; + + if (!_pSound->successfullyLoaded) + return 0; + + + if(!_pSound->m_SourceId) + return 0; + + + alSourcePlay(_pSound->m_SourceId); + + int l_error = alGetError(); + + if(l_error != AL_NO_ERROR) + { + printf("**** OpenAL ERROR play %i\n", l_error); + } + + return 1; +} + +// **************************************************************************** +// +// **************************************************************************** +int async_stop_wav(OASound* _pSound) +{ + if (!_pSound) + return 0; + + if (!_pSound->successfullyLoaded) + return 0; + + if(!_pSound->m_SourceId) + return 0; + + + alSourceStop(_pSound->m_SourceId); + return 1; +} + +void x_play_sound(enum_sound _hSound) +{ + + async_play_wav(&g_system_sounds[_hSound].sound,0,0,0); + +} + +int x_is_sound_playing(enum_sound _hSound) +{ + OASound& sound = g_system_sounds[_hSound].sound; + if (sound.m_SourceId==0) + return 0; + ALint val; + alGetSourcei(sound.m_SourceId, AL_SOURCE_STATE, &val); + return (val == AL_PLAYING); +} + + +#if 1 + +/* + * Struct to hold fmt subchunk data for WAVE files. + */ +struct WAVE_Format { + char subChunkID[4]; + long subChunkSize; + short audioFormat; + short numChannels; + long sampleRate; + long byteRate; + short blockAlign; + short bitsPerSample; +}; + +/* + * Struct to hold the data of the wave file + */ +struct WAVE_Data { + char subChunkID[4]; //should contain the word data + long subChunk2Size; //Stores the size of the data block +}; + +struct RIFF_Header { + char chunkID[4]; + long chunkSize;//size not including chunkSize or chunkID + char format[4]; +}; + +bool loadWavFile(const char* filename, unsigned char** buffer, + unsigned int* size, int* frequency, + int* depth,int* nbchannel) { + //Local Declarations + FILE* soundFile = NULL; + WAVE_Format wave_format; + RIFF_Header riff_header; + WAVE_Data wave_data; + unsigned char* data; + + + soundFile = fopen(filename, "rb"); + if (!soundFile) + { + printf("could not open %s\n",filename); + return false; + } + + // Read in the first chunk into the struct + fread(&riff_header, sizeof(RIFF_Header), 1, soundFile); + + //check for RIFF and WAVE tag in memeory + if ((riff_header.chunkID[0] != 'R' || + riff_header.chunkID[1] != 'I' || + riff_header.chunkID[2] != 'F' || + riff_header.chunkID[3] != 'F') || + (riff_header.format[0] != 'W' || + riff_header.format[1] != 'A' || + riff_header.format[2] != 'V' || + riff_header.format[3] != 'E')) + { + fclose(soundFile); + printf ("Invalid RIFF or WAVE Header in %s\n",filename); + return false; + } + + //Read in the 2nd chunk for the wave info + fread(&wave_format, sizeof(WAVE_Format), 1, soundFile); + //check for fmt tag in memory + if (wave_format.subChunkID[0] != 'f' || + wave_format.subChunkID[1] != 'm' || + wave_format.subChunkID[2] != 't' || + wave_format.subChunkID[3] != ' ') + { + fclose(soundFile); + printf ("Invalid Wave Format"); + return false; + } + + + //check for extra parameters; + if (wave_format.subChunkSize > 16) + fseek(soundFile, sizeof(short), SEEK_CUR); + + //Read in the the last byte of data before the sound file + fread(&wave_data, sizeof(WAVE_Data), 1, soundFile); + //check for data tag in memory + if (wave_data.subChunkID[0] != 'd' || + wave_data.subChunkID[1] != 'a' || + wave_data.subChunkID[2] != 't' || + wave_data.subChunkID[3] != 'a') + { + + fclose(soundFile); + printf ( "Invalid data header"); + return false; + } + + //Allocate memory for data + data = (unsigned char*)malloc(wave_data.subChunk2Size); + + // Read in the sound data into the soundData variable + if (!fread(data, wave_data.subChunk2Size, 1, soundFile)) + { + free(data); + fclose(soundFile); + printf ( "error loading WAVE data into struct!"); + return false; + } + + //Now we set the variables that we passed in with the + //data from the structs + *size = wave_data.subChunk2Size; + *frequency = wave_format.sampleRate; + *nbchannel = wave_format.numChannels ; + *depth = wave_format.bitsPerSample; + *buffer = data; + fclose(soundFile); + return true; + } + +bool x_load_wav(const char* _Path, unsigned char** _outDataBuffer, unsigned int & _outFileSize, OASound & _sound ) +{ + + return loadWavFile(_Path,_outDataBuffer,&_outFileSize,&_sound.frequency,&_sound.depth,&_sound.nbchannel); + } + +#endif diff --git a/kegs/Src/paddles.cpp b/kegs/Src/paddles.cpp new file mode 100644 index 0000000..7d7357c --- /dev/null +++ b/kegs/Src/paddles.cpp @@ -0,0 +1,221 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "adb.h" +#include "moremem.h" +#include "paddles.h" +#include "sim65816.h" + +s_paddles g_paddles; + +int g_invert_paddles = 0; +int g_swap_paddles = 0; + +int g_joystick_type = JOYSTICK_TYPE_NATIVE_1; // OG Trying to set native joystick as default +int g_joystick_native_type1 = -1; +int g_joystick_native_type2 = -1; +int g_joystick_native_type = -1; + + +void +paddle_fixup_joystick_type() +{ + /* If g_paddles.g_joystick_type points to an illegal value, change it */ + if(g_joystick_type == JOYSTICK_TYPE_NATIVE_1) { + g_joystick_native_type = g_joystick_native_type1; + if(g_joystick_native_type1 < 0) { + g_joystick_type = JOYSTICK_TYPE_KEYPAD; + printf("no joy 1 --- switching to keypad\n"); + } + } + if(g_joystick_type == JOYSTICK_TYPE_NATIVE_2) { + g_joystick_native_type = g_joystick_native_type2; + if(g_joystick_native_type2 < 0) { + g_joystick_type = JOYSTICK_TYPE_KEYPAD; + printf("no joy 2 --- switching to keypad\n"); + } + } +} + +void +paddle_trigger(double dcycs) +{ + /* Called by read/write to $c070 */ + g_paddles.g_paddle_trig_dcycs = dcycs; + + /* Determine what all the paddle values are right now */ + paddle_fixup_joystick_type(); + + switch(g_joystick_type) { + case JOYSTICK_TYPE_KEYPAD: /* Keypad Joystick */ + paddle_trigger_keypad(dcycs); + break; + case JOYSTICK_TYPE_MOUSE: /* Mouse Joystick */ + paddle_trigger_mouse(dcycs); + break; + case JOYSTICK_TYPE_NONE: /* None Joystick */ + paddle_trigger_none(dcycs); + break; +#if defined(DRIVER_IOS) && defined(ACTIVEGS) && !defined(ACTIVEGSKARATEKA) + case JOYSTICK_TYPE_ICADE: /* Mouse Joystick */ + { + extern void paddle_trigger_icade(double); + paddle_trigger_icade(dcycs); + } + break; +#endif + default: + joystick_update(dcycs); + } +} + +void +paddle_trigger_mouse(double dcycs) +{ + int val_x, val_y; + int mouse_x, mouse_y; + + val_x = 0; + + mouse_x = g_adb.g_mouse_raw_x; + mouse_y = g_adb.g_mouse_raw_y; + /* mous_phys_x is 0->560, convert that to -32768 to + 32767 cyc */ + /* So subtract 280 then mult by 117 */ + val_x = (mouse_x - 280) * 117; + + /* mous_phys_y is 0->384, convert that to -32768 to + 32767 cyc */ + /* so subtract 192 then mult by 180 to overscale it a bit */ + val_y = (mouse_y - 192) * 180; + + g_paddles.g_paddle_val[0] = val_x; + g_paddles.g_paddle_val[1] = val_y; + g_paddles.g_paddle_val[2] = 32767; + g_paddles.g_paddle_val[3] = 32767; + g_moremem.g_paddle_buttons |= 0xc; + paddle_update_trigger_dcycs(dcycs); +} + +void +paddle_trigger_none(double dcycs) +{ + g_paddles.g_paddle_val[0] = 32767; + g_paddles.g_paddle_val[1] = 32767; + g_paddles.g_paddle_val[2] = 32767; + g_paddles.g_paddle_val[3] = 32767; + g_moremem.g_paddle_buttons |= 0xc; + paddle_update_trigger_dcycs(dcycs); +} + +void +paddle_trigger_keypad(double dcycs) +{ + int get_y; + int val_x, val_y; + + val_x = adb_get_keypad_xy(get_y=0); + val_y = adb_get_keypad_xy(get_y=1); + /* val_x and val_y are already scale -32768 to +32768 */ + + g_paddles.g_paddle_val[0] = val_x; + g_paddles.g_paddle_val[1] = val_y; + g_paddles.g_paddle_val[2] = 32767; + g_paddles.g_paddle_val[3] = 32767; + g_moremem.g_paddle_buttons |= 0xc; + paddle_update_trigger_dcycs(dcycs); +} + +void +paddle_update_trigger_dcycs(double dcycs) +{ + double trig_dcycs; + int val; + int paddle_num; + int scale, trim; + int i; + + for(i = 0; i < 4; i++) { + paddle_num = i; + if(g_swap_paddles) { + paddle_num = i ^ 1; + } + val = g_paddles.g_paddle_val[paddle_num]; + if(g_invert_paddles) { + val = -val; + } + + /* convert -32768 to +32768 into 0->2816.0 cycles (the */ + /* paddle delay const) */ + /* First multiply by the scale factor to adjust range */ + if(paddle_num & 1) { + scale = g_paddles.g_joystick_scale_factor_y; + trim = g_paddles.g_joystick_trim_amount_y; + } else { + scale = g_paddles.g_joystick_scale_factor_x; + trim = g_paddles.g_joystick_trim_amount_x; + } +#if 0 + if(i == 0) { + printf("val was %04x(%d) * scale %03x = %d\n", + val, val, scale, (val*scale)>>16); + } +#endif + val = val * scale >> 16; + /* Val is now from -128 to + 128 since scale is */ + /* 256=1.0, 128 = 0.5 */ + val = val + 128 + trim; + if(val >= 255) { + val = 280; /* increase range */ + } + + + // OG Try to make the joystick up and running, even at fast speed (this might be turned into a user option?) + { + double facteur = 11.04; + + if (g_sim65816.g_speed_fast) + { + if (g_sim65816.get_limit_speed() == SPEED_ZIP) + facteur /= g_sim65816.g_zip_pmhz / 2.6; + else + if (g_sim65816.get_limit_speed() == SPEED_UNLIMITED) + facteur /= g_sim65816.g_projected_pmhz / 2.6; + } + else + { + // OG Hack to make the Joystick works with Miniprix (to investigate why it is needed...) + if (g_sim65816.engine.kpc == 0x5A02) + facteur /= 2.6; + } + + /* convert 0->255 into 0->2816.0 cycles (the paddle delay const) */ + trig_dcycs = dcycs + (val * facteur); + // trig_dcycs = dcycs + (val * 11.04); + g_paddles.g_paddle_dcycs[i] = trig_dcycs; + } + } +} + +int +read_paddles(double dcycs, int paddle) +{ + double trig_dcycs; + + trig_dcycs = g_paddles.g_paddle_dcycs[paddle & 3]; + + if(dcycs < trig_dcycs) { + return 0x80; + } else { + return 0x00; + } +} + +void +paddle_update_buttons() +{ + paddle_fixup_joystick_type(); + joystick_update_buttons(); +} diff --git a/kegs/Src/paddles.h b/kegs/Src/paddles.h new file mode 100644 index 0000000..d9bd220 --- /dev/null +++ b/kegs/Src/paddles.h @@ -0,0 +1,63 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +// OG Added define for joystick +#define JOYSTICK_TYPE_KEYPAD 1000 +#define JOYSTICK_TYPE_MOUSE 1001 +#define JOYSTICK_TYPE_NATIVE_1 1002 +#define JOYSTICK_TYPE_NATIVE_2 1003 +#define JOYSTICK_TYPE_NONE 1004 // OG Added Joystick None +#define JOYSTICK_TYPE_ICADE 1005 // OG Added Joystick Icade + +//#define NB_JOYSTICK_TYPE 5 +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +class s_paddles : public serialized +{ +public: + + + double g_paddle_trig_dcycs; + + int g_joystick_scale_factor_x ; + int g_joystick_scale_factor_y ; + int g_joystick_trim_amount_x ; + int g_joystick_trim_amount_y ; + + + int g_paddle_val[4] ; + /* g_paddle_val[0]: Joystick X coord, [1]:Y coord */ + + double g_paddle_dcycs[4] ; + /* g_paddle_dcycs are the dcycs the paddle goes to 0 */ + + s_paddles() + { + INIT_SERIALIZED(); + + g_joystick_scale_factor_x = 0x100; + g_joystick_scale_factor_y = 0x100; + + } + + DEFAULT_SERIALIZE_IN_OUT ; + +} XCODE_PRAGMA_PACK; + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +extern s_paddles g_paddles; + +extern int g_joystick_type ; // OG Trying to set native joystick as default +extern int g_joystick_native_type1; +extern int g_joystick_native_type2; +extern int g_joystick_native_type ; diff --git a/kegs/Src/prodos.h b/kegs/Src/prodos.h new file mode 100644 index 0000000..c4165b6 --- /dev/null +++ b/kegs/Src/prodos.h @@ -0,0 +1,109 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_C +const char rcsid_defc_h[] = "@(#)$Id: prodos.h,v 1.4 2002/11/19 07:49:31 kadickey Exp $"; +#endif + + +typedef struct l2byte_st L2byte; +struct l2byte_st { + byte low; + byte hi; +}; + +typedef struct l3byte_st L3byte; +struct l3byte_st { + byte low; + byte hi; + byte higher; +}; + +typedef L2byte Block; + +typedef struct pro_time_st Pro_time; +struct pro_time_st { + byte times[4]; +}; + +typedef struct file_entry_st File_entry; +struct file_entry_st { + byte storage_type_name_len; + byte file_name[15]; +/* 0x10 */ + byte file_type; + Block key_pointer; +/* 0x13 */ + L2byte blocks_used; +/* 0x15 */ + L3byte eof; +/* 0x18 */ + Pro_time creation_time; +/* 0x1c */ + byte version; + byte min_version; +/* 0x1e */ + byte access; +/* 0x1f */ + L2byte aux_type; +/* 0x21 */ + Pro_time last_mod; +/* 0x25 */ + Block header_pointer; +}; + +STRUCT(Vol_hdr) { +/* 0x4 */ + byte storage_type_name_len; +/* 0x5 */ + byte vol_name[15]; +/* 0x14 */ + byte res1[8]; +/* 0x1c */ + Pro_time creation_time; +/* 0x20 */ + byte version; + byte min_version; + byte access; + byte entry_length; +/* 0x24 */ + byte entries_per_block; + L2byte file_count; +/* 0x27 */ + Block bit_map; +/* 0x29 */ + L2byte total_blocks; +}; + +typedef struct directory_st Directory; +struct directory_st { + Block prev_blk; + Block next_blk; + File_entry file_entries[13]; +}; + +STRUCT(ProDisk) { + int fd; + int total_blocks; + int size_bitmap_blocks; + int disk_bytes_left; + + int bitmap_bytes; + int bitmap_cur_pos; + byte *bitmap_ptr; + + int file_open; + File_entry *file_ptr; + int dir_blk_num; + int ind_blk_num; + int master_ind_blk_num; + byte dir_blk_data[512]; + byte ind_blk_data[512]; + byte master_ind_blk_data[512]; +}; + + +#include "prodos_protos.h" diff --git a/kegs/Src/prodos_protos.h b/kegs/Src/prodos_protos.h new file mode 100644 index 0000000..99b4e0d --- /dev/null +++ b/kegs/Src/prodos_protos.h @@ -0,0 +1,36 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +void flush_disk(ProDisk *disk); +void close_file(ProDisk *disk); +ProDisk *allocate_memdisk(char *out_name, int size); +void format_memdisk(ProDisk *ptr, char *name); +void disk_write_data(ProDisk *disk, int blk_num, byte *buf, int size); +void disk_read_data(ProDisk *disk, int blk_num, byte *buf, int size); +Directory *disk_read_dir(ProDisk *disk, int blk_num); +void disk_write_dir(ProDisk *disk, int blk_num); +void create_new_file(ProDisk *disk, int dir_block, int storage_type, + char *name, int file_type, word32 creation_time, int version, + int min_version, int access, int aux_type, word32 last_mod, word32 eof); +int pro_write_file(ProDisk *disk, byte *in_buf, int pos, int size); +int get_disk_block(ProDisk *disk, int pos, int create); +void get_new_ind_block(ProDisk *disk); +void write_ind_block(ProDisk *disk); +void get_new_master_ind_block(ProDisk *disk); +void write_master_ind_block(ProDisk *disk); +int find_next_free_block(ProDisk *disk); +void set_bitmap_used(byte *ptr, int i); +void set_bitmap_free(byte *ptr, int i); +void set_file_entry(File_entry *entry, int storage_type_name_len, + char *file_name, int file_type, int key_pointer, int blocks_used, + int eof, word32 creation, int version, int min_version, int access, + int aux_type, word32 last_mod, int header_pointer); +void set_l2byte(L2byte *ptr, int val); +void set_l3byte(L3byte *ptr, int val); +void set_pro_time(Pro_time *ptr, word32 val); +int get_l2byte(L2byte *ptr); +int get_l3byte(L3byte *ptr); +void inc_l2byte(L2byte *ptr); diff --git a/kegs/Src/protos.h b/kegs/Src/protos.h new file mode 100644 index 0000000..264b125 --- /dev/null +++ b/kegs/Src/protos.h @@ -0,0 +1,465 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_C +const char rcsid_protos_h[] = "@(#)$KmKId: protos.h,v 1.188 2004-12-06 19:08:34-05 kentd Exp $"; +#endif + +/* xdriver.c and macdriver.c and windriver.c */ +int x_show_alert(int is_fatal, const char *str); +int win_nonblock_read_stdin(int fd, char *bufptr, int len); +void x_dialog_create_kegs_conf(const char *str); +void update_color_array(int col_num, int a2_color); +void set_border_color(int val); +void x_update_physical_colormap(void); +void x_show_color_array(void); +void x_auto_repeat_on(int must); +void install_text_colormap(void); +void set_border_color(int val); +void draw_status(int line_num, const char *string1); +void x_video_shut(void); +void x_video_init(void); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void redraw_border(void); +void check_input_events(void); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(); +void x_hide_pointer(int); +void x_get_kimage(Kimage *kimage_ptr); +void x_full_screen(int do_full); + +/* test65.c */ +void do_gen_test(int got_num, int base_seed); + + +/* engine.s and engine_c.c */ +void fixed_memory_ptrs_init(); +void fixed_memory_ptrs_shut(); // OG Added shut to smoothly free up allocated memory +word32 get_itimer(void); + +word32 get_memory_c(word32 addr, int cycs); +word32 get_memory16_c(word32 addr, int cycs); +word32 get_memory24_c(word32 addr, int cycs); + +int get_memory_asm(word32 addr, int cycs); +int get_memory16_asm(word32 addr, int cycs); +int get_memory16_asm_fail(word32 addr, int cycs); +int get_memory_act_stub_asm(word32 addr, int cycs); +int get_memory16_act_stub_asm(word32 addr, int cycs); + +void set_memory_c(word32 addr, word32 val, int cycs); +void set_memory16_c(word32 addr, word32 val, int cycs); +void set_memory24_c(word32 addr, word32 val, int cycs); + +int enter_engine(Engine_reg *ptr); +void clr_halt_act(void); +void set_halt_act(int val); + +/* special scc_macdriver.c prototypes */ +int scc_serial_mac_init(int port); +void scc_serial_mac_change_params(int port); +void scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs); +void scc_serial_mac_empty_writebuf(int port); + +/* special scc_windriver.c prototypes */ +int scc_serial_win_init(int port); +void scc_serial_win_change_params(int port); +void scc_serial_win_fill_readbuf(int port, int space_left, double dcycs); +void scc_serial_win_empty_writebuf(int port); + +/* special joystick_driver.c prototypes */ +void joystick_init(void); +void joystick_update(double dcycs); +void joystick_update_buttons(void); + + +/* END_HDR */ + +/* adb.c */ +void adb_init(void); +void adb_shut(); // OG Added adb_shut() +void adb_reset(void); +void adb_log(word32 addr, int val); +void show_adb_log(void); +void adb_error(void); +void adb_add_kbd_srq(void); +void adb_clear_kbd_srq(void); +void adb_add_data_int(void); +void adb_add_mouse_int(void); +void adb_clear_data_int(void); +void adb_clear_mouse_int(void); +void adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2); +void adb_send_1byte(word32 val); +void adb_response_packet(int num_bytes, word32 val); +void adb_kbd_reg0_data(int a2code, int is_up); +void adb_kbd_talk_reg0(void); +void adb_set_config(word32 val0, word32 val1, word32 val2); +void adb_set_new_mode(word32 val); +int adb_read_c026(void); +void adb_write_c026(int val); +void do_adb_cmd(void); +int adb_read_c027(void); +void adb_write_c027(int val); +int read_adb_ram(word32 addr); +void write_adb_ram(word32 addr, int val); +int adb_get_keypad_xy(int get_y); +int update_mouse(int x, int y, int button_states, int buttons_valid); +int mouse_read_c024(double dcycs); +void mouse_compress_fifo(double dcycs); +void adb_key_event(int a2code, int is_up); +word32 adb_read_c000(void); +word32 adb_access_c010(void); +word32 adb_read_c025(void); +int adb_is_cmd_key_down(void); +int adb_is_option_key_down(void); +void adb_increment_speed(void); +void adb_physical_key_update(int a2code, int is_up); +void adb_virtual_key_update(int a2code, int is_up); +void adb_all_keys_up(void); +void adb_kbd_repeat_off(void); + + +/* clock.c */ +double get_dtime(void); +int micro_sleep(double dtime); +void clk_bram_zero(void); +void clk_bram_set(int bram_num, int offset, int val); +void clk_setup_bram_version(void); +void clk_write_bram(FILE *fconf); +void update_cur_time(void); +void clock_update(void); +void clock_update_if_needed(void); +void clock_write_c034(word32 val); +void do_clock_data(void); + + +/* compile_time.c */ + + + + +/* dis.c */ +int get_num(void); +void debugger_help(void); +void do_debug_intfc(void); +word32 dis_get_memory_ptr(word32 addr); +void show_one_toolset(FILE *toolfile, int toolnum, word32 addr); +void show_toolset_tables(word32 a2bank, word32 addr); + + +enum mode_breakpoint + { + BRK_DISABLED=0, + BRK_X = 1, + BRK_READ=2, + BRK_WRITE=4, + BRK_PATCH=8, + BRK_STOP=16, + BRK_SLOWSPEED=32, + BRK_DEFAULTSPEED=64, + BRK_MESSAGE=128, + BRK_ALL = BRK_STOP|BRK_X|BRK_READ|BRK_WRITE + }; + + +void set_bp(word32 _addr,enum mode_breakpoint _mode,const char* _patch,const char* _check); +void show_bp(void); +void delete_bp(word32 addr); +void do_blank(void); +void do_go(void); +void do_step(void); +void xam_mem(int count); +void show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count); +int read_line(char *buf, int len); +void do_debug_list(void); +void dis_do_memmove(void); +void dis_do_pattern_search(void); +void dis_do_compare(void); +void do_debug_unix(void); +void do_debug_load(void); +int do_dis(FILE *outfile, word32 kpc, int accsize, int xsize, int op_provided, word32 instr); +void show_line(FILE *outfile, word32 kaddr, word32 operand, int size, char *string); +void halt_printf(const char *fmt, ...); +void halt2_printf(const char *fmt, ...); + + +/* scc.c */ +void scc_init(void); +void scc_reset(void); +void scc_hard_reset_port(int port); +void scc_reset_port(int port); +void scc_regen_clocks(int port); +void scc_port_init(int port); +void scc_try_to_empty_writebuf(int port, double dcycs); +void scc_try_fill_readbuf(int port, double dcycs); +void scc_update(double dcycs); +void do_scc_event(int type, double dcycs); +void show_scc_state(void); +void scc_log(int regnum, word32 val, double dcycs); +void show_scc_log(void); +word32 scc_read_reg(int port, double dcycs); +void scc_write_reg(int port, word32 val, double dcycs); +void scc_maybe_br_event(int port, double dcycs); +void scc_evaluate_ints(int port); +void scc_maybe_rx_event(int port, double dcycs); +void scc_maybe_rx_int(int port, double dcycs); +void scc_clr_rx_int(int port); +void scc_handle_tx_event(int port, double dcycs); +void scc_maybe_tx_event(int port, double dcycs); +void scc_clr_tx_int(int port); +void scc_set_zerocnt_int(int port); +void scc_clr_zerocnt_int(int port); +void scc_add_to_readbuf(int port, word32 val, double dcycs); +void scc_add_to_readbufv(int port, double dcycs, const char *fmt, ...); +void scc_transmit(int port, word32 val, double dcycs); +void scc_add_to_writebuf(int port, word32 val, double dcycs); +word32 scc_read_data(int port, double dcycs); +void scc_write_data(int port, word32 val, double dcycs); + + +/* scc_socket_driver.c */ +void scc_socket_init(int port); +void scc_socket_maybe_open_incoming(int port, double dcycs); +void scc_socket_open_outgoing(int port, double dcycs); +void scc_socket_make_nonblock(int port, double dcycs); +void scc_socket_change_params(int port); +void scc_socket_close(int port, int full_close, double dcycs); +void scc_accept_socket(int port, double dcycs); +void scc_socket_telnet_reqs(int port, double dcycs); +void scc_socket_fill_readbuf(int port, int space_left, double dcycs); +void scc_socket_recvd_char(int port, int c, double dcycs); +void scc_socket_empty_writebuf(int port, double dcycs); +void scc_socket_modem_write(int port, int c, double dcycs); +void scc_socket_do_cmd_str(int port, double dcycs); +void scc_socket_send_modem_code(int port, int code, double dcycs); +void scc_socket_modem_hangup(int port, double dcycs); +void scc_socket_modem_connect(int port, double dcycs); +void scc_socket_modem_do_ring(int port, double dcycs); +void scc_socket_do_answer(int port, double dcycs); + + +/* scc_windriver.c */ + + +/* scc_macdriver.c */ + + +/* iwm.c */ + + +/* joystick_driver.c */ + + +/* moremem.c */ +void moremem_init(); // OG Added moremem_init() +void fixup_brks(void); +void fixup_hires_on(void); +void fixup_bank0_2000_4000(void); +void fixup_bank0_0400_0800(void); +void fixup_any_bank_any_page(int start_page, int num_pages, byte *mem0rd, byte *mem0wr); +void fixup_intcx(void); +void fixup_wrdefram(int new_wrdefram); +void fixup_st80col(double dcycs); +void fixup_altzp(void); +void fixup_page2(double dcycs); +void fixup_ramrd(void); +void fixup_ramwrt(void); +void fixup_lcbank2(void); +void fixup_rdrom(void); +void set_statereg(double dcycs, int val); +void fixup_shadow_txt1(void); +void fixup_shadow_txt2(void); +void fixup_shadow_hires1(void); +void fixup_shadow_hires2(void); +void fixup_shadow_shr(void); +void fixup_shadow_iolc(void); +void update_shadow_reg(int val); +void fixup_shadow_all_banks(void); +void setup_pageinfo(void); +void show_bankptrs_bank0rdwr(void); +void show_bankptrs(int bnk); +void show_addr(byte *ptr); +int io_read(word32 loc, double *cyc_ptr); +void io_write(word32 loc, int val, double *cyc_ptr); +word32 get_lines_since_vbl(double dcycs); +int in_vblank(double dcycs); +int read_vid_counters(int loc, double dcycs); + + +/* paddles.c */ +void paddle_fixup_joystick_type(void); +void paddle_trigger(double dcycs); +void paddle_trigger_mouse(double dcycs); +void paddle_trigger_none(double dcycs); +void paddle_trigger_keypad(double dcycs); +void paddle_update_trigger_dcycs(double dcycs); +int read_paddles(double dcycs, int paddle); +void paddle_update_buttons(void); + + +/* sim65816.c */ +void show_pc_log(void); +word32 toolbox_debug_4byte(word32 addr); +void toolbox_debug_c(word32 xreg, word32 stack, double *cyc_ptr); +void show_toolbox_log(void); +word32 get_memory_io(word32 loc, double *cyc_ptr); +void set_memory_io(word32 loc, int val, double *cyc_ptr); +void show_regs_act(Engine_reg *eptr); +void show_regs(void); +void my_exit(int ret); +void do_reset(void); +void check_engine_asm_defines(void); +byte *memalloc_align(int size, int skip_amt, void **alloc_ptr); +void memory_ptr_init(void); +void memory_ptr_shut(void); // OG Added shut +int kegsmain(int argc, char **argv); +void load_roms_init_memory(void); +void load_roms_shut_memory(void); // OG Added shut +void kegs_expand_path(char *out_ptr, const char *in_ptr, int maxlen); +void setup_kegs_file(char *outname, int maxlen, int ok_if_missing, int can_create_file, const char **name_ptr); +void initialize_events(void); +void check_for_one_event_type(int type); +void add_event_entry(double dcycs, int type); +double remove_event_entry(int type); +void add_event_stop(double dcycs); +void add_event_doc(double dcycs, int osc); +void add_event_scc(double dcycs, int type); +void add_event_vbl(void); +void add_event_vid_upd(int line); +double remove_event_doc(int osc); +double remove_event_scc(int type); +void show_all_events(void); +void show_pmhz(void); +void setup_zip_speeds(void); +void run_prog(void); +void add_irq(word32 irq_mask); +void remove_irq(word32 irq_mask); +void take_irq(int is_it_brk); +void show_dtime_array(void); +void update_60hz(double dcycs, double dtime_now); +void do_vbl_int(void); +void do_scan_int(double dcycs, int line); +void check_scan_line_int(double dcycs, int cur_video_line); +void check_for_new_scan_int(double dcycs); +void init_reg(void); +void handle_action(word32 ret); +void do_break(word32 ret); +void do_cop(word32 ret); +void do_wdm(word32 arg); +void do_wai(void); +void do_stp(void); +void size_fail(int val, word32 v1, word32 v2); +int fatal_printf(const char *fmt, ...); +int kegs_vprintf(const char *fmt, va_list ap); +void must_write(int fd, char *bufptr, int len); +void clear_fatal_logs(void); +char *kegs_malloc_str(const char *in_str); + + +/* smartport.c */ +void smartport_error(void); +void smartport_log(word32 start_addr, int cmd, int rts_addr, int cmd_list); +void do_c70d(word32 arg0); +void do_c70a(word32 arg0); +int do_read_c7(int unit_num, word32 buf, int blk); +int do_write_c7(int unit_num, word32 buf, int blk); +int do_format_c7(int unit_num); +void do_c700(word32 ret); + + +/* sound.c */ +void doc_log_rout(char *msg, int osc, double dsamps, int etc); +void show_doc_log(void); +void sound_init(void); +void sound_init_general(void); +void parent_sound_get_sample_rate(int read_fd); +void set_audio_rate(int rate); +void sound_reset(double dcycs); +void sound_shutdown(void); +void sound_update(double dcycs); +void open_sound_file(void); +void close_sound_file(void); +void check_for_range(word32 *addr, int num_samps, int offset); +void send_sound_to_file(word32 *addr, int shm_pos, int num_samps); +void send_sound(int real_samps, int size); +void show_c030_state(void); +void show_c030_samps(int *outptr, int num); +void sound_play(double dsamps); +void doc_handle_event(int osc, double dcycs); +void doc_sound_end(int osc, int can_repeat, double eff_dsamps, double dsamps); +void add_sound_irq(int osc); +void remove_sound_irq(int osc, int must); +void start_sound(int osc, double eff_dsamps, double dsamps); +void wave_end_estimate(int osc, double eff_dsamps, double dsamps); +void remove_sound_event(int osc); +void doc_write_ctl_reg(int osc, int val, double dsamps); +void doc_recalc_sound_parms(int osc, double eff_dcycs, double dsamps); +int doc_read_c030(double dcycs); +int doc_read_c03c(double dcycs); +int doc_read_c03d(double dcycs); +void doc_write_c03c(int val, double dcycs); +void doc_write_c03d(int val, double dcycs); +void doc_show_ensoniq_state(int osc); + + +/* sound_driver.c */ +void reliable_buf_write(word32 *shm_addr, int pos, int size); +void reliable_zero_write(int amt); +void child_sound_loop(int read_fd, int write_fd, word32 *shm_addr); +void child_sound_playit(word32 tmp); + + +/* video.c */ +void video_init(void); +void show_a2_line_stuff(void); +void video_reset(void); +void video_update(void); +int video_all_stat_to_line_stat(int line, int new_all_stat); +int *video_update_kimage_ptr(int line, int new_stat); +void change_a2vid_palette(int new_palette); +void check_a2vid_palette(void); +void change_display_mode(double dcycs); +void video_update_all_stat_through_line(int line); +void change_border_color(double dcycs, int val); +void update_border_info(void); +void update_border_line(int st_line_offset, int end_line_offset, int color); +void video_border_pixel_write(Kimage *kimage_ptr, int starty, int num_lines, word32 val, int st_off, int end_off); +void redraw_changed_text_40(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, int pixels_per_line); +void redraw_changed_text_80(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, int pixels_per_line); +void redraw_changed_gr(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_gr(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_hires(int start_offset, int start_line, int num_lines, int color, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_hires_bw(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_hires_color(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_hires(int start_offset, int start_line, int num_lines, int color, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_hires_bw(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_hires_color(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +int video_rebuild_super_hires_palette(word32 scan_info, int line, int reparse); +void redraw_changed_super_hires(int start_offset, int start_line, int num_lines, int in_reparse, byte *screen_data); +void display_screen(void); +void video_update_event_line(int line); +void video_check_input_events(void); +void video_update_through_line(int line); +void video_refresh_lines(int st_line, int num_lines, int must_reparse); +void refresh_border(void); +void end_screen(void); +void read_a2_font(void); +void video_get_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth); +void video_get_kimages(void); +void video_convert_kimage_depth(Kimage *kim_in, Kimage *kim_out, int startx, int starty, int width, int height); +void video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix, int right_pix); +void video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line, int end_line); +void video_push_border_sides(void); +void video_push_border_special(void); +void video_push_kimages(void); +void video_update_color_raw(int col_num, int a2_color); +void video_update_color_array(int col_num, int a2_color); +void video_update_colormap(void); +void video_update_status_line(int line, const char *string); +void video_show_debug_info(void); +word32 float_bus(double dcycs); + diff --git a/kegs/Src/protos_engine_c.h b/kegs/Src/protos_engine_c.h new file mode 100644 index 0000000..77c2d36 --- /dev/null +++ b/kegs/Src/protos_engine_c.h @@ -0,0 +1,43 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_C +const char rcsid_protos_engine_c_h[] = "@(#)$KmKId: protos_engine_c.h,v 1.11 2004-10-11 22:48:16-04 kentd Exp $"; +#endif + +/* END_HDR */ + +/* engine_c.c */ +void check_breakpoints(word32 addr,enum mode_breakpoint); +word32 get_memory8_io_stub(word32 addr, byte *stat, double *fcycs_ptr, double fplus_x_m1); +word32 get_memory16_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank); +word32 get_memory24_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank); +void set_memory8_io_stub(word32 addr, word32 val, byte *stat, double *fcycs_ptr, double fplus_x_m1); +void set_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, double fplus_1, double fplus_x_m1, int in_bank); +void set_memory24_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank); +word32 get_memory_c(word32 addr, int cycs); +word32 get_memory16_c(word32 addr, int cycs); +word32 get_memory24_c(word32 addr, int cycs); +void set_memory_c(word32 addr, word32 val, int cycs); +void set_memory16_c(word32 addr, word32 val, int cycs); +void set_memory24_c(word32 addr, word32 val, int cycs); +word32 do_adc_sbc8(word32 in1, word32 in2, word32 psr, int sub); +word32 do_adc_sbc16(word32 in1, word32 in2, word32 psr, int sub); +void fixed_memory_ptrs_init(void); +word32 get_itimer(void); +void set_halt_act(int val); +void clr_halt_act(void); +word32 get_remaining_operands(word32 addr, word32 opcode, word32 psr, Fplus *fplus_ptr); +int enter_engine(Engine_reg *engine_ptr); +struct struct_breakpoint +{ + word32 addr; + enum mode_breakpoint mode; + const char* patch; + const char* check; +} ; +extern int g_num_breakpoints; +extern struct_breakpoint g_breakpts[MAX_BREAK_POINTS]; diff --git a/kegs/Src/protos_macdriver.h b/kegs/Src/protos_macdriver.h new file mode 100644 index 0000000..36cbd91 --- /dev/null +++ b/kegs/Src/protos_macdriver.h @@ -0,0 +1,59 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +void show_simple_alert(const char *str1, const char *str2, const char *str3, int num); +void x_dialog_create_kegs_conf(const char *str); +int x_show_alert(int is_fatal, const char *str);void update_window(void); + +//void mac_update_modifiers(word32 state); +void mac_warp_mouse(void); +void check_input_events(void); +void temp_run_application_event_loop(void); +int main(int argc, char *argv[]); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void x_update_physical_colormap(void); +void x_show_color_array(void); + + +void x_get_kimage(Kimage *kimage_ptr); +//void x_dev_video_init(void); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(void); +void x_auto_repeat_on(int must); +void x_auto_repeat_off(int must); +void x_hide_pointer(int do_hide); +void x_full_screen(int do_full); +void update_main_window_size(void); + +#ifndef __EVENTS__ +typedef unsigned short EventModifiers; +enum { + /* modifiers */ + activeFlagBit = 0, /* activate? (activateEvt and mouseDown)*/ + btnStateBit = 7, /* state of button?*/ + cmdKeyBit = 8, /* command key down?*/ + shiftKeyBit = 9, /* shift key down?*/ + alphaLockBit = 10, /* alpha lock down?*/ + optionKeyBit = 11, /* option key down?*/ + controlKeyBit = 12, /* control key down?*/ + rightShiftKeyBit = 13, /* right shift key down? Not supported on Mac OS X.*/ + rightOptionKeyBit = 14, /* right Option key down? Not supported on Mac OS X.*/ + rightControlKeyBit = 15 /* right Control key down? Not supported on Mac OS X.*/ +}; +enum { + activeFlag = 1 << activeFlagBit, + btnState = 1 << btnStateBit, + cmdKey = 1 << cmdKeyBit, + shiftKey = 1 << shiftKeyBit, + alphaLock = 1 << alphaLockBit, + optionKey = 1 << optionKeyBit, + controlKey = 1 << controlKeyBit, + rightShiftKey = 1 << rightShiftKeyBit, /* Not supported on Mac OS X.*/ + rightOptionKey = 1 << rightOptionKeyBit, /* Not supported on Mac OS X.*/ + rightControlKey = 1 << rightControlKeyBit /* Not supported on Mac OS X.*/ +}; +#endif \ No newline at end of file diff --git a/kegs/Src/protos_macsnd_driver.h b/kegs/Src/protos_macsnd_driver.h new file mode 100644 index 0000000..1ccf262 --- /dev/null +++ b/kegs/Src/protos_macsnd_driver.h @@ -0,0 +1,11 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +void mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd); +int mac_send_audio(byte *ptr, int in_size); +void child_sound_init_mac(void); +void macsnd_init(word32 *shmaddr); + diff --git a/kegs/Src/protos_windriver.h b/kegs/Src/protos_windriver.h new file mode 100644 index 0000000..1896e3b --- /dev/null +++ b/kegs/Src/protos_windriver.h @@ -0,0 +1,27 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +int win_update_mouse(int x, int y, int button_states, int buttons_valid); +void win_event_mouse(int umsg,WPARAM wParam, LPARAM lParam); +void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags); +void win_event_quit(HWND hwnd); +void window_needs_full_refresh(); +LRESULT CALLBACK win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); +int main(int argc, char **argv); +void check_input_events(void); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void x_update_physical_colormap(void); +void show_xcolor_array(void); +void x_driver_end(void); +void x_get_kimage(Kimage *kimage_ptr); +//void x_dev_video_init(void); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(void); +void x_auto_repeat_on(int must); +void x_auto_repeat_off(int must); +void x_hide_pointer(int do_hide); + diff --git a/kegs/Src/protos_xdriver.h b/kegs/Src/protos_xdriver.h new file mode 100644 index 0000000..ddf7c19 --- /dev/null +++ b/kegs/Src/protos_xdriver.h @@ -0,0 +1,36 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +int main(int argc, char **argv); +void x_dialog_create_kegs_conf(const char *str); +int x_show_alert(int is_fatal, const char *str); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void x_update_physical_colormap(void); +void x_show_color_array(void); +int my_error_handler(Display *display, XErrorEvent *ev); +void x_driver_end(void); +void show_colormap(char *str, Colormap cmap, int index1, int index2, int index3); +void x_badpipe(int signum); +//void x_dev_video_init(void); +Visual *x_try_find_visual(int depth, int screen_num, XVisualInfo **visual_list_ptr); +void x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int *shift_right_ptr); +int xhandle_shm_error(Display *display, XErrorEvent *event); +void x_get_kimage(Kimage *kimage_ptr); +int get_shm(Kimage *kimage_ptr); +void get_ximage(Kimage *kimage_ptr); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(void); +int x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid); +void check_input_events(void); +void x_hide_pointer(int do_hide); +void handle_keysym(XEvent *xev_in); +int x_keysym_to_a2code(int keysym, int is_up); +void x_update_modifier_state(int state); +void x_auto_repeat_on(int must); +void x_auto_repeat_off(int must); +void x_full_screen(int do_full); + diff --git a/kegs/Src/raster.h b/kegs/Src/raster.h new file mode 100644 index 0000000..7e85399 --- /dev/null +++ b/kegs/Src/raster.h @@ -0,0 +1,19 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + + + #ifdef USE_RASTER + +//#define TEST_RASTER +int getScanLine(); +int x_init_raster(void*); +void x_close_raster(); + int x_wait_for_vbl(); + int x_wait_for_last_refresh(double); +int x_test_raster(); +#endif \ No newline at end of file diff --git a/kegs/Src/scc.cpp b/kegs/Src/scc.cpp new file mode 100644 index 0000000..8d6ef65 --- /dev/null +++ b/kegs/Src/scc.cpp @@ -0,0 +1,1265 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "moremem.h" +#include "sim65816.h" + +#ifdef UNDER_CE +#define vsnprintf _vsnprintf +#endif + + + +/* my scc port 0 == channel A = slot 1 = c039/c03b */ +/* port 1 == channel B = slot 2 = c038/c03a */ + +#include "scc.h" + +s_scc g_scc; + +#define SCC_R14_DPLL_SOURCE_BRG 0x100 +#define SCC_R14_FM_MODE 0x200 + +#define SCC_DCYCS_PER_PCLK ((DCYCS_1_MHZ) / ((DCYCS_28_MHZ) /8)) +#define SCC_DCYCS_PER_XTAL ((DCYCS_1_MHZ) / 3686400.0) + +#define SCC_BR_EVENT 1 +#define SCC_TX_EVENT 2 +#define SCC_RX_EVENT 3 +#define SCC_MAKE_EVENT(port, a) (((a) << 1) + (port)) + +const int g_baud_table[] = { + 110, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 +}; + + +void +scc_init() +{ + Scc *scc_ptr; + int i, j; + + for(i = 0; i < 2; i++) { + scc_ptr = &(g_scc.scc_stat[i]); + scc_ptr->accfd = -1; + scc_ptr->sockfd = -1; + scc_ptr->socket_state = -1; + scc_ptr->rdwrfd = -1; + scc_ptr->state = 0; + scc_ptr->host_handle = 0; + scc_ptr->host_handle2 = 0; + scc_ptr->br_event_pending = 0; + scc_ptr->rx_event_pending = 0; + scc_ptr->tx_event_pending = 0; + scc_ptr->char_size = 8; + scc_ptr->baud_rate = 9600; + scc_ptr->telnet_mode = 0; + scc_ptr->telnet_iac = 0; + scc_ptr->out_char_dcycs = 0.0; + scc_ptr->socket_num_rings = 0; + scc_ptr->socket_last_ring_dcycs = 0; + scc_ptr->modem_mode = 0; + scc_ptr->modem_dial_or_acc_mode = 0; + scc_ptr->modem_plus_mode = 0; + scc_ptr->modem_s0_val = 0; + scc_ptr->modem_cmd_len = 0; + scc_ptr->modem_cmd_str[0] = 0; + for(j = 0; j < 2; j++) { + scc_ptr->telnet_local_mode[j] = 0; + scc_ptr->telnet_remote_mode[j] = 0; + scc_ptr->telnet_reqwill_mode[j] = 0; + scc_ptr->telnet_reqdo_mode[j] = 0; + } + } + + scc_reset(); +} + +void +scc_reset() +{ + Scc *scc_ptr; + int i; + + for(i = 0; i < 2; i++) { + scc_ptr = &(g_scc.scc_stat[i]); + + scc_ptr->port = i; + scc_ptr->mode = 0; + scc_ptr->reg_ptr = 0; + scc_ptr->in_rdptr = 0; + scc_ptr->in_wrptr = 0; + scc_ptr->out_rdptr = 0; + scc_ptr->out_wrptr = 0; + scc_ptr->dcd = 0; + scc_ptr->wantint_rx = 0; + scc_ptr->wantint_tx = 0; + scc_ptr->wantint_zerocnt = 0; + scc_ptr->read_called_this_vbl = 0; + scc_ptr->write_called_this_vbl = 0; + scc_evaluate_ints(i); + scc_hard_reset_port(i); + } +} + +void +scc_hard_reset_port(int port) +{ + Scc *scc_ptr; + + scc_reset_port(port); + + scc_ptr = &(g_scc.scc_stat[port]); + scc_ptr->reg[14] = 0; /* zero bottom two bits */ + scc_ptr->reg[13] = 0; + scc_ptr->reg[12] = 0; + scc_ptr->reg[11] = 0x08; + scc_ptr->reg[10] = 0; + scc_ptr->reg[7] = 0; + scc_ptr->reg[6] = 0; + scc_ptr->reg[5] = 0; + scc_ptr->reg[4] = 0x04; + scc_ptr->reg[3] = 0; + scc_ptr->reg[2] = 0; + scc_ptr->reg[1] = 0; + + /* HACK HACK: */ + g_scc.scc_stat[0].reg[9] = 0; /* Clear all interrupts */ + + scc_evaluate_ints(port); + + scc_regen_clocks(port); +} + +void +scc_reset_port(int port) +{ + Scc *scc_ptr; + + scc_ptr = &(g_scc.scc_stat[port]); + scc_ptr->reg[15] = 0xf8; + scc_ptr->reg[14] &= 0x03; /* 0 most (including >= 0x100) bits */ + scc_ptr->reg[10] = 0; + scc_ptr->reg[5] &= 0x65; /* leave tx bits and sdlc/crc bits */ + scc_ptr->reg[4] |= 0x04; /* Set async mode */ + scc_ptr->reg[3] &= 0xfe; /* clear receiver enable */ + scc_ptr->reg[1] &= 0xfe; /* clear ext int enable */ + + scc_ptr->br_is_zero = 0; + scc_ptr->tx_buf_empty = 1; + + scc_ptr->wantint_rx = 0; + scc_ptr->wantint_tx = 0; + scc_ptr->wantint_zerocnt = 0; + + scc_ptr->rx_queue_depth = 0; + + scc_evaluate_ints(port); + + scc_regen_clocks(port); + + scc_clr_tx_int(port); + scc_clr_rx_int(port); +} + +void +scc_regen_clocks(int port) +{ + Scc *scc_ptr; + double br_dcycs, tx_dcycs, rx_dcycs; + double rx_char_size, tx_char_size; + double clock_mult; + word32 reg4; + word32 reg14; + word32 reg11; + word32 br_const; + word32 baud; + word32 max_diff; + word32 diff; + int state; + int baud_entries; + int pos; + int i; + + /* Always do baud rate generator */ + scc_ptr = &(g_scc.scc_stat[port]); + br_const = (scc_ptr->reg[13] << 8) + scc_ptr->reg[12]; + br_const += 2; /* counts down past 0 */ + + reg4 = scc_ptr->reg[4]; + clock_mult = 1.0; + switch((reg4 >> 6) & 3) { + case 0: /* x1 */ + clock_mult = 1.0; + break; + case 1: /* x16 */ + clock_mult = 16.0; + break; + case 2: /* x32 */ + clock_mult = 32.0; + break; + case 3: /* x64 */ + clock_mult = 64.0; + break; + } + + br_dcycs = 0.01; + reg14 = scc_ptr->reg[14]; + if(reg14 & 0x1) { + br_dcycs = SCC_DCYCS_PER_XTAL; + if(reg14 & 0x2) { + br_dcycs = SCC_DCYCS_PER_PCLK; + } + } + + br_dcycs = br_dcycs * (double)br_const; + + tx_dcycs = 1; + rx_dcycs = 1; + reg11 = scc_ptr->reg[11]; + if(((reg11 >> 3) & 3) == 2) { + tx_dcycs = 2.0 * br_dcycs * clock_mult; + } + if(((reg11 >> 5) & 3) == 2) { + rx_dcycs = 2.0 * br_dcycs * clock_mult; + } + + tx_char_size = 8.0; + switch((scc_ptr->reg[5] >> 5) & 0x3) { + case 0: // 5 bits + tx_char_size = 5.0; + break; + case 1: // 7 bits + tx_char_size = 7.0; + break; + case 2: // 6 bits + tx_char_size = 6.0; + break; + } + + scc_ptr->char_size = (int)tx_char_size; + + switch((scc_ptr->reg[4] >> 2) & 0x3) { + case 1: // 1 stop bit + tx_char_size += 2.0; // 1 stop + 1 start bit + break; + case 2: // 1.5 stop bit + tx_char_size += 2.5; // 1.5 stop + 1 start bit + break; + case 3: // 2 stop bits + tx_char_size += 3.0; // 2.0 stop + 1 start bit + break; + } + + if(scc_ptr->reg[4] & 1) { + // parity enabled + tx_char_size += 1.0; + } + + if(scc_ptr->reg[14] & 0x10) { + /* loopback mode, make it go faster...*/ + rx_char_size = 1.0; + tx_char_size = 1.0; + } + + rx_char_size = tx_char_size; /* HACK */ + + baud = (int)(DCYCS_1_MHZ / tx_dcycs); + max_diff = 5000000; + pos = 0; + baud_entries = sizeof(g_baud_table)/sizeof(g_baud_table[0]); + for(i = 0; i < baud_entries; i++) { + diff = abs((int)(g_baud_table[i] - baud)); + if(diff < max_diff) { + pos = i; + max_diff = diff; + } + } + + scc_ptr->baud_rate = g_baud_table[pos]; + + scc_ptr->br_dcycs = br_dcycs; + scc_ptr->tx_dcycs = tx_dcycs * tx_char_size; + scc_ptr->rx_dcycs = rx_dcycs * rx_char_size; + + state = scc_ptr->state; + if(state == 2) { + /* real serial ports */ +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) + scc_serial_mac_change_params(port); +#endif +#ifdef _WIN32 + scc_serial_win_change_params(port); +#endif + } else { + scc_socket_change_params(port); + } +} + +void +scc_port_init(int port) +{ + int state; + + state = 0; + if(g_sim65816.g_raw_serial) { +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) + state = scc_serial_mac_init(port); +#endif +#ifdef _WIN32 + state = scc_serial_win_init(port); +#endif + } + + if(state <= 0) { + scc_socket_init(port); + } +} + +void +scc_try_to_empty_writebuf(int port, double dcycs) +{ + Scc *scc_ptr; + int state; + + scc_ptr = &(g_scc.scc_stat[port]); + state = scc_ptr->state; + if(scc_ptr->write_called_this_vbl) { + return; + } + + scc_ptr->write_called_this_vbl = 1; + + if(state == 2) { +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) + scc_serial_mac_empty_writebuf(port); +#endif +#if defined(_WIN32) + scc_serial_win_empty_writebuf(port); +#endif + } else if(state == 1) { + scc_socket_empty_writebuf(port, dcycs); + } +} + +void +scc_try_fill_readbuf(int port, double dcycs) +{ + Scc *scc_ptr; + int space_used, space_left; + int state; + + scc_ptr = &(g_scc.scc_stat[port]); + state = scc_ptr->state; + + space_used = scc_ptr->in_wrptr - scc_ptr->in_rdptr; + if(space_used < 0) { + space_used += SCC_INBUF_SIZE; + } + space_left = (7*SCC_INBUF_SIZE/8) - space_used; + if(space_left < 1) { + /* Buffer is pretty full, don't try to get more */ + return; + } + +#if 0 + if(scc_ptr->read_called_this_vbl) { + return; + } +#endif + + scc_ptr->read_called_this_vbl = 1; + + if(state == 2) { +#if defined(DRIVER_IOS) || defined(DRIVER_OSX) + scc_serial_mac_fill_readbuf(port, space_left, dcycs); +#endif +#if defined(_WIN32) + scc_serial_win_fill_readbuf(port, space_left, dcycs); +#endif + } else if(state == 1) { + scc_socket_fill_readbuf(port, space_left, dcycs); + } +} + +void +scc_update(double dcycs) +{ + /* called each VBL update */ + g_scc.scc_stat[0].write_called_this_vbl = 0; + g_scc.scc_stat[1].write_called_this_vbl = 0; + g_scc.scc_stat[0].read_called_this_vbl = 0; + g_scc.scc_stat[1].read_called_this_vbl = 0; + + scc_try_to_empty_writebuf(0, dcycs); + scc_try_to_empty_writebuf(1, dcycs); + scc_try_fill_readbuf(0, dcycs); + scc_try_fill_readbuf(1, dcycs); + + g_scc.scc_stat[0].write_called_this_vbl = 0; + g_scc.scc_stat[1].write_called_this_vbl = 0; + g_scc.scc_stat[0].read_called_this_vbl = 0; + g_scc.scc_stat[1].read_called_this_vbl = 0; +} + +void +do_scc_event(int type, double dcycs) +{ + Scc *scc_ptr; + int port; + + port = type & 1; + type = (type >> 1); + + scc_ptr = &(g_scc.scc_stat[port]); + if(type == SCC_BR_EVENT) { + // printf("SCC_BR_EVENT %d\n",port); + + /* baud rate generator counted down to 0 */ + scc_ptr->br_event_pending = 0; + scc_set_zerocnt_int(port); + scc_maybe_br_event(port, dcycs); + } else if(type == SCC_TX_EVENT) { + // printf("SCC_TX_EVENT %d\n",port); + + scc_ptr->tx_event_pending = 0; + scc_ptr->tx_buf_empty = 1; + scc_handle_tx_event(port, dcycs); + } else if(type == SCC_RX_EVENT) { + // printf("SCC_RX_EVENT %d\n",port); + scc_ptr->rx_event_pending = 0; + scc_maybe_rx_event(port, dcycs); + } else { + halt_printf("do_scc_event: %08x!\n", type); + } + return; +} + +void +show_scc_state() +{ + Scc *scc_ptr; + int i, j; + + for(i = 0; i < 2; i++) { + scc_ptr = &(g_scc.scc_stat[i]); + printf("SCC port: %d\n", i); + for(j = 0; j < 16; j += 4) { + printf("Reg %2d-%2d: %02x %02x %02x %02x\n", j, j+3, + scc_ptr->reg[j], scc_ptr->reg[j+1], + scc_ptr->reg[j+2], scc_ptr->reg[j+3]); + } + printf("state: %d, accfd: %d, rdwrfd: %d, host:%p, host2:%p\n", + scc_ptr->state, scc_ptr->accfd, scc_ptr->rdwrfd, + scc_ptr->host_handle, scc_ptr->host_handle2); + printf("in_rdptr: %04x, in_wr:%04x, out_rd:%04x, out_wr:%04x\n", + scc_ptr->in_rdptr, scc_ptr->in_wrptr, + scc_ptr->out_rdptr, scc_ptr->out_wrptr); + printf("rx_queue_depth: %d, queue: %02x, %02x, %02x, %02x\n", + scc_ptr->rx_queue_depth, scc_ptr->rx_queue[0], + scc_ptr->rx_queue[1], scc_ptr->rx_queue[2], + scc_ptr->rx_queue[3]); + printf("want_ints: rx:%d, tx:%d, zc:%d\n", + scc_ptr->wantint_rx, scc_ptr->wantint_tx, + scc_ptr->wantint_zerocnt); + printf("ev_pendings: rx:%d, tx:%d, br:%d\n", + scc_ptr->rx_event_pending, + scc_ptr->tx_event_pending, + scc_ptr->br_event_pending); + printf("br_dcycs: %f, tx_dcycs: %f, rx_dcycs: %f\n", + scc_ptr->br_dcycs, scc_ptr->tx_dcycs, + scc_ptr->rx_dcycs); + printf("char_size: %d, baud_rate: %d, mode: %d\n", + scc_ptr->char_size, scc_ptr->baud_rate, + scc_ptr->mode); + printf("modem_dial_mode:%d, telnet_mode:%d iac:%d, " + "modem_cmd_len:%d\n", scc_ptr->modem_dial_or_acc_mode, + scc_ptr->telnet_mode, scc_ptr->telnet_iac, + scc_ptr->modem_cmd_len); + printf("telnet_loc_modes:%08x %08x, telnet_rem_motes:" + "%08x %08x\n", scc_ptr->telnet_local_mode[0], + scc_ptr->telnet_local_mode[1], + scc_ptr->telnet_remote_mode[0], + scc_ptr->telnet_remote_mode[1]); + printf("modem_mode:%08x plus_mode: %d, out_char_dcycs: %f\n", + scc_ptr->modem_mode, scc_ptr->modem_plus_mode, + scc_ptr->out_char_dcycs); + } + +} + +#define LEN_SCC_LOG 50 +STRUCT(Scc_log) { + int regnum; + word32 val; + double dcycs; +}; + +Scc_log g_scc_log[LEN_SCC_LOG]; +int g_scc_log_pos = 0; + +#define SCC_REGNUM(wr,port,reg) ((wr << 8) + (port << 4) + reg) + +void +scc_log(int regnum, word32 val, double dcycs) +{ + int pos; + + pos = g_scc_log_pos; + g_scc_log[pos].regnum = regnum; + g_scc_log[pos].val = val; + g_scc_log[pos].dcycs = dcycs; + pos++; + if(pos >= LEN_SCC_LOG) { + pos = 0; + } + g_scc_log_pos = pos; +} + +void +show_scc_log(void) +{ + double dcycs; + int regnum; + int pos; + int i; + + pos = g_scc_log_pos; + dcycs = g_sim65816.g_cur_dcycs; + printf("SCC log pos: %d, cur dcycs:%f\n", pos, dcycs); + for(i = 0; i < LEN_SCC_LOG; i++) { + pos--; + if(pos < 0) { + pos = LEN_SCC_LOG - 1; + } + regnum = g_scc_log[pos].regnum; + printf("%d:%d: port:%d wr:%d reg: %d val:%02x at t:%f\n", + i, pos, (regnum >> 4) & 0xf, (regnum >> 8), + (regnum & 0xf), + g_scc_log[pos].val, + g_scc_log[pos].dcycs - dcycs); + } +} + +word32 +scc_read_reg(int port, double dcycs) +{ + Scc *scc_ptr; + word32 ret; + int regnum; + + scc_ptr = &(g_scc.scc_stat[port]); + scc_ptr->mode = 0; + regnum = scc_ptr->reg_ptr; + + /* port 0 is channel A, port 1 is channel B */ + switch(regnum) { + case 0: + case 4: + ret = 0x60; /* 0x44 = no dcd, no cts,0x6c = dcd ok, cts ok*/ + if(scc_ptr->dcd) { + ret |= 0x08; + } + ret |= 0x8; /* HACK HACK */ + if(scc_ptr->rx_queue_depth) { + ret |= 0x01; + } + if(scc_ptr->tx_buf_empty) { + ret |= 0x04; + } + if(scc_ptr->br_is_zero) { + ret |= 0x02; + } + //printf("Read scc[%d] stat: %f : %02x\n", port, dcycs, ret); + break; + case 1: + case 5: + /* HACK: residue codes not right */ + ret = 0x07; /* all sent */ + break; + case 2: + case 6: + if(port == 0) { + ret = scc_ptr->reg[2]; + } else { + + halt_printf("Read of RR2B...stopping\n"); + ret = 0; +#if 0 + ret = g_scc.scc_stat[0].reg[2]; + wr9 = g_scc.scc_stat[0].reg[9]; + for(i = 0; i < 8; i++) { + if(ZZZ){}; + } + if(wr9 & 0x10) { + /* wr9 status high */ + + } +#endif + } + break; + case 3: + case 7: + if(port == 0) { + ret = (g_moremem.g_irq_pending & 0x3f); + } else { + ret = 0; + } + break; + case 8: + ret = scc_read_data(port, dcycs); + break; + case 9: + case 13: + ret = scc_ptr->reg[13]; + break; + case 10: + case 14: + ret = 0; + break; + case 11: + case 15: + ret = scc_ptr->reg[15]; + break; + case 12: + ret = scc_ptr->reg[12]; + break; + default: + halt_printf("Tried reading c03%x with regnum: %d!\n", 8+port, + regnum); + ret = 0; + } + + scc_ptr->reg_ptr = 0; + scc_printf("Read c03%x, rr%d, ret: %02x\n", 8+port, regnum, ret); + if(regnum != 0 && regnum != 3) { + scc_log(SCC_REGNUM(0,port,regnum), ret, dcycs); + } + + return ret; +} + +void +scc_write_reg(int port, word32 val, double dcycs) +{ + Scc *scc_ptr; + word32 old_val; + word32 changed_bits; + word32 irq_mask; + int regnum; + int mode; + int tmp1; + + scc_ptr = &(g_scc.scc_stat[port]); + regnum = scc_ptr->reg_ptr & 0xf; + mode = scc_ptr->mode; + + if(mode == 0) { + if((val & 0xf0) == 0) { + /* Set reg_ptr */ + scc_ptr->reg_ptr = val & 0xf; + regnum = 0; + scc_ptr->mode = 1; + } else { + scc_log(SCC_REGNUM(1,port,0), val, dcycs); + } + } else { + scc_ptr->reg_ptr = 0; + scc_ptr->mode = 0; + } + + if(regnum != 0) { + scc_log(SCC_REGNUM(1,port,regnum), val, dcycs); + } + + changed_bits = (scc_ptr->reg[regnum] ^ val) & 0xff; + + /* Set reg reg */ + switch(regnum) { + case 0: /* wr0 */ + tmp1 = (val >> 3) & 0x7; + switch(tmp1) { + case 0x0: + case 0x1: + break; + case 0x2: /* reset ext/status ints */ + /* should clear other ext ints */ + scc_clr_zerocnt_int(port); + break; + case 0x5: /* reset tx int pending */ + scc_clr_tx_int(port); + break; + case 0x6: /* reset rr1 bits */ + break; + case 0x7: /* reset highest pri int pending */ + irq_mask = g_moremem.g_irq_pending; + if(port == 0) { + /* Move SCC0 ints into SCC1 positions */ + irq_mask = irq_mask >> 3; + } + if(irq_mask & IRQ_PENDING_SCC1_RX) { + scc_clr_rx_int(port); + } else if(irq_mask & IRQ_PENDING_SCC1_TX) { + scc_clr_tx_int(port); + } else if(irq_mask & IRQ_PENDING_SCC1_ZEROCNT) { + scc_clr_zerocnt_int(port); + } + break; + case 0x4: /* enable int on next rx char */ + default: + halt_printf("Wr c03%x to wr0 of %02x, bad cmd cd:%x!\n", + 8+port, val, tmp1); + } + tmp1 = (val >> 6) & 0x3; + switch(tmp1) { + case 0x0: /* null code */ + break; + case 0x1: /* reset rx crc */ + case 0x2: /* reset tx crc */ + printf("Wr c03%x to wr0 of %02x!\n", 8+port, val); + break; + case 0x3: /* reset tx underrun/eom latch */ + /* if no extern status pending, or being reset now */ + /* and tx disabled, ext int with tx underrun */ + /* ah, just do nothing */ + break; + } + return; + case 1: /* wr1 */ + /* proterm sets this == 0x10, which is int on all rx */ + scc_ptr->reg[regnum] = val; + return; + case 2: /* wr2 */ + /* All values do nothing, let 'em all through! */ + scc_ptr->reg[regnum] = val; + return; + case 3: /* wr3 */ + if((val & 0x1e) != 0x0) { + halt_printf("Wr c03%x to wr3 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + return; + case 4: /* wr4 */ + if((val & 0x30) != 0x00 || (val & 0x0c) == 0) { + halt_printf("Wr c03%x to wr4 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + if(changed_bits) { + scc_regen_clocks(port); + } + return; + case 5: /* wr5 */ + if((val & 0x15) != 0x0) { + halt_printf("Wr c03%x to wr5 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + if(changed_bits & 0x60) { + scc_regen_clocks(port); + } + return; + case 6: /* wr6 */ + if(val != 0) { + halt_printf("Wr c03%x to wr6 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + return; + case 7: /* wr7 */ + if(val != 0) { + halt_printf("Wr c03%x to wr7 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + return; + case 8: /* wr8 */ + scc_write_data(port, val, dcycs); + return; + case 9: /* wr9 */ + if((val & 0xc0)) { + if(val & 0x80) { + scc_reset_port(0); + } + if(val & 0x40) { + scc_reset_port(1); + } + if((val & 0xc0) == 0xc0) { + scc_hard_reset_port(0); + scc_hard_reset_port(1); + } + } + if((val & 0x35) != 0x00) { + printf("Write c03%x to wr9 of %02x!\n", 8+port, val); + halt_printf("val & 0x35: %02x\n", (val & 0x35)); + } + old_val = g_scc.scc_stat[0].reg[9]; + g_scc.scc_stat[0].reg[regnum] = val; + scc_evaluate_ints(0); + scc_evaluate_ints(1); + return; + case 10: /* wr10 */ + if((val & 0xff) != 0x00) { + printf("Wr c03%x to wr10 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + return; + case 11: /* wr11 */ + scc_ptr->reg[regnum] = val; + if(changed_bits) { + scc_regen_clocks(port); + } + return; + case 12: /* wr12 */ + scc_ptr->reg[regnum] = val; + if(changed_bits) { + scc_regen_clocks(port); + } + return; + case 13: /* wr13 */ + scc_ptr->reg[regnum] = val; + if(changed_bits) { + scc_regen_clocks(port); + } + return; + case 14: /* wr14 */ + old_val = scc_ptr->reg[regnum]; + val = val + (old_val & (~0xff)); + switch((val >> 5) & 0x7) { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + break; + + case 0x4: /* DPLL source is BR gen */ + val |= SCC_R14_DPLL_SOURCE_BRG; + break; + default: + halt_printf("Wr c03%x to wr14 of %02x, bad dpll cd!\n", + 8+port, val); + } + if((val & 0x0c) != 0x0) { + halt_printf("Wr c03%x to wr14 of %02x!\n", 8+port, val); + } + scc_ptr->reg[regnum] = val; + if(changed_bits) { + scc_regen_clocks(port); + } + scc_maybe_br_event(port, dcycs); + return; + case 15: /* wr15 */ + /* ignore all accesses since IIgs self test messes with it */ + if((val & 0xff) != 0x0) { + scc_printf("Write c03%x to wr15 of %02x!\n", 8+port, + val); + } + if((g_scc.scc_stat[0].reg[9] & 0x8) && (val != 0)) { + printf("Write wr15:%02x and master int en = 1!\n",val); + /* set_halt(1); */ + } + scc_ptr->reg[regnum] = val; + scc_maybe_br_event(port, dcycs); + scc_evaluate_ints(port); + return; + default: + halt_printf("Wr c03%x to wr%d of %02x!\n", 8+port, regnum, val); + return; + } +} + +void +scc_maybe_br_event(int port, double dcycs) +{ + Scc *scc_ptr; + double br_dcycs; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(((scc_ptr->reg[14] & 0x01) == 0) || scc_ptr->br_event_pending) { + return; + } + /* also, if ext ints not enabled, don't do baud rate ints */ + if((scc_ptr->reg[15] & 0x02) == 0) { + return; + } + + br_dcycs = scc_ptr->br_dcycs; + if(br_dcycs < 1.0) { + halt_printf("br_dcycs: %f!\n", br_dcycs); + } + + scc_ptr->br_event_pending = 1; + add_event_scc(dcycs + br_dcycs, SCC_MAKE_EVENT(port, SCC_BR_EVENT)); +} + +void +scc_evaluate_ints(int port) +{ + Scc *scc_ptr; + word32 irq_add_mask, irq_remove_mask; + int mie; + + scc_ptr = &(g_scc.scc_stat[port]); + mie = g_scc.scc_stat[0].reg[9] & 0x8; /* Master int en */ + + if(!mie) { + /* There can be no interrupts if MIE=0 */ + remove_irq(IRQ_PENDING_SCC1_RX | IRQ_PENDING_SCC1_TX | + IRQ_PENDING_SCC1_ZEROCNT | + IRQ_PENDING_SCC0_RX | IRQ_PENDING_SCC0_TX | + IRQ_PENDING_SCC0_ZEROCNT); + return; + } + + irq_add_mask = 0; + irq_remove_mask = 0; + if(scc_ptr->wantint_rx) { + irq_add_mask |= IRQ_PENDING_SCC1_RX; + } else { + irq_remove_mask |= IRQ_PENDING_SCC1_RX; + } + if(scc_ptr->wantint_tx) { + irq_add_mask |= IRQ_PENDING_SCC1_TX; + } else { + irq_remove_mask |= IRQ_PENDING_SCC1_TX; + } + if(scc_ptr->wantint_zerocnt) { + irq_add_mask |= IRQ_PENDING_SCC1_ZEROCNT; + } else { + irq_remove_mask |= IRQ_PENDING_SCC1_ZEROCNT; + } + if(port == 0) { + /* Port 1 is in bits 0-2 and port 0 is in bits 3-5 */ + irq_add_mask = irq_add_mask << 3; + irq_remove_mask = irq_remove_mask << 3; + } + if(irq_add_mask) { + add_irq(irq_add_mask); + } + if(irq_remove_mask) { + remove_irq(irq_remove_mask); + } +} + + +void +scc_maybe_rx_event(int port, double dcycs) +{ + Scc *scc_ptr; + double rx_dcycs; + int in_rdptr, in_wrptr; + int depth; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(scc_ptr->rx_event_pending) { + + /* one pending already, wait for the event to arrive */ + return; + } + + in_rdptr = scc_ptr->in_rdptr; + in_wrptr = scc_ptr->in_wrptr; + depth = scc_ptr->rx_queue_depth; + if((in_rdptr == in_wrptr) || (depth >= 3)) { + /* no more chars or no more space, just get out */ + return; + } + + if(depth < 0) { + depth = 0; + } + + /* pull char from in_rdptr into queue */ + scc_ptr->rx_queue[depth] = scc_ptr->in_buf[in_rdptr]; + scc_ptr->in_rdptr = (in_rdptr + 1) & (SCC_INBUF_SIZE - 1); + scc_ptr->rx_queue_depth = depth + 1; + scc_maybe_rx_int(port, dcycs); + rx_dcycs = scc_ptr->rx_dcycs; + scc_ptr->rx_event_pending = 1; + add_event_scc(dcycs + rx_dcycs, SCC_MAKE_EVENT(port, SCC_RX_EVENT)); +} + +void +scc_maybe_rx_int(int port, double dcycs) +{ + Scc *scc_ptr; + int depth; + int rx_int_mode; + + scc_ptr = &(g_scc.scc_stat[port]); + + depth = scc_ptr->rx_queue_depth; + if(depth <= 0) { + /* no more chars, just get out */ + scc_clr_rx_int(port); + return; + } + rx_int_mode = (scc_ptr->reg[1] >> 3) & 0x3; + if(rx_int_mode == 1 || rx_int_mode == 2) { + scc_ptr->wantint_rx = 1; + } + scc_evaluate_ints(port); +} + +void +scc_clr_rx_int(int port) +{ + g_scc.scc_stat[port].wantint_rx = 0; + scc_evaluate_ints(port); +} + +void +scc_handle_tx_event(int port, double dcycs) +{ + Scc *scc_ptr; + int tx_int_mode; + + scc_ptr = &(g_scc.scc_stat[port]); + + /* nothing pending, see if ints on */ + tx_int_mode = (scc_ptr->reg[1] & 0x2); + if(tx_int_mode) { + scc_ptr->wantint_tx = 1; + } + scc_evaluate_ints(port); +} + +void +scc_maybe_tx_event(int port, double dcycs) +{ + Scc *scc_ptr; + double tx_dcycs; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(scc_ptr->tx_event_pending) { + /* one pending already, tx_buf is full */ + scc_ptr->tx_buf_empty = 0; + } else { + /* nothing pending, see ints on */ + scc_evaluate_ints(port); + tx_dcycs = scc_ptr->tx_dcycs; + scc_ptr->tx_event_pending = 1; + add_event_scc(dcycs + tx_dcycs, + SCC_MAKE_EVENT(port, SCC_TX_EVENT)); + } +} + +void +scc_clr_tx_int(int port) +{ + g_scc.scc_stat[port].wantint_tx = 0; + scc_evaluate_ints(port); +} + +void +scc_set_zerocnt_int(int port) +{ + Scc *scc_ptr; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(scc_ptr->reg[15] & 0x2) { + scc_ptr->wantint_zerocnt = 1; + } + scc_evaluate_ints(port); +} + +void +scc_clr_zerocnt_int(int port) +{ + g_scc.scc_stat[port].wantint_zerocnt = 0; + scc_evaluate_ints(port); +} + +void +scc_add_to_readbuf(int port, word32 val, double dcycs) +{ + Scc *scc_ptr; + int in_wrptr; + int in_wrptr_next; + int in_rdptr; + + scc_ptr = &(g_scc.scc_stat[port]); + + in_wrptr = scc_ptr->in_wrptr; + in_rdptr = scc_ptr->in_rdptr; + in_wrptr_next = (in_wrptr + 1) & (SCC_INBUF_SIZE - 1); + if(in_wrptr_next != in_rdptr) { + scc_ptr->in_buf[in_wrptr] = val; + scc_ptr->in_wrptr = in_wrptr_next; + scc_printf("scc in port[%d] add char 0x%02x, %d,%d != %d\n", + scc_ptr->port, val, + in_wrptr, in_wrptr_next, in_rdptr); + printf("sending to modem :%c\n",val); + g_scc.g_scc_overflow = 0; + } else { + if(g_scc.g_scc_overflow == 0) { + g_sim65816.g_code_yellow++; + printf("scc inbuf overflow port %d\n", port); + } + g_scc.g_scc_overflow = 1; + } + + scc_maybe_rx_event(port, dcycs); +} + +void +scc_add_to_readbufv(int port, double dcycs, const char *fmt, ...) +{ + va_list ap; + char *bufptr; + int ret, len, c; + int i; + + va_start(ap, fmt); + bufptr = (char*)malloc(4096); // OG cast added + bufptr[0] = 0; + ret = vsnprintf(bufptr, 4090, fmt, ap); + len = strlen(bufptr); + for(i = 0; i < len; i++) { + c = bufptr[i]; + if(c == 0x0a) { + scc_add_to_readbuf(port, 0x0d, dcycs); + } + scc_add_to_readbuf(port, c, dcycs); + } + va_end(ap); +} + +void +scc_transmit(int port, word32 val, double dcycs) +{ + Scc *scc_ptr; + int out_wrptr; + int out_rdptr; + + scc_ptr = &(g_scc.scc_stat[port]); + + /* See if port initialized, if not, do so now */ + if(scc_ptr->state == 0) { + scc_port_init(port); + } + if(scc_ptr->state < 0) { + /* No working serial port, just toss it and go */ + return; + } + + if(!scc_ptr->tx_buf_empty) { + /* toss character! */ + printf("Tossing char\n"); + return; + } + + out_wrptr = scc_ptr->out_wrptr; + out_rdptr = scc_ptr->out_rdptr; + if(scc_ptr->tx_dcycs < 1.0) { + if(out_wrptr != out_rdptr) { + /* do just one char, then get out */ + printf("tx_dcycs < 1\n"); + return; + } + } + if(g_sim65816.g_serial_out_masking) { + val = val & 0x7f; + } + + scc_add_to_writebuf(port, val, dcycs); +} + +void +scc_add_to_writebuf(int port, word32 val, double dcycs) +{ + Scc *scc_ptr; + int out_wrptr; + int out_wrptr_next; + int out_rdptr; + + scc_ptr = &(g_scc.scc_stat[port]); + + /* See if port initialized, if not, do so now */ + if(scc_ptr->state == 0) { + scc_port_init(port); + } + if(scc_ptr->state < 0) { + /* No working serial port, just toss it and go */ + return; + } + + out_wrptr = scc_ptr->out_wrptr; + out_rdptr = scc_ptr->out_rdptr; + + out_wrptr_next = (out_wrptr + 1) & (SCC_OUTBUF_SIZE - 1); + if(out_wrptr_next != out_rdptr) { + scc_ptr->out_buf[out_wrptr] = val; + scc_ptr->out_wrptr = out_wrptr_next; + scc_printf("scc wrbuf port %d had char 0x%02x added\n", + scc_ptr->port, val); + g_scc.g_scc_overflow = 0; + } else { + if(g_scc.g_scc_overflow == 0) { + g_sim65816.g_code_yellow++; + // OG Too many warning with DiversiTune + scc_printf("scc outbuf overflow port %d\n", port); + } + g_scc.g_scc_overflow = 1; + } +} + +word32 +scc_read_data(int port, double dcycs) +{ + Scc *scc_ptr; + word32 ret; + int depth; + int i; + + scc_ptr = &(g_scc.scc_stat[port]); + + scc_try_fill_readbuf(port, dcycs); + + depth = scc_ptr->rx_queue_depth; + + ret = 0; + if(depth != 0) { + ret = scc_ptr->rx_queue[0]; + for(i = 1; i < depth; i++) { + scc_ptr->rx_queue[i-1] = scc_ptr->rx_queue[i]; + } + scc_ptr->rx_queue_depth = depth - 1; + scc_maybe_rx_event(port, dcycs); + scc_maybe_rx_int(port, dcycs); + } + + scc_printf("SCC read %04x: ret %02x, depth:%d\n", 0xc03b-port, ret, + depth); + + scc_log(SCC_REGNUM(0,port,8), ret, dcycs); + +// printf("scc send %d\n",ret); + return ret; +} + + +void +scc_write_data(int port, word32 val, double dcycs) +{ + Scc *scc_ptr; + + scc_printf("SCC write %04x: %02x\n", 0xc03b-port, val); + scc_log(SCC_REGNUM(1,port,8), val, dcycs); + + scc_ptr = &(g_scc.scc_stat[port]); + if(scc_ptr->reg[14] & 0x10) { + /* local loopback! */ + scc_add_to_readbuf(port, val, dcycs); + } else { + scc_transmit(port, val, dcycs); + } + scc_try_to_empty_writebuf(port, dcycs); + + scc_maybe_tx_event(port, dcycs); +} + diff --git a/kegs/Src/scc.h b/kegs/Src/scc.h new file mode 100644 index 0000000..cc74ca4 --- /dev/null +++ b/kegs/Src/scc.h @@ -0,0 +1,172 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#ifdef INCLUDE_RCSID_C +const char rcsid_scc_h[] = "@(#)$KmKId: scc.h,v 1.17 2004-12-03 14:03:12-05 kentd Exp $"; +#endif + +#include + +#ifdef _WIN32 +# include +#else +# include +# include +# include +#endif + +#if defined(HPUX) || defined(__linux__) || defined(SOLARIS) || defined(DRIVER_IOS) || defined(DRIVER_OSX) || defined(__MACH__) || defined(_WIN32) +# define SCC_SOCKETS +#endif + + +/* my scc port 0 == channel A, port 1 = channel B */ + +#define SCC_INBUF_SIZE 512 /* must be a power of 2 */ +#define SCC_OUTBUF_SIZE 512 /* must be a power of 2 */ + +#define SCC_MODEM_MAX_CMD_STR 128 + +#ifndef SOCKET +# define SOCKET word32 /* for non-windows */ +#endif + + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +STRUCT(Scc) { + int port; + int state; + int accfd; + SOCKET sockfd; + int socket_state; + int rdwrfd; + void *host_handle; + void *host_handle2; + int host_aux1; + int read_called_this_vbl; + int write_called_this_vbl; + + int mode; + int reg_ptr; + int reg[16]; + + int rx_queue_depth; + byte rx_queue[4]; + + int in_rdptr; + int in_wrptr; + byte in_buf[SCC_INBUF_SIZE]; + + int out_rdptr; + int out_wrptr; + byte out_buf[SCC_OUTBUF_SIZE]; + + int br_is_zero; + int tx_buf_empty; + int wantint_rx; + int wantint_tx; + int wantint_zerocnt; + int dcd; + + _ALIGNED(8) double br_dcycs; + _ALIGNED(8) double tx_dcycs ; + _ALIGNED(8) double rx_dcycs; + + int br_event_pending; + int rx_event_pending; + int tx_event_pending; + + int char_size; + int baud_rate; + _ALIGNED(8) double out_char_dcycs; + + int socket_num_rings; + int socket_last_ring_dcycs; + word32 modem_mode; + int modem_dial_or_acc_mode; + int modem_plus_mode; + int modem_s0_val; + int telnet_mode; + int telnet_iac; + word32 telnet_local_mode[2]; + word32 telnet_remote_mode[2]; + word32 telnet_reqwill_mode[2]; + word32 telnet_reqdo_mode[2]; + int modem_cmd_len; + byte modem_cmd_str[SCC_MODEM_MAX_CMD_STR + 5]; +} XCODE_PRAGMA_PACK ; + + + + +#define SCCMODEM_NOECHO 0x0001 +#define SCCMODEM_NOVERBOSE 0x0002 + + +class s_scc : public serialized +{ +public: + Scc scc_stat[2]; + int g_scc_overflow ; + int g_wsastartup_called; + + s_scc() + { + INIT_SERIALIZED(); + } + + +#define SERIALIZE_SOCKET(X,N) int old_##N = X.sockfd; X.sockfd=0; +#define UNSERIALIZE_SOCKET(X,N) X.sockfd = old_##N ; + + void in(serialize* _s) + { + byte* ptr = (byte*)_s->data; + int ssize = *(int*)ptr; + if (ssize!= sizeof(*this)) + ALIGNMENT_ERROR("scc",ssize,sizeof(*this)); + ptr += sizeof(ssize); + memcpy(this,ptr,sizeof(*this)); + + // TODO UNSERIALIZE SOCKET + } + + int out(serialize* _s, int _fastalloc) + { + + int ssize = sizeof(*this); + int size = ssize + sizeof(ssize); + _s->size = size; + _s->fastalloc = _fastalloc; + _s->data = (void*)x_malloc(size,_fastalloc); + byte* ptr = (byte*) _s->data; + + memcpy(ptr,&ssize,sizeof(ssize)); + ptr+=sizeof(ssize); + + SERIALIZE_SOCKET(scc_stat[0],stat0); + SERIALIZE_SOCKET(scc_stat[1],stat1); + + memcpy(ptr,this,sizeof(*this)); + + UNSERIALIZE_SOCKET(scc_stat[0],stat0); + UNSERIALIZE_SOCKET(scc_stat[1],stat1); + + return size; + } + +} XCODE_PRAGMA_PACK; + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +extern s_scc g_scc; \ No newline at end of file diff --git a/kegs/Src/scc_socket_driver.cpp b/kegs/Src/scc_socket_driver.cpp new file mode 100644 index 0000000..507d51d --- /dev/null +++ b/kegs/Src/scc_socket_driver.cpp @@ -0,0 +1,1183 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "scc.h" +#include "sim65816.h" + + +#ifndef UNDER_CE //OG +#include +#endif + +#ifndef _MSC_VER //OG +extern int h_errno; +#else +#define socklen_t int +#endif + +/* Usage: scc_socket_init() called to init socket mode */ +/* At all times, we try to have a listen running on the incoming socket */ +/* If we want to dial out, we close the incoming socket and create a new */ +/* outgoing socket. Any hang-up causes the socket to be closed and it will */ +/* then re-open on a subsequent call to scc_socket_open */ + +void +scc_socket_init(int port) +{ + Scc *scc_ptr; + +#ifdef _WIN32 + WSADATA wsadata; + int ret; + + if(g_scc.g_wsastartup_called == 0) { + ret = WSAStartup(MAKEWORD(2,0), &wsadata); + printf("WSAStartup ret: %d\n", ret); + g_scc.g_wsastartup_called = 1; + } +#endif + scc_ptr = &(g_scc.scc_stat[port]); + scc_ptr->state = 1; /* successful socket */ + scc_ptr->sockfd = -1; /* Indicate no socket open yet */ + scc_ptr->accfd = -1; /* Indicate no socket open yet */ + scc_ptr->rdwrfd = -1; /* Indicate no socket open yet */ + scc_ptr->socket_state = -2; /* 0 means talk to "modem" */ + /* 1 connected */ + scc_ptr->socket_num_rings = 0; + scc_ptr->socket_last_ring_dcycs = 0; + scc_ptr->dcd = 0; /* 0 means no carrier */ + scc_ptr->modem_s0_val = 0; + scc_ptr->host_aux1 = sizeof(struct sockaddr_in); + scc_ptr->host_handle = malloc(scc_ptr->host_aux1); + /* Real init will be done when bytes need to be read/write from skt */ +} + +void +scc_socket_maybe_open_incoming(int port, double dcycs) +{ + Scc *scc_ptr; + struct sockaddr_in sa_in; + int on; + int ret; + SOCKET sockfd; + int inc; + + inc = 0; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(scc_ptr->sockfd != -1) { + /* it's already open, get out */ + return; + } + if(scc_ptr->socket_state < 0) { + /* not initialized, get out */ + return; + } + + printf("scc socket close being called from socket_open_out\n"); + scc_socket_close(port, 0, dcycs); + + scc_ptr->socket_state = 0; + scc_ptr->socket_num_rings = 0; + + memset(scc_ptr->host_handle, 0, scc_ptr->host_aux1); + + while(1) { + sockfd = socket(AF_INET, SOCK_STREAM, 0); + printf("sockfd ret: %d\n", sockfd); + if(sockfd == -1) { + printf("socket ret: %d, errno: %d\n", sockfd, errno); + scc_socket_close(port, 0, dcycs); + scc_ptr->socket_state = -1; + return; + } + /* printf("socket ret: %d\n", sockfd); */ + + on = 1; + ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)); + if(ret < 0) { + printf("setsockopt REUSEADDR ret: %d, err:%d\n", + ret, errno); + scc_socket_close(port, 0, dcycs); + scc_ptr->socket_state = -1; + return; + } + + memset(&sa_in, 0, sizeof(sa_in)); + sa_in.sin_family = AF_INET; + sa_in.sin_port = htons(6501 + port + inc); + sa_in.sin_addr.s_addr = htonl(INADDR_ANY); + + ret = bind(sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in)); + + if(ret >= 0) { + ret = listen(sockfd, 1); + break; + } + /* else ret to bind was < 0 */ + printf("bind ret: %d, errno: %d\n", ret, errno); + inc++; +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + printf("Trying next port: %d\n", 6501 + port + inc); + if(inc >= 10) { + printf("Too many retries, quitting\n"); + scc_socket_close(port, 0, dcycs); + scc_ptr->socket_state = -1; + return; + } + } + + printf("SCC port %d is at unix port %d\n", port, 6501 + port + inc); + + scc_ptr->sockfd = sockfd; + scc_ptr->state = 1; /* successful socket */ + + scc_socket_make_nonblock(port, dcycs); + +} + + +Scc *scc_delayed_ptr=NULL; + +void +scc_socket_open_outgoing(int port, double dcycs) +{ + Scc *scc_ptr; + struct sockaddr_in sa_in; + struct hostent *hostentptr; + int on; + int ret; + SOCKET sockfd; + + scc_ptr = &(g_scc.scc_stat[port]); + + printf("scc socket close being called from socket_open_out\n"); + scc_socket_close(port, 0, dcycs); + + scc_ptr->socket_state = 0; + + memset(scc_ptr->host_handle, 0, scc_ptr->host_aux1); + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + printf("sockfd ret: %d\n", sockfd); + if(sockfd == -1) { + printf("socket ret: %d, errno: %d\n", sockfd, errno); + scc_socket_close(port, 1, dcycs); + return; + } + /* printf("socket ret: %d\n", sockfd); */ + + on = 1; + ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)); + if(ret < 0) { + printf("setsockopt REUSEADDR ret: %d, err:%d\n", + ret, errno); + scc_socket_close(port, 1, dcycs); + return; + } + + memset(&sa_in, 0, sizeof(sa_in)); + sa_in.sin_family = AF_INET; + + int requestport = 23; // default telnet + const char* str = (const char*)&scc_ptr->modem_cmd_str[0]; + char host[1024]; + int l = strlen(str); + int i ; + for(i=0;imodem_cmd_str[0]); +#else + fatal_printf("Lookup host %s failed, herrno: %d\n", + &scc_ptr->modem_cmd_str[0], h_errno); +#endif +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + + scc_socket_close(port, 1, dcycs); + x_show_alert(0, 0); + return; + } + memcpy(&sa_in.sin_addr.s_addr, hostentptr->h_addr, + hostentptr->h_length); + /* The above copies the 32-bit internet address into */ + /* sin_addr.s_addr. It's in correct network format */ + + ret = connect(sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in)); + if(ret < 0) { + printf("connect ret: %d, errno: %d\n", ret, errno); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + scc_socket_close(port, 1, dcycs); + return; + } + scc_socket_modem_connect(port, dcycs); + scc_ptr->dcd = 1; /* carrier on */ + scc_ptr->socket_state = 1; /* talk to socket */ + scc_ptr->socket_num_rings = 0; + + printf("SCC port %d is now outgoing to %s\n", port, + &scc_ptr->modem_cmd_str[0]); + + scc_ptr->sockfd = sockfd; +// scc_ptr->state = 1; /* successful socket */ + scc_ptr->state = 0; //delay state + scc_delayed_ptr = scc_ptr; + add_event_entry(dcycs+(5000/16)*DCYCS_IN_16MS , EV_SCC_ENABLE); //1s delay + + scc_socket_make_nonblock(port, dcycs); + scc_ptr->rdwrfd = scc_ptr->sockfd; +} + +void scc_delayed_enable() +{ + if (scc_delayed_ptr) + { + printf("enabling scc\n"); + scc_delayed_ptr->state = 1; + scc_delayed_ptr = NULL; + } +} + +void +scc_socket_make_nonblock(int port, double dcycs) +{ + Scc *scc_ptr; + SOCKET sockfd; + int ret; +#ifdef _WIN32 + u_long flags; +#else + int flags; +#endif + + scc_ptr = &(g_scc.scc_stat[port]); + sockfd = scc_ptr->sockfd; + +#ifdef _WIN32 + flags = 1; + ret = ioctlsocket(sockfd, FIONBIO, &flags); + if(ret != 0) { + printf("ioctlsocket ret: %d\n", ret); + } +#else + flags = fcntl(sockfd, F_GETFL, 0); + if(flags == -1) { + printf("fcntl GETFL ret: %d, errno: %d\n", flags, errno); + scc_socket_close(port, 1, dcycs); + scc_ptr->socket_state = -1; + return; + } + ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + if(ret == -1) { + printf("fcntl SETFL ret: %d, errno: %d\n", ret, errno); + scc_socket_close(port, 1, dcycs); + scc_ptr->socket_state = -1; + return; + } +#endif +} + +void +scc_socket_change_params(int port) +{ +} + +void +scc_socket_close(int port, int full_close, double dcycs) +{ + Scc *scc_ptr; + int rdwrfd; + SOCKET sockfd; + int i; + + scc_ptr = &(g_scc.scc_stat[port]); + + printf("In scc_socket_close, %d, %d, %f\n", port, full_close, dcycs); + + rdwrfd = scc_ptr->rdwrfd; + if(rdwrfd >= 0) { + printf("socket_close: rdwrfd=%d, closing\n", rdwrfd); +#ifdef WIN32 + closesocket(rdwrfd); +#else + close(rdwrfd); +#endif + } + sockfd = scc_ptr->sockfd; + if(sockfd != -1) { + printf("socket_close: sockfd=%d, closing\n", sockfd); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + } + + scc_ptr->modem_cmd_len = 0; + scc_ptr->telnet_mode = 0; + scc_ptr->telnet_iac = 0; + for(i = 0; i < 2; i++) { + scc_ptr->telnet_local_mode[i] = 0; + scc_ptr->telnet_remote_mode[i] = 0; + scc_ptr->telnet_reqwill_mode[i] = 0; + scc_ptr->telnet_reqdo_mode[i] = 0; + } + scc_ptr->rdwrfd = -1; + scc_ptr->sockfd = -1; + scc_ptr->dcd = 0; + scc_ptr->socket_num_rings = 0; + + if(!full_close) { + return; + } + + scc_socket_modem_hangup(port, dcycs); + + /* and go back to modem mode */ + scc_ptr->socket_state = 0; + if(g_sim65816.g_serial_modem[port]) { + scc_ptr->modem_dial_or_acc_mode = 0; + } else { + scc_ptr->modem_dial_or_acc_mode = 2; /* always accept */ + } +} + +void +scc_accept_socket(int port, double dcycs) +{ +#ifdef SCC_SOCKETS + Scc *scc_ptr; + int flags; + int num_rings; + int rdwrfd; + int ret; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(scc_ptr->sockfd == -1) { + printf("in accept_socket, call socket_open\n"); + scc_socket_maybe_open_incoming(port, dcycs); + } + if(scc_ptr->sockfd == -1) { + return; /* just give up */ + } + if(scc_ptr->rdwrfd == -1) { + rdwrfd = accept(scc_ptr->sockfd, (sockaddr*)scc_ptr->host_handle, + (socklen_t*)&(scc_ptr->host_aux1)); + if(rdwrfd < 0) { + return; + } + + flags = 0; + ret = 0; +#ifndef _WIN32 + /* For Linux, we need to set O_NONBLOCK on the rdwrfd */ + flags = fcntl(rdwrfd, F_GETFL, 0); + if(flags == -1) { + printf("fcntl GETFL ret: %d, errno: %d\n", flags,errno); + return; + } + ret = fcntl(rdwrfd, F_SETFL, flags | O_NONBLOCK); + if(ret == -1) { + printf("fcntl SETFL ret: %d, errno: %d\n", ret, errno); + return; + } +#endif + scc_ptr->rdwrfd = rdwrfd; + printf("Set port[%d].rdwrfd = %d\n", port, rdwrfd); + + num_rings = 4; + if(scc_ptr->modem_s0_val > 0) { + num_rings = scc_ptr->modem_s0_val; + } + scc_ptr->socket_num_rings = num_rings; + scc_ptr->socket_last_ring_dcycs = 0; /* do ring now*/ + scc_socket_modem_do_ring(port, dcycs); + + /* and send some telnet codes */ + scc_ptr->telnet_reqwill_mode[0] = 0xa; /* 3=GO_AH and 1=ECHO */ + scc_ptr->telnet_reqdo_mode[0] = 0xa; /* 3=GO_AH and 1=ECHO */ +#if 0 + scc_ptr->telnet_reqdo_mode[1] = 0x4; /* 34=LINEMODE */ +#endif + } +#endif +} + +void +scc_socket_telnet_reqs(int port, double dcycs) +{ + Scc *scc_ptr; + word32 mask, willmask, domask; + int i, j; + + scc_ptr = &(g_scc.scc_stat[port]); + + for(i = 0; i < 64; i++) { + j = i >> 5; + mask = 1 << (i & 31); + willmask = scc_ptr->telnet_reqwill_mode[j]; + if(willmask & mask) { + scc_add_to_writebuf(port, 0xff, dcycs); + scc_add_to_writebuf(port, 0xfb, dcycs); /* WILL */ + scc_add_to_writebuf(port, i, dcycs); + } + domask = scc_ptr->telnet_reqdo_mode[j]; + if(domask & mask) { + scc_add_to_writebuf(port, 0xff, dcycs); + scc_add_to_writebuf(port, 0xfd, dcycs); /* DO */ + scc_add_to_writebuf(port, i, dcycs); + } + } +} + +void +scc_socket_fill_readbuf(int port, int space_left, double dcycs) +{ +#ifdef SCC_SOCKETS + byte tmp_buf[256]; + Scc *scc_ptr; + int rdwrfd; + int ret; + int i; + + scc_ptr = &(g_scc.scc_stat[port]); + + scc_accept_socket(port, dcycs); + scc_socket_modem_do_ring(port, dcycs); + + if(scc_ptr->socket_state == 0 && g_sim65816.g_serial_modem[port]) { + /* Just get out, this is modem mode */ + /* The transmit function stuffs any bytes in receive buf */ + return; + } + rdwrfd = scc_ptr->rdwrfd; + if(rdwrfd < 0) { + return; /* just get out */ + } + + /* Try reading some bytes */ + space_left = MIN(space_left, 256); + ret = recv(rdwrfd, (char*)tmp_buf, space_left, 0); // OG Added cast + if(ret > 0) { + for(i = 0; i < ret; i++) { + if(tmp_buf[i] == 0) { + /* Skip null chars */ + continue; + } + scc_socket_recvd_char(port, tmp_buf[i], dcycs); + } + } else if(ret == 0) { + /* assume socket close */ + printf("recv got 0 from rdwrfd=%d, closing\n", rdwrfd); + scc_socket_close(port, 1, dcycs); + } +#endif +} + +int g_scc_dbg_print_cnt = 50; + +void +scc_socket_recvd_char(int port, int c, double dcycs) +{ + Scc *scc_ptr; + word32 locmask, remmask, mask; + word32 reqwillmask, reqdomask; + int telnet_mode, telnet_iac; + int eff_c, cpos; + int reply; + + scc_ptr = &(g_scc.scc_stat[port]); + + scc_socket_maybe_open_incoming(port, dcycs); + + telnet_mode = scc_ptr->telnet_mode; + telnet_iac = scc_ptr->telnet_iac; + if(c >= 0xf0 || telnet_mode || telnet_iac) { + g_scc_dbg_print_cnt = 50; + } +#if 0 + if(g_scc_dbg_print_cnt) { + printf("Recv: %02x mode: %d\n", c, telnet_mode); + g_scc_dbg_print_cnt--; + } +#endif + + eff_c = c; + if(telnet_iac == 0) { + if(c == 0xff) { + scc_ptr->telnet_iac = 0xff; + return; /* and just get out */ + } + } else { + /* last char was 0xff, see if this is 0xff */ + if(c != 0xff) { + /* this is some kind of command */ + eff_c = eff_c | 0x100; /* indicate prev char IAC */ + } + } + scc_ptr->telnet_iac = 0; + + mask = 1 << (c & 31); + cpos = (c >> 5) & 1; + locmask = scc_ptr->telnet_local_mode[cpos] & mask; + remmask = scc_ptr->telnet_remote_mode[cpos] & mask; + reqwillmask = scc_ptr->telnet_reqwill_mode[cpos] & mask; + reqdomask = scc_ptr->telnet_reqdo_mode[cpos] & mask; + switch(telnet_mode) { + case 0: /* just passing through bytes */ + switch(eff_c) { + case 0x1fe: /* DON'T */ + case 0x1fd: /* DO */ + case 0x1fc: /* WON'T */ + case 0x1fb: /* WILL */ + case 0x1fa: /* SB */ + telnet_mode = c; + break; + default: + if(eff_c < 0x100) { + scc_add_to_readbuf(port, c, dcycs); + } + break; + } + break; + case 3: /* LINEMODE SB SLC, octet 0 */ + if(eff_c == 0x1f0) { + /* SE, the end */ + telnet_mode = 0; + } + printf("LINEMODE SLC octet 0: %02x\n", c); + telnet_mode = 4; + break; + case 4: /* LINEMODE SB SLC, octet 1 */ + printf("LINEMODE SLC octet 1: %02x\n", c); + telnet_mode = 5; + if(eff_c == 0x1f0) { + /* SE, the end */ + printf("Got SE at octet 1...\n"); + telnet_mode = 0; + } + break; + case 5: /* LINEMODE SB SLC, octet 2 */ + printf("LINEMODE SLC octet 2: %02x\n", c); + telnet_mode = 3; + if(eff_c == 0x1f0) { + /* SE, the end */ + printf("Got SE at octet 2...\n"); + telnet_mode = 0; + } + break; + case 34: /* LINEMODE SB beginning */ + switch(c) { + case 3: /* SLC */ + telnet_mode = 3; + break; + default: + telnet_mode = 0xee; /* go to SB eat */ + break; + } + break; + case 0xfa: /* in 0xfa = SB mode, eat up subcommands */ + switch(c) { + case 34: /* LINEMODE */ + telnet_mode = 34; + break; + default: + telnet_mode = 0xee; /* SB eat mode */ + break; + } + break; + case 0xee: /* in SB eat mode */ + if(eff_c == 0x1f0) { /* SE, end of sub-command */ + telnet_mode = 0; + } else { + /* just stay in eat mode */ + } + break; + case 0xfe: /* previous char was "DON'T" */ + if(locmask && (reqwillmask == 0)) { + /* it's a mode change */ + /* always OK to turn off a mode that we had on */ + scc_add_to_writebuf(port, 0xff, dcycs); + scc_add_to_writebuf(port, 0xfc, dcycs); /* WON'T */ + scc_add_to_writebuf(port, c, dcycs); + } + scc_ptr->telnet_local_mode[cpos] &= ~mask; + scc_ptr->telnet_reqwill_mode[cpos] &= ~mask; + telnet_mode = 0; + break; + case 0xfd: /* previous char was "DO" */ + reply = 0xfc; + if(locmask == 0 && (reqwillmask == 0)) { + /* it's a mode change, send some response */ + reply = 0xfc; /* nack it with WON'T */ + if(c == 0x03 || c == 0x01) { + reply = 0xfb; /* Ack with WILL */ + } + scc_add_to_writebuf(port, 0xff, dcycs); + scc_add_to_writebuf(port, reply, dcycs); + scc_add_to_writebuf(port, c, dcycs); + } + if(reqwillmask || (reply == 0xfb)) { + scc_ptr->telnet_local_mode[cpos] |= mask; + } + scc_ptr->telnet_reqwill_mode[cpos] &= ~mask; + telnet_mode = 0; + break; + case 0xfc: /* previous char was "WON'T" */ + if(remmask && (reqdomask == 0)) { + /* it's a mode change, ack with DON'T */ + scc_add_to_writebuf(port, 0xff, dcycs); + scc_add_to_writebuf(port, 0xfe, dcycs); /* DON'T */ + scc_add_to_writebuf(port, c, dcycs); + } + scc_ptr->telnet_remote_mode[cpos] &= ~mask; + scc_ptr->telnet_reqdo_mode[cpos] &= ~mask; + telnet_mode = 0; + break; + case 0xfb: /* previous char was "WILL" */ + reply = 0xfe; /* nack it with DON'T */ + if(remmask == 0 && (reqdomask == 0)) { + /* it's a mode change, send some response */ + if(c == 0x03 || c == 0x01) { + reply = 0xfd; /* Ack with DO */ + } + scc_add_to_writebuf(port, 0xff, dcycs); + scc_add_to_writebuf(port, reply, dcycs); + scc_add_to_writebuf(port, c, dcycs); + } + if(reqdomask || (reply == 0xfd)) { + scc_ptr->telnet_remote_mode[cpos] |= mask; + } + scc_ptr->telnet_reqdo_mode[cpos] &= ~mask; + telnet_mode = 0; + break; + default: + telnet_mode = 0; + break; + } + scc_ptr->telnet_mode = telnet_mode; +} + +void +scc_socket_empty_writebuf(int port, double dcycs) +{ +#ifdef SCC_SOCKETS +# ifndef _WIN32 + struct sigaction newact, oldact; +# endif + Scc *scc_ptr; + double diff_dcycs; + int plus_mode; + int rdptr; + int wrptr; + int rdwrfd; + int done; + int ret; + int len; + int c; + int i; + + scc_ptr = &(g_scc.scc_stat[port]); + + /* See if +++ done and we should go to command mode */ + diff_dcycs = dcycs - scc_ptr->out_char_dcycs; + if((diff_dcycs > 900.0*1000) && (scc_ptr->modem_plus_mode == 3) && + (scc_ptr->socket_state >= 1) && + (g_sim65816.g_serial_modem[port] != 0)) { + scc_ptr->socket_state = 0; /* go modem mode, stay connect*/ + scc_ptr->modem_plus_mode = 0; + scc_socket_send_modem_code(port, 0, dcycs); + } + + /* Try writing some bytes */ + done = 0; + while(!done) { + rdptr = scc_ptr->out_rdptr; + wrptr = scc_ptr->out_wrptr; + if(rdptr == wrptr) { + done = 1; + break; + } + rdwrfd = scc_ptr->rdwrfd; + len = wrptr - rdptr; + if(len < 0) { + len = SCC_OUTBUF_SIZE - rdptr; + } + if(len > 32) { + len = 32; + } + if(len <= 0) { + done = 1; + break; + } + + if(scc_ptr->socket_state < 1 && g_sim65816.g_serial_modem[port]) { + len = 1; + scc_socket_modem_write(port, scc_ptr->out_buf[rdptr], + dcycs); + ret = 1; + } else { + if(rdwrfd == -1) { + if(g_sim65816.g_serial_modem[port]) { + printf("socket_state: %d, ser_mod: %d, " + "rdwrfd: %d\n", + scc_ptr->socket_state, + g_sim65816.g_serial_modem[port], rdwrfd); + } + scc_ptr->socket_state = 0; + scc_socket_maybe_open_incoming(port, dcycs); + return; + } + for(i = 0; i < len; i++) { + c = scc_ptr->out_buf[rdptr + i]; + plus_mode = scc_ptr->modem_plus_mode; + diff_dcycs = dcycs - scc_ptr->out_char_dcycs; + if(c == '+' && plus_mode == 0) { + if(diff_dcycs > 500*1000) { + scc_ptr->modem_plus_mode = 1; + } + } else if(c == '+') { + if(diff_dcycs < 800.0*1000) { + plus_mode++; + scc_ptr->modem_plus_mode = + plus_mode; + } + } else { + scc_ptr->modem_plus_mode = 0; + } + scc_ptr->out_char_dcycs = dcycs; + } + +# ifdef _WIN32 + ret = send(rdwrfd, (const char*)&(scc_ptr->out_buf[rdptr]), len, 0); // OG Added Cast +# else + /* ignore SIGPIPE around writes to the socket, so we */ + /* can catch a closed socket and prepare to accept */ + /* a new connection. Otherwise, SIGPIPE kills KEGS */ + sigemptyset(&newact.sa_mask); + newact.sa_handler = SIG_IGN; + newact.sa_flags = 0; + sigaction(SIGPIPE, &newact, &oldact); + + ret = send(rdwrfd, &(scc_ptr->out_buf[rdptr]), len, 0); + + sigaction(SIGPIPE, &oldact, 0); + /* restore previous SIGPIPE behavior */ +# endif /* WIN32 */ + +#if 0 + printf("sock output: %02x\n", scc_ptr->out_buf[rdptr]); +#endif + + } + + if(ret == 0) { + done = 1; /* give up for now */ + break; + } else if(ret < 0) { + /* assume socket is dead */ + printf("socket write failed, resuming modem mode\n"); + scc_socket_close(port, 1, dcycs); + done = 1; + break; + } else { + rdptr = rdptr + ret; + if(rdptr >= SCC_OUTBUF_SIZE) { + rdptr = rdptr - SCC_OUTBUF_SIZE; + } + scc_ptr->out_rdptr = rdptr; + } + } +#endif +} + +void +scc_socket_modem_write(int port, int c, double dcycs) +{ + Scc *scc_ptr; + char *str; + word32 modem_mode; + int do_echo; + int got_at; + int len; + + scc_ptr = &(g_scc.scc_stat[port]); + + if(scc_ptr->sockfd == -1) { + scc_ptr->socket_state = 0; + scc_socket_maybe_open_incoming(port, dcycs); + } + + modem_mode = scc_ptr->modem_mode; + str = (char*)&(scc_ptr->modem_cmd_str[0]); // OG Added Cast + +#if 0 + printf("M: %02x\n", c); +#endif + do_echo = ((modem_mode & SCCMODEM_NOECHO) == 0); + len = scc_ptr->modem_cmd_len; + got_at = 0; + if(len >= 2 && str[0] == 'a' && str[1] == 't') { + /* we've got an 'at', do not back up past it */ + got_at = 1; + } + if(c == 0x0d) { + if(do_echo) { + scc_add_to_readbuf(port, c, dcycs); /* echo cr */ + scc_add_to_readbuf(port, 0x0a, dcycs); /* echo lf */ + } + do_echo = 0; /* already did the echo */ + scc_socket_do_cmd_str(port, dcycs); + scc_ptr->modem_cmd_len = 0; + len = 0; + str[0] = 0; + } else if(c == 0x08) { + if(len <= 0) { + do_echo = 0; /* do not go past left margin */ + } else if(len == 2 && got_at) { + do_echo = 0; /* do not erase "AT" */ + } else { + /* erase a character */ + len--; + str[len] = 0; + } + } else if(c < 0x20) { + /* ignore all control characters, don't echo */ + /* includes line feeds and nulls */ + do_echo = 0; + } else { + /* other characters */ + if(len < SCC_MODEM_MAX_CMD_STR) { + str[len] = tolower(c); + str[len+1] = 0; + len++; + } + } + scc_ptr->modem_cmd_len = len; + if(do_echo) { + scc_add_to_readbuf(port, c, dcycs); /* echo */ + } +} + +void +scc_socket_do_cmd_str(int port, double dcycs) +{ + Scc *scc_ptr; + char *str; + int pos, len; + int ret_val; + int reg, reg_val; + int was_amp; + int c; + int i; + + scc_ptr = &(g_scc.scc_stat[port]); + + str = (char*)&(scc_ptr->modem_cmd_str[0]); // OG Added cast + printf("Got modem string :%s:=%02x %02x %02x\n", str, str[0], str[1], + str[2]); + + len = scc_ptr->modem_cmd_len; + str[len] = 0; + str[len+1] = 0; + str[len+2] = 0; + pos = -1; + if(len < 2) { + /* just ignore it */ + return; + } + if(str[0] != 'a' || str[1] != 't') { + return; + } + + /* Some AT command received--make sure socket 6501/6502 is open */ + printf("Some AT command received, sockfd=%d\n", scc_ptr->sockfd); + + pos = 2 - 1; + ret_val = 0; /* "OK" */ + was_amp = 0; + while(++pos < len) { + c = str[pos] + was_amp; + was_amp = 0; + switch(c) { + case '&': /* at& */ + was_amp = 0x100; + break; + case 'z': /* atz */ + scc_ptr->modem_mode = 0; + scc_ptr->modem_s0_val = 0; + pos = len; /* ignore any other commands */ + break; + case 'e': /* ate = echo */ + c = str[pos+1]; + if(c == '1') { + scc_ptr->modem_mode &= ~SCCMODEM_NOECHO; + pos++; + } else { + scc_ptr->modem_mode |= SCCMODEM_NOECHO; + pos++; + } + break; + case 'v': /* atv = verbose */ + c = str[pos+1]; + if(c == '1') { + scc_ptr->modem_mode &= ~SCCMODEM_NOVERBOSE; + pos++; + } else { + scc_ptr->modem_mode |= SCCMODEM_NOVERBOSE; + pos++; + } + break; + case 'o': /* ato = go online */ + printf("ato\n"); + if(scc_ptr->dcd && (scc_ptr->rdwrfd != -1) && + (scc_ptr->socket_state == 0)) { + printf("Going back online\n"); + scc_ptr->socket_state = 1; + scc_socket_modem_connect(port, dcycs); + ret_val = -1; + } + break; + case 'h': /* ath = hang up */ + printf("ath, hanging up\n"); + scc_socket_close(port, (scc_ptr->rdwrfd != -1), dcycs); + /* scc_socket_maybe_open_incoming(port, dcycs); */ + /* reopen listen */ + break; + case 'a': /* ata */ + printf("Doing ATA\n"); + scc_socket_do_answer(port, dcycs); + ret_val = -1; + break; + case 'd': /* atd */ + pos++; + c = str[pos]; + if(c == 't' || c == 'p') { + /* skip tone or pulse */ + pos++; + } + /* see if it is 111 */ + if(strcmp(&str[pos], "111") == 0) { + /* Do PPP! */ + } else { + /* get string to connect to */ + /* Shift string so hostname moves to str[0] */ + for(i = 0; i < len; i++) { + str[i] = str[pos]; + if(pos >= len) { + break; + } + pos++; + } + + } + scc_ptr->modem_dial_or_acc_mode = 1; + scc_socket_open_outgoing(port, dcycs); + ret_val = -1; + pos = len; /* always eat rest of the line */ + break; + case 's': /* atsnn=yy */ + pos++; + reg = 0; + while(1) { + c = str[pos]; + if(c < '0' || c > '9') { + break; + } + reg = (reg * 10) + c - '0'; + pos++; + } + if(c == '?') { + /* display S-register */ + if(reg == 0) { + scc_add_to_readbufv(port, dcycs, + "S0=%d\n", + scc_ptr->modem_s0_val); + } + break; + } + if(c != '=') { + break; + } + pos++; + reg_val = 0; + while(1) { + c = str[pos]; + if(c < '0' || c >'9') { + break; + } + reg_val = (reg_val * 10) + c - '0'; + pos++; + } + printf("ats%d = %d\n", reg, reg_val); + if(reg == 0) { + scc_ptr->modem_s0_val = reg_val; + } + pos--; + break; + default: + /* some command--peek into next chars to finish it */ + while(1) { + c = str[pos+1]; + if(c >= '0' && c <= '9') { + /* eat numbers */ + pos++; + continue; + } + if(c == '=') { + /* eat this as well */ + pos++; + continue; + } + /* else get out */ + break; + } + } + } + + if(ret_val >= 0) { + scc_socket_send_modem_code(port, ret_val, dcycs); + } +} + +void +scc_socket_send_modem_code(int port, int code, double dcycs) +{ + Scc *scc_ptr; + const char *str; + word32 modem_mode; + + scc_ptr = &(g_scc.scc_stat[port]); + + switch(code) { + case 0: str = "OK"; break; + case 1: str = "CONNECT"; break; + case 2: str = "RING"; break; + case 3: str = "NO CARRIER"; break; + case 4: str = "ERROR"; break; + case 5: str = "CONNECT 1200"; break; + case 13: str = "CONNECT 9600"; break; + case 16: str = "CONNECT 19200"; break; + case 25: str = "CONNECT 14400"; break; + case 85: str = "CONNECT 19200"; break; + default: + str = "ERROR"; + } + + printf("Sending modem code %d = %s\n", code, str); + + modem_mode = scc_ptr->modem_mode; + if(modem_mode & SCCMODEM_NOVERBOSE) { + /* just the number */ + scc_add_to_readbufv(port, dcycs, "%d", code); + scc_add_to_readbuf(port, 0x0d, dcycs); + } else { + scc_add_to_readbufv(port, dcycs, "%s\n", str); + } +} + +void +scc_socket_modem_hangup(int port, double dcycs) +{ + scc_socket_send_modem_code(port, 3, dcycs); +} + +void +scc_socket_modem_connect(int port, double dcycs) +{ + /* decide which code to send. Default to 1 if needed */ + scc_socket_send_modem_code(port, 13, dcycs); /*13=9600*/ +} + +void +scc_socket_modem_do_ring(int port, double dcycs) +{ + Scc *scc_ptr; + double diff_dcycs; + int num_rings; + + scc_ptr = &(g_scc.scc_stat[port]); + num_rings = scc_ptr->socket_num_rings; + if(num_rings > 0 && scc_ptr->socket_state == 0) { + num_rings--; + diff_dcycs = dcycs - scc_ptr->socket_last_ring_dcycs; + if(diff_dcycs < 2.0*1000*1000 && g_sim65816.g_serial_modem[port]) { + return; /* nothing more to do */ + } + printf("In modem_do_ring, ringing at %f\n", dcycs); + if(g_sim65816.g_serial_modem[port]) { + scc_socket_send_modem_code(port, 2, dcycs); /* RING */ + } else { + num_rings = 0; + } + scc_ptr->socket_num_rings = num_rings; + scc_ptr->socket_last_ring_dcycs = (int)dcycs; + if(num_rings <= 0) { + /* decide on answering */ + if(scc_ptr->modem_s0_val || (g_sim65816.g_serial_modem[port]==0)) { + scc_socket_do_answer(port, dcycs); + } else { + printf("No answer, closing socket\n"); + scc_socket_close(port, 0, dcycs); + } + } + } +} + +void +scc_socket_do_answer(int port, double dcycs) +{ + Scc *scc_ptr; + + scc_ptr = &(g_scc.scc_stat[port]); + scc_ptr->modem_dial_or_acc_mode = 2; + scc_accept_socket(port, dcycs); + if(scc_ptr->rdwrfd == -1) { + printf("Answer when rdwrfd=-1, closing\n"); + scc_socket_close(port, 1, dcycs); + /* send NO CARRIER message */ + } else { + scc_ptr->socket_state = 1; + scc_socket_telnet_reqs(port, dcycs); + printf("Send telnet reqs, rdwrfd=%d\n", scc_ptr->rdwrfd); + if(g_sim65816.g_serial_modem[port]) { + scc_socket_modem_connect(port, dcycs); + } + scc_ptr->dcd = 1; /* carrier on */ + scc_ptr->socket_state = 1; /* talk to socket */ + scc_ptr->socket_num_rings = 0; + } +} diff --git a/kegs/Src/sim65816.cpp b/kegs/Src/sim65816.cpp new file mode 100644 index 0000000..a1ce06d --- /dev/null +++ b/kegs/Src/sim65816.cpp @@ -0,0 +1,3080 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef _WIN32 +# define _WINSOCKAPI_ +#endif + +#undef printf + +#include + +#define INCLUDE_RCSID_C +#include "defc.h" +#undef INCLUDE_RCSID_C +#include "raster.h" +#include "protos_engine_c.h" +#include "driver.h" + +// 2.6 = 60 +// 2.49 = 63 +// 2.45 = 64 +// 2.43 = 64 +// 2.41 = 65! *** + +#define DEFAULT_GS_SPEED 2.5 //(2.41*(2.8/2.322)) + + +#include "moremem.h" +#include "sim65816.h" +#include "iwm.h" +#include "config.h" +#include "sound.h" +#include "video.h" +#include "saveState.h" +#include "graphcounter.h" +#include "marinetti.h" + + +s_sim65816 g_sim65816; +run_sim65816 r_sim65816; + +void run_sim65816::set_state(int _newstate) +{ + int s = _newstate ; + printf("state changed from %d to %d\n",r_sim65816.emulator_state,s); + emulator_state = s; +} + +int run_sim65816::get_state() +{ + return emulator_state; +} + +void run_sim65816::set_rewind_enable(int _onoff) +{ + g_savestate_enable = _onoff; + +} + + +//OG for regular exit, use quitEmulator() +void run_sim65816::quit_emulator() +{ + printf("*** quit_emulator ***\n"); + quit_requested = 1; +} + +void run_sim65816::restart_emulator() +{ + printf("*** quit_emulator ***\n"); + restart_requested = 1; +} + + +void run_sim65816::reset_quit() +{ + printf("*** reset_quit ***\n"); + quit_requested = 0; +} + +void run_sim65816::reset_restart() +{ + printf("*** reset_restart ***\n"); + restart_requested = 0; +} + +int run_sim65816::should_emulator_terminate() +{ + return (quit_requested || restart_requested); +} + +int run_sim65816::is_emulator_offscreen_available() +{ + return ( emulator_state & OFFSCREEN_AVAILABLE ); +} + +int run_sim65816::is_emulator_in_640mode() +{ + + return g_video.g_a2_line_kimage[0]==&s_video.g_kimage_superhires && (g_slow_memory_ptr[0x19d00]&0x80) ; +} +void refresh_offscreen() +{ + printf("*** forcing offscreen refresh! ***\n"); + // recalcul la palette + r_sim65816.check_update_emulator_runtime_config(); + // regnre l'cran + g_video.g_screen_redraw_skip_count = 0; // pour forcer le refresh indpendamment du frame rate effectif + video_update(); + // force son rafraichissemnt + // OG NE PAS FAIRE LE REFRESH ICI CAR ON NE SAIT PAS D'OU VIENT LA DEMANDE!!! + // refresh_video(1); +} + + +void run_sim65816::set_color_mode(colormodeenum _cm) +{ + color_mode = _cm; + printf("color_mode set to %d\n",_cm); + g_video.g_needfullrefreshfornextframe = 1 ; + request_update_emulator_runtime_config(); + + if (r_sim65816.get_state()==IN_PAUSE) + refresh_offscreen(); + + + +} + + +void run_sim65816::set_video_fx(videofxenum _vfx) +{ + video_fx = _vfx; + g_video.g_needfullrefreshfornextframe = 1 ; + printf("video fx set to %d\n",_vfx); +#ifdef DRIVER_IOS + { + extern void x_set_video_fx(videofxenum _vfx); + x_set_video_fx(_vfx); + } +#endif +} + + +int run_sim65816::is_emulator_initialized() +{ + int s = r_sim65816.get_state(); + return (s==RUNNING) || (s==IN_PAUSE); +} + +void run_sim65816::request_update_emulator_runtime_config() +{ + emulator_config_requested=1; +} + +void run_sim65816::check_update_emulator_runtime_config() +{ + + if (!emulator_config_requested) + return ; + + emulator_config_requested=0; + + extern void video_update_palette_color(); + + if (color_mode == COLORMODE_BW) + g_video.g_cur_a2_stat |= ALL_STAT_COLOR_C021; + else + g_video.g_cur_a2_stat &= ~ALL_STAT_COLOR_C021; + + // recalcul les palettes + video_update_palette_color(); + + for(int i=0;i<200;i++) + for(int j=0;j<8;j++) + s_video.g_saved_line_palettes[i][j] = -1; + + // remets jour les borders (cf. change_border_color) + g_video.g_border_last_vbl_changes = 1; + for(int i=0;i<270;i++) + g_video.g_cur_border_colors[i] = -1; + + + // invalide la mmoire + for(int i = 0;idcycs; + dcycs = start_dcycs; + + data_wrap = 0; + /* find first data entry */ + while(data_wrap < 2 && (log_data_ptr->dcycs < dcycs)) { + log_data_ptr++; + if(log_data_ptr >= g_log_data_end_ptr) { + log_data_ptr = g_log_data_start_ptr; + data_wrap++; + } + } + fprintf(pcfile, "start_dcycs: %9.2f\n", start_dcycs); + + for(i = 0; i < PC_LOG_LEN; i++) { + dcycs = log_pc_ptr->dcycs; + while((data_wrap < 2) && (log_data_ptr->dcycs <= dcycs) && + (log_data_ptr->dcycs >= start_dcycs)) { + fprintf(pcfile, "DATA set %06x = %06x (%d) %9.2f\n", + log_data_ptr->addr, log_data_ptr->val, + log_data_ptr->size, + log_data_ptr->dcycs - start_dcycs); + log_data_ptr++; + if(log_data_ptr >= g_log_data_end_ptr) { + log_data_ptr = g_log_data_start_ptr; + data_wrap++; + } + } + dbank = (log_pc_ptr->dbank_kpc >> 24) & 0xff; + kpc = log_pc_ptr->dbank_kpc & 0xffffff; + instr = log_pc_ptr->instr; + psr = (log_pc_ptr->psr_acc >> 16) & 0xffff;; + acc = log_pc_ptr->psr_acc & 0xffff;; + xreg = (log_pc_ptr->xreg_yreg >> 16) & 0xffff;; + yreg = log_pc_ptr->xreg_yreg & 0xffff;; + stack = (log_pc_ptr->stack_direct >> 16) & 0xffff;; + direct = log_pc_ptr->stack_direct & 0xffff;; + + num = log_pc_ptr - g_log_pc_start_ptr; + + accsize = 2; + xsize = 2; + if(psr & 0x20) { + accsize = 1; + } + if(psr & 0x10) { + xsize = 1; + } + + fprintf(pcfile, "%04x: A:%04x X:%04x Y:%04x P:%03x " + "S:%04x D:%04x B:%02x %9.2f ", i, + acc, xreg, yreg, psr, stack, direct, dbank, + (dcycs-start_dcycs)); + + do_dis(pcfile, kpc, accsize, xsize, 1, instr); + log_pc_ptr++; + if(log_pc_ptr >= g_log_pc_end_ptr) { + log_pc_ptr = g_log_pc_start_ptr; + } + } + + fclose(pcfile); +} + + +word32 +toolbox_debug_4byte(word32 addr) +{ + word32 part1, part2; + + /* If addr looks safe, use it */ + if(addr > 0xbffc) { + return (word32)-1; + } + + part1 = get_memory16_c(addr, 0); + part1 = (part1 >> 8) + ((part1 & 0xff) << 8); + part2 = get_memory16_c(addr+2, 0); + part2 = (part2 >> 8) + ((part2 & 0xff) << 8); + + return (part1 << 16) + part2; +} + +void +toolbox_debug_c(word32 xreg, word32 stack, double *cyc_ptr) +{ + int pos; + + pos = g_toolbox_log_pos; + + stack += 9; + g_toolbox_log_array[pos][0] = (word32)(g_sim65816.g_last_vbl_dcycs + *cyc_ptr); + g_toolbox_log_array[pos][1] = stack+1; + g_toolbox_log_array[pos][2] = xreg; + g_toolbox_log_array[pos][3] = toolbox_debug_4byte(stack+1); + g_toolbox_log_array[pos][4] = toolbox_debug_4byte(stack+5); + g_toolbox_log_array[pos][5] = toolbox_debug_4byte(stack+9); + g_toolbox_log_array[pos][6] = toolbox_debug_4byte(stack+13); + g_toolbox_log_array[pos][7] = toolbox_debug_4byte(stack+17); + + pos++; + if(pos >= TOOLBOX_LOG_LEN) { + pos = 0; + } + + g_toolbox_log_pos = pos; +} + +void +show_toolbox_log() +{ + int pos; + int i; + + pos = g_toolbox_log_pos; + + for(i = TOOLBOX_LOG_LEN - 1; i >= 0; i--) { + printf("%2d:%2d: %08x %06x %04x: %08x %08x %08x %08x %08x\n", + i, pos, + g_toolbox_log_array[pos][0], + g_toolbox_log_array[pos][1], + g_toolbox_log_array[pos][2], + g_toolbox_log_array[pos][3], + g_toolbox_log_array[pos][4], + g_toolbox_log_array[pos][5], + g_toolbox_log_array[pos][6], + g_toolbox_log_array[pos][7]); + pos++; + if(pos >= TOOLBOX_LOG_LEN) { + pos = 0; + } + } +} + +#if 0 +/* get_memory_c is not used, get_memory_asm is, but this does what the */ +/* assembly language would do */ +word32 +get_memory_c(word32 loc, int diff_cycles) +{ + byte *addr; + word32 result; + int index; + +#ifdef CHECK_BREAKPOINTS + check_breakpoints_c(loc); +#endif + + index = loc >> 8; + result = page_info[index].rd; + if(result & BANK_IO_BIT) { + return get_memory_io(loc, diff_cycles); + } + + addr = (byte *)((result & 0xffffff00) + (loc & 0xff)); + + return *addr; +} +#endif + + +word32 +get_memory_io(word32 loc, double *cyc_ptr) +{ + int tmp; + + if(loc > 0xffffff) { + halt_printf("get_memory_io:%08x out of range==halt!\n", loc); + return 0; + } + + tmp = loc & 0xfef000; + if(tmp == 0xc000 || tmp == 0xe0c000) { + return(io_read(loc & 0xfff, cyc_ptr)); + } + + /* Else it's an illegal addr...skip if memory sizing */ + if(loc >= g_sim65816.g_mem_size_total) { + if((loc & 0xfffe) == 0) { +#if 0 + printf("get_io assuming mem sizing, not halting\n"); +#endif + return 0; + } + } + + /* Skip reads to f80000 and f00000, just return 0 */ + if((loc & 0xf70000) == 0xf00000) { + return 0; + } + + if((loc & 0xff0000) == 0xef0000) { + /* DOC RAM */ + return (g_sound.doc_ram[loc & 0xffff]); + } + + g_sim65816.g_code_yellow++; + if(r_sim65816.g_ignore_bad_acc && !r_sim65816.g_user_halt_bad) { + /* print no message, just get out. User doesn't want */ + /* to be bothered by buggy programs */ + return 0; + } + + printf("get_memory_io for addr: %06x\n", loc); + printf("stat for addr: %06x = %p\n", loc, + GET_PAGE_INFO_RD((loc >> 8) & 0xffff)); + set_halt(r_sim65816.g_halt_on_bad_read | r_sim65816.g_user_halt_bad); + + return 0; +} + +#if 0 +word32 +get_memory16_pieces(word32 loc, int diff_cycles) +{ + return(get_memory_c(loc, diff_cycles) + + (get_memory_c(loc+1, diff_cycles) << 8)); +} + +word32 +get_memory24(word32 loc, int diff_cycles) +{ + return(get_memory_c(loc, diff_cycles) + + (get_memory_c(loc+1, diff_cycles) << 8) + + (get_memory_c(loc+2, diff_cycles) << 16)); +} +#endif + +#if 0 +void +set_memory(word32 loc, int val, int diff_cycles) +{ + byte *ptr; + word32 new_addr; + word32 tmp; + word32 or_val; + int or_pos; + int old_slow_val; + +#ifdef CHECK_BREAKPOINTS + check_breakpoints_c(loc); +#endif + + tmp = GET_PAGE_INFO_WR((loc>>8) & 0xffff); + if(tmp & BANK_IO) { + set_memory_io(loc, val, diff_cycles); + return; + } + + if((loc & 0xfef000) == 0xe0c000) { + printf("set_memory_special: non-io for addr %08x, %02x, %d\n", + loc, val, diff_cycles); + halt_printf("tmp: %08x\n", tmp); + } + + ptr = (byte *)(tmp & (~0xff)); + + new_addr = loc & 0xffff; + old_slow_val = val; + + if(tmp & BANK_SHADOW) { + old_slow_val = g_slow_memory_ptr[new_addr]; + } else if(tmp & BANK_SHADOW2) { + new_addr += 0x10000; + old_slow_val = g_slow_memory_ptr[new_addr]; + } + + if(old_slow_val != val) { + g_slow_memory_ptr[new_addr] = val; + or_pos = (new_addr >> SHIFT_PER_CHANGE) & 0x1f; + or_val = DEP1(1, or_pos, 0); + if((new_addr >> CHANGE_SHIFT) >= SLOW_MEM_CH_SIZE) { + printf("new_addr: %08x\n", new_addr); + x_exit(12); + } + g_video.slow_mem_changed[(new_addr & 0xffff) >> CHANGE_SHIFT] |= or_val; + } + + ptr[loc & 0xff] = val; + +} +#endif + +void +set_memory_io(word32 loc, int val, double *cyc_ptr) +{ + word32 tmp; + + tmp = loc & 0xfef000; + if(tmp == 0xc000 || tmp == 0xe0c000) { + io_write(loc, val, cyc_ptr); + return; + } + + /* Else it's an illegal addr */ + if(loc >= g_sim65816.g_mem_size_total) { + if((loc & 0xfffe) == 0) { +#if 0 + printf("set_io assuming mem sizing, not halting\n"); +#endif + return; + } + } + + /* ignore writes to ROM */ + if((loc & 0xfc0000) == 0xfc0000) { + return; + } + + if((loc & 0xff0000) == 0xef0000) { + /* DOC RAM */ + g_sound.doc_ram[loc & 0xffff] = val; + return; + } + + if(r_sim65816.g_ignore_bad_acc && !r_sim65816.g_user_halt_bad) { + /* print no message, just get out. User doesn't want */ + /* to be bothered by buggy programs */ + return; + } + + if((loc & 0xffc000) == 0x00c000) { + printf("set_memory %06x = %02x, warning\n", loc, val); + return; + } + + halt_printf("set_memory %06x = %02x, stopping\n", loc, val); + + return; +} + + +#if 0 +void +check_breakpoints_c(word32 loc) +{ + int index; + int count; + int i; + + index = (loc & (MAX_BP_INDEX-1)); + count = breakpoints[index].count; + if(count) { + for(i = 0; i < count; i++) { + if(loc == breakpoints[index].addrs[i]) { + halt_printf("Write hit breakpoint %d!\n", i); + } + } + } +} +#endif + + +void +show_regs_act(Engine_reg *eptr) +{ + int tmp_acc, tmp_x, tmp_y, tmp_psw; + int kpc; + int direct_page, dbank; + int stack; + + kpc = eptr->kpc; + tmp_acc = eptr->acc; + direct_page = eptr->direct; + dbank = eptr->dbank; + stack = eptr->stack; + + tmp_x = eptr->xreg; + tmp_y = eptr->yreg; + + tmp_psw = eptr->psr; + + printf(" PC=%02x.%04x A=%04x X=%04x Y=%04x P=%03x", + kpc>>16, kpc & 0xffff ,tmp_acc,tmp_x,tmp_y,tmp_psw); + printf(" S=%04x D=%04x B=%02x,cyc:%.3f\n", stack, direct_page, + dbank, g_sim65816.g_cur_dcycs); +} + +void +show_regs() +{ + show_regs_act(&g_sim65816.engine); +} + + +//OG change exit() to x_exit() +extern void x_exit(int); + +void my_exit(int ret) +{ + end_screen(); + printf("exiting (ret=%d)\n",ret); + x_exit(ret); +} + + +void +do_reset() +{ + + g_moremem.g_c068_statereg = 0x08 + 0x04 + 0x01; /* rdrom, lcbank2, intcx */ + g_moremem.g_c035_shadow_reg = 0; + + g_moremem.g_c08x_wrdefram = 1; + g_moremem.g_c02d_int_crom = 0; + g_moremem.g_c023_val = 0; + g_moremem.g_c041_val = 0; + + g_sim65816.engine.psr = (g_sim65816.engine.psr | 0x134) & ~(0x08); + g_sim65816.engine.stack = 0x100 + (g_sim65816.engine.stack & 0xff); + g_sim65816.engine.dbank = 0; + g_sim65816.engine.direct = 0; + g_sim65816.engine.xreg &= 0xff; + g_sim65816.engine.yreg &= 0xff; + g_sim65816.g_wait_pending = 0; + g_sim65816.g_stp_pending = 0; + + + video_reset(); + adb_reset(); + iwm_reset(); + scc_reset(); + sound_reset(g_sim65816.g_cur_dcycs); + setup_pageinfo(); + change_display_mode(g_sim65816.g_cur_dcycs); + + g_moremem.g_irq_pending = 0; + + g_sim65816.engine.kpc = get_memory16_c(0x00fffc, 0); + + //set_bp(g_sim65816.engine.kpc); +// set_bp(0x666,(enum mode_breakpoint)(BRK_X|BRK_PATCH),"067B:60"); + + g_stepping = 0; + + // OG Cleared remaining IRQS on RESET + { + +/* + extern int g_scan_int_events ; + extern int g_c023_val; + + + #define REMOVEIRQ(ADR) { extern int ADR; if (ADR) { remove_irq(); ADR=0; } } + #define CLEARIRQ(ADR) { extern int ADR; ADR=0; } + + REMOVEIRQ(g_adb_kbd_srq_sent); + REMOVEIRQ(g_adb_data_int_sent); + REMOVEIRQ(g_adb_mouse_int_sent); + REMOVEIRQ(c046_vbl_irq_pending); + REMOVEIRQ(c046_25sec_irq_pend); + REMOVEIRQ(c023_scan_int_irq_pending); + REMOVEIRQ(c023_1sec_int_irq_pending); + REMOVEIRQ(c046_vbl_irq_pending); + + CLEARIRQ(c041_en_25sec_ints); + CLEARIRQ(c041_en_vbl_ints); + CLEARIRQ(c041_en_switch_ints); + CLEARIRQ(c041_en_move_ints); + CLEARIRQ(c041_en_mouse); + + g_sim65816.g_scan_int_events = 0; + + initialize_events(); +*/ + if (g_moremem.g_irq_pending) + halt_printf("*** irq remainings...\n"); + +/* + g_moremem.g_irq_pending = 0; + // reinitiliase zip speed (not sure)??? + // g_moremem.g_zipgs_reg_c05a = 0x80; + */ + } + +} + +#define CHECK(start, var, value, var1, var2) \ + var2 = PTR2WORD(&(var)); \ + var1 = PTR2WORD((start)); \ + if((var2 - var1) != value) { \ + printf("CHECK: " #var " is 0x%x, but " #value " is 0x%x\n", \ + (var2 - var1), value); \ + x_exit(5); \ + } + +void +check_engine_asm_defines() +{ + Fplus fplus; + Fplus *fplusptr; + Pc_log pclog; + Pc_log *pcptr; + Engine_reg ereg; + Engine_reg *eptr; + word32 val1; + word32 val2; + + eptr = &ereg; + CHECK(eptr, eptr->fcycles, ENGINE_FCYCLES, val1, val2); + CHECK(eptr, eptr->fplus_ptr, ENGINE_FPLUS_PTR, val1, val2); + CHECK(eptr, eptr->acc, ENGINE_REG_ACC, val1, val2); + CHECK(eptr, eptr->xreg, ENGINE_REG_XREG, val1, val2); + CHECK(eptr, eptr->yreg, ENGINE_REG_YREG, val1, val2); + CHECK(eptr, eptr->stack, ENGINE_REG_STACK, val1, val2); + CHECK(eptr, eptr->dbank, ENGINE_REG_DBANK, val1, val2); + CHECK(eptr, eptr->direct, ENGINE_REG_DIRECT, val1, val2); + CHECK(eptr, eptr->psr, ENGINE_REG_PSR, val1, val2); + CHECK(eptr, eptr->kpc, ENGINE_REG_KPC, val1, val2); + + pcptr = &pclog; + CHECK(pcptr, pcptr->dbank_kpc, LOG_PC_DBANK_KPC, val1, val2); + CHECK(pcptr, pcptr->instr, LOG_PC_INSTR, val1, val2); + CHECK(pcptr, pcptr->psr_acc, LOG_PC_PSR_ACC, val1, val2); + CHECK(pcptr, pcptr->xreg_yreg, LOG_PC_XREG_YREG, val1, val2); + CHECK(pcptr, pcptr->stack_direct, LOG_PC_STACK_DIRECT, val1, val2); + if(LOG_PC_SIZE != sizeof(pclog)) { + printf("LOG_PC_SIZE: %d != sizeof=%d\n", LOG_PC_SIZE, + (int)sizeof(pclog)); + x_exit(2); + } + + fplusptr = &fplus; + CHECK(fplusptr, fplusptr->plus_1, FPLUS_PLUS_1, val1, val2); + CHECK(fplusptr, fplusptr->plus_2, FPLUS_PLUS_2, val1, val2); + CHECK(fplusptr, fplusptr->plus_3, FPLUS_PLUS_3, val1, val2); + CHECK(fplusptr, fplusptr->plus_x_minus_1, FPLUS_PLUS_X_M1, val1, val2); +} + + +byte * +memalloc_align(int size, int skip_amt, void **alloc_ptr) +{ + byte *bptr; + word32 addr; + word32 offset; + + skip_amt = MAX(256, skip_amt); + bptr = (byte*)calloc(size + skip_amt + 256, 1); // OG Added cast + if(alloc_ptr) { + /* Save allocation address */ + *alloc_ptr = bptr; + } + + addr = PTR2WORD(bptr) & 0xff; + + /* must align bptr to be 256-byte aligned */ + /* this code should work even if ptrs are > 32 bits */ + + offset = ((addr + skip_amt - 1) & (~0xff)) - addr; + + return (bptr + offset); +} + + +void +memory_ptr_init() +{ + word32 mem_size; + + /* This routine may be called several times--each time the ROM file */ + /* changes this will be called */ + mem_size = MIN(0xdf0000, g_sim65816.g_mem_size_base + g_sim65816.g_mem_size_exp); + g_sim65816.g_mem_size_total = mem_size; + + // OG using memory_ptr_shut() instead + memory_ptr_shut(); + + g_memory_ptr = memalloc_align(mem_size, 256, &g_memory_alloc_ptr); + + printf("RAM size is 0 - %06x (%.2fMB)\n", mem_size, (double)mem_size/(1024.0*1024.0)); +} + +// OG Added memory_ptr_shut +void +memory_ptr_shut() +{ + if(g_memory_alloc_ptr) + { + free(g_memory_alloc_ptr); + g_memory_alloc_ptr = 0; + } + g_memory_ptr = 0; +} + + + + + + +void +kegsmain_init(int argc, char **argv) +{ + int diff; + printf("kegsmain"); + + r_sim65816.set_state(INITIALIZING); + + //initSavedStateModule(); + + // OG Restoring globals + sim65816_initglobals(); + moremem_init(); + +//OG Disabling argument parsing +#ifndef ACTIVEGS + + int skip_amt; + int tmp1; + + /* parse args */ + for(int i = 1; i < argc; i++) { + if(!strcmp("-badrd", argv[i])) { + printf("Halting on bad reads\n"); + r_sim65816.g_halt_on_bad_read = 2; + } else if(!strcmp("-noignbadacc", argv[i])) { + printf("Not ignoring bad memory accesses\n"); + r_sim65816.g_ignore_bad_acc = 0; + } else if(!strcmp("-noignhalt", argv[i])) { + printf("Not ignoring code red halts\n"); + r_sim65816.g_ignore_halts = 0; + } else if(!strcmp("-test", argv[i])) { + printf("Allowing testing\n"); + g_sim65816.g_testing_enabled = 1; + } else if(!strcmp("-hpdev", argv[i])) { + printf("Using /dev/audio\n"); + g_sim65816.g_use_alib = 0; + } else if(!strcmp("-alib", argv[i])) { + printf("Using Aserver audio server\n"); + g_sim65816.g_use_alib = 1; + } else if(!strcmp("-24", argv[i])) { + printf("Using 24-bit visual\n"); + g_sim65816.g_force_depth = 24; + } else if(!strcmp("-16", argv[i])) { + printf("Using 16-bit visual\n"); + g_sim65816.g_force_depth = 16; + } else if(!strcmp("-15", argv[i])) { + printf("Using 15-bit visual\n"); + g_sim65816.g_force_depth = 15; + } else if(!strcmp("-mem", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + x_exit(1); + } + g_sim65816.g_mem_size_exp = strtol(argv[i+1], 0, 0) & 0x00ff0000; + printf("Using %d as memory size\n", g_sim65816.g_mem_size_exp); + i++; + } else if(!strcmp("-skip", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + x_exit(1); + } + skip_amt = strtol(argv[i+1], 0, 0); + printf("Using %d as skip_amt\n", skip_amt); + g_video.g_screen_redraw_skip_amt = skip_amt; + i++; + } else if(!strcmp("-audio", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + x_exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Using %d as audio enable val\n", tmp1); + g_sound.g_audio_enable = tmp1; + i++; + } + /* + else if(!strcmp("-arate", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + x_exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Using %d as preferred audio rate\n", tmp1); + g_preferred_rate = tmp1; + i++; + }*/ + else if(!strcmp("-v", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + x_exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Setting g_sim65816.Verbose = 0x%03x\n", tmp1); + Verbose = tmp1; + i++; +#ifndef __NeXT__ + } else if(!strcmp("-display", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + x_exit(1); + } + printf("Using %s as display\n", argv[i+1]); + sprintf(g_sim65816.g_display_env, "DISPLAY=%s", argv[i+1]); + putenv(&g_sim65816.g_display_env[0]); + i++; +#endif + } +#ifdef DRIVER_LINUX + else if(!strcmp("-noshm", argv[i])) { + printf("Not using X shared memory\n"); + g_use_shmem = 0; + } +#endif + else if(!strcmp("-joystick", argv[i])) { + printf("Ignoring -joystick option\n"); + } else if(!strcmp("-dhr140", argv[i])) { + printf("Using simple dhires color map\n"); + g_video.g_use_dhr140 = 1; + } else if(!strcmp("-bw", argv[i])) { + printf("Forcing black-and-white hires modes\n"); + g_video.g_cur_a2_stat |= ALL_STAT_COLOR_C021; + r_sim65816.set_color_mode(COLORMODE_BW); + // s_video.g_use_bw_hires = 1; + } else { + printf("Bad option: %s\n", argv[i]); + x_exit(3); + } + } +#endif + + check_engine_asm_defines(); + fixed_memory_ptrs_init(); + + if(sizeof(word32) != 4) { + printf("sizeof(word32) = %d, must be 4!\n", + (int)sizeof(word32)); + x_exit(1); + } + + if(!g_engine_c_mode) { + diff = &defs_instr_end_8 - &defs_instr_start_8; + if(diff != 1) { + printf("defs_instr_end_8 - start is %d\n",diff); + x_exit(1); + } + + diff = &defs_instr_end_16 - &defs_instr_start_16; + if(diff != 1) { + printf("defs_instr_end_16 - start is %d\n", diff); + x_exit(1); + } + + diff = &op_routs_end - &op_routs_start; + if(diff != 1) { + printf("op_routs_end - start is %d\n", diff); + x_exit(1); + } + } + + + iwm_init(); + config_init(); + + load_roms_init_memory(); + + init_reg(); + clear_halt(); + + initialize_events(); + + video_init(); + + sound_init(); + marinetti_init(); + scc_init(); + adb_init(); + joystick_init(); + if(g_sim65816.g_rom_version >= 3) { + g_moremem.g_c036_val_speed |= 0x40; /* set power-on bit */ + } + + + g_num_breakpoints = 0; +#ifdef ACTIVEGS + extern void apply_breakpoints(); + apply_breakpoints(); +#endif + + do_reset(); + g_stepping = 0; + + + + r_sim65816.request_update_emulator_runtime_config(); + r_sim65816.set_state(RUNNING); + if (g_driver.x_post_event) + g_driver.x_post_event("emulator_launched"); +} + +void kegsmain_shut() +{ + + + /* If we get here, we hit a breakpoint, call debug intfc */ + do_debug_intfc(); + + r_sim65816.set_state(SHUTTING_DOWN); + + marinetti_shutdown(); + sound_shutdown(); + + adb_shut(); + iwm_shut(); + fixed_memory_ptrs_shut(); + load_roms_shut_memory(); + clear_fatal_logs(); + + end_screen(); + + r_sim65816.set_state(NO_INITIALIZED); + + //return 0; +} + + +int +kegsmain(int argc, char **argv) +{ + + kegsmain_init(argc,argv); + + #ifdef ACTIVEGS + { + extern void disableConsole(); + disableConsole(); + } + #endif + +// do go +extern int g_config_control_panel; +extern void run_prog_init(); +extern void run_prog_shut(); +extern int run_prog_loop(); + + g_config_control_panel = 0; + clear_halt(); + + run_prog_init(); + + while(1) + { + int ret = run_prog_loop(); + if (!ret) + break; + } + + run_prog_shut(); + + show_regs(); + g_config_control_panel = 1; + + kegsmain_shut(); + return 0; +} + + +void +load_roms_init_memory() +{ + config_load_roms(); + memory_ptr_init(); + clk_setup_bram_version(); /* Must be after config_load_roms */ + if(g_sim65816.g_rom_version >= 3) { + g_moremem.g_c036_val_speed |= 0x40; /* set power-on bit */ + } else { + g_moremem.g_c036_val_speed &= (~0x40); /* clear the bit */ + } + do_reset(); + + /* if user booted ROM 01, switches to ROM 03, then switches back */ + /* to ROM 01, then the reset routines call to Tool $0102 looks */ + /* at uninitialized $e1/15fe and if it is negative it will JMP */ + /* through $e1/1688 which ROM 03 left pointing to fc/0199 */ + /* So set e1/15fe = 0 */ + set_memory16_c(0xe115fe, 0, 0); +} + +// OG Added load_roms_shut_memory +void load_roms_shut_memory() +{ + memory_ptr_shut(); +} + +#ifndef ACTIVEGS + +void +kegs_expand_path(char *out_ptr, const char *in_ptr, int maxlen) +{ + char name_buf[256]; + const char *tmp_ptr; + int name_len; + int in_char; + int state; + + out_ptr[0] = 0; + + name_len = 0; + state = 0; + + /* See if in_ptr has ${} notation, replace with getenv or argv0 */ + while(maxlen > 0) { + in_char = *in_ptr++; + *out_ptr++ = in_char; + maxlen--; + if(state == 0) { + /* No $ seen yet, look for it */ + if(in_char == '$') { + state = 1; + } + } else if(state == 1) { + /* See if next char is '{' (dummy }) */ + if(in_char == '{') { /* add dummy } */ + state = 2; + name_len = 0; + out_ptr -= 2; + } else { + state = 0; + } + } else if(state == 2) { + /* fill name_buf ... dummy '{' */ + out_ptr--; + if(in_char == '}') { + name_buf[name_len] = 0; + + /* got token, now look it up */ + tmp_ptr = ""; + if(!strncmp("0", name_buf, 128)) { + /* Replace ${0} with g_argv0_path */ + tmp_ptr = &(g_argv0_path[0]); + } else { + tmp_ptr = getenv(name_buf); + if(tmp_ptr == 0) { + tmp_ptr = ""; + } + } + strncpy(out_ptr, tmp_ptr, maxlen); + out_ptr += strlen(tmp_ptr); + maxlen -= strlen(tmp_ptr); + state = 0; + } else { + name_buf[name_len++] = in_char; + } + } + if(in_char == 0) { + /* make sure its null terminated */ + *out_ptr++ = 0; + break; + } + } +} + +void +setup_kegs_file(char *outname, int maxlen, int ok_if_missing, + int can_create_file, const char **name_ptr) +{ + char local_path[256]; + struct stat stat_buf; + const char **path_ptr; + const char **cur_name_ptr, **save_path_ptr; + int ret; + + outname[0] = 0; + + path_ptr = &g_kegs_default_paths[0]; + + save_path_ptr = path_ptr; + while(*path_ptr) { + kegs_expand_path(&(local_path[0]), *path_ptr, 250); + cur_name_ptr = name_ptr; + while(*cur_name_ptr) { + strcpy(outname, &(local_path[0])); + strncat(outname, *cur_name_ptr, 255-strlen(outname)); + if(!ok_if_missing) { + printf("Trying '%s'\n", outname); + } + ret = stat(outname, &stat_buf); + if(ret == 0) { + /* got it! */ + return; + } + cur_name_ptr++; + } + path_ptr++; + } + + outname[0] = 0; + if(ok_if_missing > 0) { + return; + } + + /* couldn't find it, print out all the attempts */ + path_ptr = save_path_ptr; + fatal_printf("Could not find required file \"%s\" in any of these " + "directories:\n", *name_ptr); + while(*path_ptr) { + fatal_printf(" %s\n", *path_ptr++); + } + + if(can_create_file) { + // Ask user if it's OK to create the file + x_dialog_create_kegs_conf(*name_ptr); + can_create_file = 0; + + // But clear out the fatal_printfs first + clear_fatal_logs(); + setup_kegs_file(outname, maxlen, ok_if_missing, + can_create_file, name_ptr); + // It's one-level of recursion--it cannot loop since we + // clear can_create_file. + // If it returns, then there was succes and we should get out + return; + } else if(ok_if_missing) { + /* Just show an alert and return if ok_if_missing < 0 */ + x_show_alert(0, 0); + return; + } + + system("pwd"); + + my_exit(2); +} + +#endif + + +void +initialize_events() +{ + int i; + + for(i = 1; i < MAX_EVENTS; i++) { + g_sim65816.g_event_list[i-1].next = &g_sim65816.g_event_list[i]; + } + g_sim65816.g_event_free.next = &g_sim65816.g_event_list[0]; + g_sim65816.g_event_list[MAX_EVENTS-1].next = 0; + + g_sim65816.g_event_start.next = 0; + g_sim65816.g_event_start.dcycs = 0.0; + + add_event_entry(DCYCS_IN_16MS, EV_60HZ); +} + +void +check_for_one_event_type(int type) +{ + Event *ptr; + int count; + int depth; + + count = 0; + depth = 0; + ptr = g_sim65816.g_event_start.next; + while(ptr != 0) { + depth++; + if(ptr->type == type) { + count++; + if(count != 1) { + halt_printf("in check_for_1, type %d found at " + "depth: %d, count: %d, at %f\n", + type, depth, count, ptr->dcycs); + } + } + ptr = ptr->next; + } +} + + +void +add_event_entry(double dcycs, int type) +{ + Event *this_event; + Event *ptr, *prev_ptr; + int tmp_type; + int done; + + this_event = g_sim65816.g_event_free.next; + if(this_event == 0) { + halt_printf("Out of queue entries!\n"); + show_all_events(); + return; + } + g_sim65816.g_event_free.next = this_event->next; + + this_event->type = type; + + tmp_type = type & 0xff; + if((dcycs < 0.0) || (dcycs > (g_sim65816.g_cur_dcycs + 50*1000*1000.0)) || + ((dcycs < g_sim65816.g_cur_dcycs) && (tmp_type != EV_SCAN_INT))) { + halt_printf("add_event: dcycs: %f, type:%05x, cur_dcycs: %f!\n", + dcycs, type, g_sim65816.g_cur_dcycs); + dcycs = g_sim65816.g_cur_dcycs + 1000.0; + } + + ptr = g_sim65816.g_event_start.next; + if(ptr && (dcycs < ptr->dcycs)) { + /* create event before next expected event */ + /* do this by setting HALT_EVENT */ + set_halt(HALT_EVENT); + } + + prev_ptr = &g_sim65816.g_event_start; + ptr = g_sim65816.g_event_start.next; + + done = 0; + while(!done) { + if(ptr == 0) { + this_event->next = ptr; + this_event->dcycs = dcycs; + prev_ptr->next = this_event; + return; + } else { + if(ptr->dcycs < dcycs) { + /* step across this guy */ + prev_ptr = ptr; + ptr = ptr->next; + } else { + /* go in front of this guy */ + this_event->dcycs = dcycs; + this_event->next = ptr; + prev_ptr->next = this_event; + return; + } + } + } +} + + +double +remove_event_entry(int type) +{ + Event *ptr, *prev_ptr; + Event *next_ptr; + + ptr = g_sim65816.g_event_start.next; + prev_ptr = &g_sim65816.g_event_start; + + while(ptr != 0) { + if((ptr->type & 0xffff) == type) { + /* got it, remove it */ + next_ptr = ptr->next; + prev_ptr->next = next_ptr; + + /* Add ptr to free list */ + ptr->next = g_sim65816.g_event_free.next; + g_sim65816.g_event_free.next = ptr; + + return ptr->dcycs; + } + prev_ptr = ptr; + ptr = ptr->next; + } + + halt_printf("remove event_entry: %08x, but not found!\n", type); + if((type & 0xff) == EV_DOC_INT) { + printf("DOC, g_doc_saved_ctl = %02x\n", g_sound.g_doc_saved_ctl); + } +#ifdef HPUX + U_STACK_TRACE(); +#endif + show_all_events(); + + return 0.0; +} + +void +add_event_stop(double dcycs) +{ + add_event_entry(dcycs, EV_STOP); +} + +void +add_event_doc(double dcycs, int osc) +{ + if(dcycs < g_sim65816.g_cur_dcycs) { + dcycs = g_sim65816.g_cur_dcycs; +#if 0 + halt_printf("add_event_doc: dcycs: %f, cur_dcycs: %f\n", + dcycs, g_sim65816.g_cur_dcycs); +#endif + } + + add_event_entry(dcycs, EV_DOC_INT + (osc << 8)); +} + +void +add_event_scc(double dcycs, int type) +{ + if(dcycs < g_sim65816.g_cur_dcycs) { + dcycs = g_sim65816.g_cur_dcycs; + } + + add_event_entry(dcycs, EV_SCC + (type << 8)); +} + +void +add_event_vbl() +{ + double dcycs; + + dcycs = g_sim65816.g_last_vbl_dcycs + (DCYCS_IN_16MS * (192.0/262.0)); + add_event_entry(dcycs, EV_VBL_INT); +} + +void +add_event_vid_upd(int line) +{ + double dcycs; + + dcycs = g_sim65816.g_last_vbl_dcycs + ((DCYCS_IN_16MS * line) / 262.0); + add_event_entry(dcycs, EV_VID_UPD + (line << 8)); +} + +double +remove_event_doc(int osc) +{ + return remove_event_entry(EV_DOC_INT + (osc << 8)); +} + +double +remove_event_scc(int type) +{ + return remove_event_entry(EV_SCC + (type << 8)); +} + +void +show_all_events() +{ + Event *ptr; + int count; + double dcycs; + + count = 0; + ptr = g_sim65816.g_event_start.next; + while(ptr != 0) { + dcycs = ptr->dcycs; + printf("Event: %02x: type: %05x, dcycs: %f (%f)\n", + count, ptr->type, dcycs, dcycs - g_sim65816.g_cur_dcycs); + ptr = ptr->next; + count++; + } + +} + +void +show_pmhz() +{ + printf("Pmhz: %f, c036:%02x, limit: %d\n", + g_sim65816.g_projected_pmhz, g_moremem.g_c036_val_speed, g_sim65816.get_limit_speed()); + +} + +void +setup_zip_speeds() +{ + double frecip; + double fmhz; + int mult; + + mult = 16 - ((g_moremem.g_zipgs_reg_c05a >> 4) & 0xf); + // 16 = full speed, 1 = 1/16th speed + fmhz = (8.0 * mult) / 16.0; +#if 0 + if(mult == 16) { + /* increase full speed by 19% to make zipgs freq measuring */ + /* programs work correctly */ + fmhz = fmhz * 1.19; + } +#endif + frecip = 1.0 / fmhz; + g_sim65816.g_zip_pmhz = fmhz; + g_sim65816.g_recip_projected_pmhz_zip.plus_1 = frecip; + g_sim65816.g_recip_projected_pmhz_zip.plus_2 = 2.0 * frecip; + g_sim65816.g_recip_projected_pmhz_zip.plus_3 = 3.0 * frecip; + if(frecip >= 0.5) { + g_sim65816.g_recip_projected_pmhz_zip.plus_x_minus_1 = 1.01; + } else { + g_sim65816.g_recip_projected_pmhz_zip.plus_x_minus_1 = 1.01 - frecip; + } +} + + +void +run_prog_init() +{ + + Fplus *fplus_ptr; + Event *this_event; + Event *db1; + double dcycs; + double now_dtime; + double prev_dtime; + double prerun_fcycles; + double fspeed_mult; + double fcycles_stop; + word32 ret; + word32 zip_speed_0tof, zip_speed_0tof_new; + int zip_en, zip_follow_cps; + int type; + int motor_on; + int iwm_1; + int iwm_25; + int limit_speed; + int apple35_sel; + int fast, zip_speed, faster_than_28, unl_speed; + int this_type; + + fflush(stdout); + + g_sim65816.g_cur_sim_dtime = 0.0; + + g_sim65816.g_recip_projected_pmhz_slow.plus_1 = 1.0; + g_sim65816.g_recip_projected_pmhz_slow.plus_2 = 2.0; + g_sim65816.g_recip_projected_pmhz_slow.plus_3 = 3.0; + g_sim65816.g_recip_projected_pmhz_slow.plus_x_minus_1 = 0.9; + + g_sim65816.g_recip_projected_pmhz_fast.plus_1 = (1.0 / DEFAULT_GS_SPEED); + g_sim65816.g_recip_projected_pmhz_fast.plus_2 = (2.0 / DEFAULT_GS_SPEED); + g_sim65816.g_recip_projected_pmhz_fast.plus_3 = (3.0 / DEFAULT_GS_SPEED); + g_sim65816.g_recip_projected_pmhz_fast.plus_x_minus_1 = (1.98 - (1.0/DEFAULT_GS_SPEED)); + + zip_speed_0tof = g_moremem.g_zipgs_reg_c05a & 0xf0; + setup_zip_speeds(); + + if(g_sim65816.engine.fplus_ptr == 0) { + g_sim65816.g_recip_projected_pmhz_unl = g_sim65816.g_recip_projected_pmhz_slow; + } + + +} + +int +run_prog_loop() +{ + + Fplus *fplus_ptr; + Event *this_event; + Event *db1; + double dcycs; + double now_dtime; + double prev_dtime; + double prerun_fcycles; + double fspeed_mult; + double fcycles_stop; + word32 ret; + word32 zip_speed_0tof, zip_speed_0tof_new; + int zip_en, zip_follow_cps; + int type; + int motor_on; + int iwm_1; + int iwm_25; + int limit_speed; + int apple35_sel; + int fast, zip_speed, faster_than_28, unl_speed; + int this_type; + + int isnextframe=0; + zip_speed_0tof = g_moremem.g_zipgs_reg_c05a & 0xf0; + + while(!r_sim65816.should_emulator_terminate()) + { + + fflush(stdout); + + r_sim65816.check_update_emulator_runtime_config(); + +// OG Disabling control panel +#ifndef ACTIVEGS + extern int g_config_control_panel; + if(g_config_control_panel) { + config_control_panel(); + } +#endif + if(g_moremem.g_irq_pending && !(g_sim65816.engine.psr & 0x4)) { + irq_printf("taking an irq!\n"); + take_irq(0); + /* Interrupt! */ + } + + motor_on = g_iwm.g_iwm_motor_on; + limit_speed = g_sim65816.get_limit_speed(); + apple35_sel = g_moremem.g_c031_disk35 & 0x40; + zip_en = ((g_moremem.g_zipgs_reg_c05b & 0x10) == 0); + zip_follow_cps = ((g_moremem.g_zipgs_reg_c059 & 0x8) != 0); + zip_speed_0tof_new = g_moremem.g_zipgs_reg_c05a & 0xf0; + fast = (g_moremem.g_c036_val_speed & 0x80) || (zip_en && !zip_follow_cps); + // OG Make fast parameter public + g_sim65816.g_speed_fast = fast; + if(zip_speed_0tof_new != zip_speed_0tof) { + zip_speed_0tof = zip_speed_0tof_new; + setup_zip_speeds(); + } + + iwm_1 = motor_on && !apple35_sel && + (g_moremem.g_c036_val_speed & 0x4) && + (g_iwm.g_slow_525_emul_wr || !g_iwm.g_fast_disk_emul); + iwm_25 = (motor_on && apple35_sel) && !g_iwm.g_fast_disk_emul; + faster_than_28 = fast && (!iwm_1 && !iwm_25) && zip_en && + ((limit_speed == 0) || (limit_speed == 3)); + zip_speed = faster_than_28 && + ((zip_speed_0tof != 0) || (limit_speed == 3) || + (g_moremem.g_zipgs_unlock >= 4) ); + + // OG unlimited speed should not be affected by zip. + // unl_speed = faster_than_28 && !zip_speed; + unl_speed = (limit_speed == 0) && faster_than_28; + + if(unl_speed) { + /* use unlimited speed */ + fspeed_mult = g_sim65816.g_projected_pmhz; + fplus_ptr = &g_sim65816.g_recip_projected_pmhz_unl; + } else if(zip_speed) { + fspeed_mult = g_sim65816.g_zip_pmhz; + fplus_ptr = &g_sim65816.g_recip_projected_pmhz_zip; + } else if(fast && !iwm_1 && !(limit_speed == 1)) { + fspeed_mult = DEFAULT_GS_SPEED; + fplus_ptr = &g_sim65816.g_recip_projected_pmhz_fast; + } else { + /* else run slow */ + fspeed_mult = 1.0; + fplus_ptr = &g_sim65816.g_recip_projected_pmhz_slow; + } + + g_sim65816.engine.fplus_ptr = fplus_ptr; + + this_type = g_sim65816.g_event_start.next->type; + + prerun_fcycles = g_sim65816.g_cur_dcycs - g_sim65816.g_last_vbl_dcycs; + g_sim65816.engine.fcycles = prerun_fcycles; + fcycles_stop = (g_sim65816.g_event_start.next->dcycs - g_sim65816.g_last_vbl_dcycs) + + 0.001; + if(g_stepping) { + fcycles_stop = prerun_fcycles; + } + g_sim65816.g_fcycles_stop = fcycles_stop; + +#if 0 + printf("Enter g_sim65816.engine, fcycs: %f, stop: %f\n", + prerun_fcycles, fcycles_stop); + printf("g_sim65816.g_cur_dcycs: %f, last_vbl_dcyc: %f\n", g_cur_dcycs, + g_sim65816.g_last_vbl_dcycs); +#endif + + g_sim65816.g_num_enter_engine++; + prev_dtime = get_dtime(); + + ret = enter_engine(&g_sim65816.engine); + + now_dtime = get_dtime(); + + g_sim65816.g_cur_sim_dtime += (now_dtime - prev_dtime); + + dcycs = g_sim65816.g_last_vbl_dcycs + (double)(g_sim65816.engine.fcycles); + + g_sim65816.g_dadjcycs += (g_sim65816.engine.fcycles - prerun_fcycles) * + fspeed_mult; + +#if 0 + printf("...back, g_sim65816.engine.fcycles: %f, dcycs: %f\n", + (double)g_sim65816.engine.fcycles, dcycs); +#endif + + g_sim65816.g_cur_dcycs = dcycs; + + if(ret != 0) { + g_sim65816.g_engine_action++; + handle_action(ret); + } + + if(g_sim65816.halt_sim == HALT_EVENT) { + g_sim65816.g_engine_halt_event++; + /* if we needed to stop to check for interrupts, */ + /* clear halt */ + g_sim65816.halt_sim = 0; + } + +#if 0 + if(!g_sim65816.g_testing && run_cycles < -2000000) { + halt_printf("run_cycles: %d, cycles: %d\n", run_cycles, + cycles); + printf("this_type: %05x\n", this_type); + printf("duff_cycles: %d\n", duff_cycles); + printf("start.next->rel_time: %d, type: %05x\n", + g_sim65816.g_event_start.next->rel_time, + g_sim65816.g_event_start.next->type); + } +#endif + + this_event = g_sim65816.g_event_start.next; + while(dcycs >= this_event->dcycs) { + /* Pop this guy off of the queue */ + g_sim65816.g_event_start.next = this_event->next; + + type = this_event->type; + this_event->next = g_sim65816.g_event_free.next; + g_sim65816.g_event_free.next = this_event; + switch(type & 0xff) { + case EV_60HZ: + update_60hz(dcycs, now_dtime); + isnextframe=1; + break; + case EV_STOP: + printf("type: EV_STOP\n"); + printf("next: %p, dcycs: %f\n", + g_sim65816.g_event_start.next, dcycs); + db1 = g_sim65816.g_event_start.next; + halt_printf("next.dcycs: %f\n", db1->dcycs); + break; + case EV_SCAN_INT: + g_sim65816.g_engine_scan_int++; + irq_printf("type: scan int\n"); + do_scan_int(dcycs, type >> 8); + break; + case EV_DOC_INT: + g_sim65816.g_engine_doc_int++; + doc_handle_event(type >> 8, dcycs); + break; + case EV_SCC_ENABLE: + { + extern void scc_delayed_enable(); + scc_delayed_enable(); + } + break; + case EV_VBL_INT: + do_vbl_int(); + break; + case EV_SCC: + do_scc_event(type >> 8, dcycs); + break; + case EV_VID_UPD: + { + /* + extern double last_vid_update_dcys; // OG + last_vid_update_dcys = this_event->dcycs; + */ + video_update_event_line(type >> 8); + } + break; + /* + // OG Added DelayWriteC023 Event + case EV_DELAY_WRITE_C023: + { + extern int g_c023_val; + printf("clearing c023 for line(%d)\n",type>>8); + g_moremem.g_c023_val = g_c023_val & 0xDF & 0x7F; + } + break; + */ + default: + printf("Unknown event: %d!\n", type); + x_exit(3); + break; + } + + this_event = g_sim65816.g_event_start.next; + + } + + if(g_sim65816.g_event_start.next == 0) { + halt_printf("ERROR...run_prog, event_start.n=0!\n"); + } + +#if 0 + if(!g_sim65816.g_testing && g_sim65816.g_event_start.next->rel_time > 2000000) { + printf("Z:start.next->rel_time: %d, duff_cycles: %d\n", + g_sim65816.g_event_start.next->rel_time, duff_cycles); + halt_printf("Zrun_cycles:%d, cycles:%d\n", run_cycles, + cycles); + + show_all_events(); + } +#endif + + if (isnextframe) + { + isnextframe=0; + if (g_driver.x_handle_state!=NULL) + g_driver.x_handle_state(); + else + g_savestate.handleState(); + + return 1; + } + + if(g_sim65816.halt_sim != 0 && g_sim65816.halt_sim != HALT_EVENT) + { + break; + } + if(g_stepping) + { + break; + } + + } + + return 0; // quit +} + + + + + +void +run_prog_shut() +{ + + + + if(!g_sim65816.g_testing) { + printf("leaving run_prog, g_sim65816.halt_sim:%d\n", g_sim65816.halt_sim); + } + + x_auto_repeat_on(0); +} + + +void run_prog() +{ + run_prog_init(); + while(1) + { + int ret = run_prog_loop(); + if (!ret) + break; + } + + run_prog_shut(); +} + + +void +add_irq(word32 irq_mask) +{ + if(g_moremem.g_irq_pending & irq_mask) { + /* Already requested, just get out */ + return; + } + g_moremem.g_irq_pending |= irq_mask; + set_halt(HALT_EVENT); +} + +void +remove_irq(word32 irq_mask) +{ + g_moremem.g_irq_pending = g_moremem.g_irq_pending & (~irq_mask); +} + +void +take_irq(int is_it_brk) +{ + word32 new_kpc; + word32 va; + + irq_printf("Taking irq, at: %02x/%04x, psw: %02x, dcycs: %f\n", + g_sim65816.engine.kpc>>16, g_sim65816.engine.kpc & 0xffff, g_sim65816.engine.psr, + g_sim65816.g_cur_dcycs); + + g_sim65816.g_num_irq++; + if(g_sim65816.g_wait_pending) { + /* step over WAI instruction */ + g_sim65816.engine.kpc++; + g_sim65816.g_wait_pending = 0; + } + + if(g_sim65816.engine.psr & 0x100) { + /* Emulation */ + set_memory_c(g_sim65816.engine.stack, (g_sim65816.engine.kpc >> 8) & 0xff, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xff) + 0x100; + + set_memory_c(g_sim65816.engine.stack, g_sim65816.engine.kpc & 0xff, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xff) + 0x100; + + set_memory_c(g_sim65816.engine.stack, + (g_sim65816.engine.psr & 0xef)|(is_it_brk<<4),0); + /* Clear B bit in psr on stack */ + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xff) + 0x100; + + va = 0xfffffe; + if(g_moremem.g_c035_shadow_reg & 0x40) { + /* I/O shadowing off...use ram locs */ + va = 0x00fffe; + } + + } else { + /* native */ + set_memory_c(g_sim65816.engine.stack, (g_sim65816.engine.kpc >> 16) & 0xff, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xffff); + + set_memory_c(g_sim65816.engine.stack, (g_sim65816.engine.kpc >> 8) & 0xff, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xffff); + + set_memory_c(g_sim65816.engine.stack, g_sim65816.engine.kpc & 0xff, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xffff); + + set_memory_c(g_sim65816.engine.stack, g_sim65816.engine.psr & 0xff, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack -1) & 0xffff); + + if(is_it_brk) { + /* break */ + va = 0xffffe6; + if(g_moremem.g_c035_shadow_reg & 0x40) { + va = 0xffe6; + } + } else { + /* irq */ + va = 0xffffee; + if(g_moremem.g_c035_shadow_reg & 0x40) { + va = 0xffee; + } + } + + } + + new_kpc = get_memory_c(va, 0); + new_kpc = new_kpc + (get_memory_c(va+1, 0) << 8); + + g_sim65816.engine.psr = ((g_sim65816.engine.psr & 0x1f3) | 0x4); + + g_sim65816.engine.kpc = new_kpc; + HALT_ON(HALT_ON_IRQ, "Halting on IRQ\n"); + +} + + + +void +show_dtime_array() +{ + double dfirst_time; + double first_total_cycs; + int i; + int pos; + + dfirst_time = 0.0; + first_total_cycs = 0.0; + + + for(i = 0; i < 60; i++) { + pos = (g_sim65816.g_vbl_index_count + i) % 60; + printf("%2d:%2d dt:%.5f adjc:%9.1f this_vbl:%.6f " + "exp:%.5f p:%2.2f ep:%2.2f\n", + i, pos, + g_sim65816.dtime_array[pos] - dfirst_time, + g_sim65816.g_dadjcycs_array[pos] - first_total_cycs, + g_sim65816.g_dtime_this_vbl_array[pos], + g_sim65816.g_dtime_exp_array[pos] - dfirst_time, + g_sim65816.g_dtime_pmhz_array[pos], + g_sim65816.g_dtime_eff_pmhz_array[pos]); + dfirst_time = g_sim65816.dtime_array[pos]; + first_total_cycs = g_sim65816.g_dadjcycs_array[pos]; + } +} + + + +void +update_60hz(double dcycs, double dtime_now) +{ + register word32 end_time; + char status_buf[1024]; + char sim_mhz_buf[128]; + char total_mhz_buf[128]; + const char *sim_mhz_ptr, *total_mhz_ptr; + const char *code_str1, *code_str2/*,*sp_str*/; + double eff_pmhz; + double planned_dcycs; + double predicted_pmhz; + double recip_predicted_pmhz; + double dtime_this_vbl_sim; + double dtime_diff_1sec; + double dratio; + double dtime_till_expected; + double dtime_diff; + double dtime_this_vbl; + double dadjcycs_this_vbl; + double dadj_cycles_1sec; + double dtmp1, dtmp2, dtmp3, dtmp4, dtmp5; + double dnatcycs_1sec; + int tmp; + int doit_3_persec; + int cur_vbl_index; + int prev_vbl_index; + + g_sim65816.g_vbl_count++; + + /* + if (g_driver.x_post_event) + g_driver.x_post_event("60hz"); +*/ + + /* NOTE: this event is defined to occur before line 0 */ + /* It's actually happening at the start of the border for line (-1) */ + /* All other timings should be adjusted for this */ + + irq_printf("vbl_60hz: vbl: %d, dcycs: %f, last_vbl_dcycs: %f\n", + g_sim65816.g_vbl_count, dcycs, g_sim65816.g_last_vbl_dcycs); + + planned_dcycs = DCYCS_IN_16MS; + + g_sim65816.g_last_vbl_dcycs = g_sim65816.g_last_vbl_dcycs + planned_dcycs; + + add_event_entry(g_sim65816.g_last_vbl_dcycs + planned_dcycs, EV_60HZ); + check_for_one_event_type(EV_60HZ); + + cur_vbl_index = g_sim65816.g_vbl_index_count; + + /* figure out dtime spent running SIM, not all the overhead */ + dtime_this_vbl_sim = g_sim65816.g_cur_sim_dtime; + g_sim65816.g_cur_sim_dtime = 0.0; + g_sim65816.g_sim_sum = g_sim65816.g_sim_sum - g_sim65816.sim_time[cur_vbl_index] + dtime_this_vbl_sim; + g_sim65816.sim_time[cur_vbl_index] = dtime_this_vbl_sim; + + dadj_cycles_1sec = g_sim65816.g_dadjcycs - g_sim65816.g_dadjcycs_array[cur_vbl_index]; + + /* dtime_diff_1sec is dtime total spent over the last 60 ticks */ + dtime_diff_1sec = dtime_now - g_sim65816.dtime_array[cur_vbl_index]; + + g_sim65816.dtime_array[cur_vbl_index] = dtime_now; + g_sim65816.g_dadjcycs_array[cur_vbl_index] = g_sim65816.g_dadjcycs; + + prev_vbl_index = cur_vbl_index; + cur_vbl_index = prev_vbl_index + 1; + if(cur_vbl_index >= 60) { + cur_vbl_index = 0; + } + g_sim65816.g_vbl_index_count = cur_vbl_index; + + GET_ITIMER(end_time); + g_sim65816.g_dnatcycs_1sec += (double)(end_time - g_sim65816.g_natcycs_lastvbl); + g_sim65816.g_natcycs_lastvbl = end_time; + + if(prev_vbl_index == 0) { + if(g_sim65816.g_sim_sum < (1.0/250.0)) { + sim_mhz_ptr = "???"; + g_sim65816.g_sim_mhz = 250.0; + } else { + g_sim65816.g_sim_mhz = (dadj_cycles_1sec / g_sim65816.g_sim_sum) / + (1000.0*1000.0); + sprintf(sim_mhz_buf, "%6.2f", g_sim65816.g_sim_mhz); + sim_mhz_ptr = sim_mhz_buf; + } + if(dtime_diff_1sec < (1.0/250.0)) { + total_mhz_ptr = "???"; + } else { + sprintf(total_mhz_buf, "%6.2f", + (dadj_cycles_1sec / dtime_diff_1sec) / + (1000000.0)); + total_mhz_ptr = total_mhz_buf; + } + + x_update_info(total_mhz_ptr); + + if(g_sim65816.g_video_line_update_interval == 0) { + if(g_sim65816.g_sim_mhz > 12.0) { + /* just set video line_ref_amt to 1 */ + g_sim65816.g_line_ref_amt = 1; + } else if(g_sim65816.g_line_ref_amt == 1 && g_sim65816.g_sim_mhz < 4.0) { + g_sim65816.g_line_ref_amt = 8; + } + } else { + g_sim65816.g_line_ref_amt = g_sim65816.g_video_line_update_interval; + } + + if(g_sim65816.g_dnatcycs_1sec < (1000.0*1000.0)) { + /* make it so large that all %'s become 0 */ + g_sim65816.g_dnatcycs_1sec = 800.0*1000.0*1000.0*1000.0; + } + dnatcycs_1sec = g_sim65816.g_dnatcycs_1sec / 100.0; /* eff mult by 100 */ + + dtmp2 = (double)(g_video.g_cycs_in_check_input) / dnatcycs_1sec; + dtmp3 = (double)(g_video.g_cycs_in_refresh_line) / dnatcycs_1sec; + dtmp4 = (double)(g_video.g_cycs_in_refresh_ximage) / dnatcycs_1sec; + sprintf(status_buf, "xfer:%08x, %5.1f ref_amt:%d " + "ch_in:%4.1f%% ref_l:%4.1f%% ref_x:%4.1f%%", + g_refresh_bytes_xfer, g_sim65816.g_dnatcycs_1sec/(1000.0*1000.0), + g_sim65816.g_line_ref_amt, dtmp2, dtmp3, dtmp4); + video_update_status_line(1, status_buf); + + sprintf(status_buf, "Ints:%3d I/O:%4dK BRK:%3d COP:%2d " + "Eng:%3d act:%3d hev:%3d esi:%3d edi:%3d", + g_sim65816.g_num_irq, g_sim65816.g_io_amt>>10, g_sim65816.g_num_brk, g_sim65816.g_num_cop, + g_sim65816.g_num_enter_engine, g_sim65816.g_engine_action, + g_sim65816.g_engine_halt_event, g_sim65816.g_engine_scan_int, + g_sim65816.g_engine_doc_int); + video_update_status_line(2, status_buf); + + dtmp1 = (double)(g_cycs_in_sound1) / dnatcycs_1sec; + dtmp2 = (double)(g_cycs_in_sound2) / dnatcycs_1sec; + dtmp3 = (double)(g_cycs_in_sound3) / dnatcycs_1sec; + dtmp4 = (double)(g_cycs_in_start_sound) / dnatcycs_1sec; + dtmp5 = (double)(g_cycs_in_est_sound) / dnatcycs_1sec; + sprintf(status_buf, "snd1:%4.1f%%, 2:%4.1f%%, " + "3:%4.1f%%, st:%4.1f%% est:%4.1f%% %4.2f", + dtmp1, dtmp2, dtmp3, dtmp4, dtmp5, g_fvoices); + video_update_status_line(3, status_buf); + + code_str1 = ""; + code_str2 = ""; + if(g_sim65816.g_code_yellow) { + code_str1 = "Code: Yellow"; + code_str2 = "Emulated system state suspect, save work"; + } + if(g_sim65816.g_code_red) { + code_str1 = "Code: RED"; + code_str2 = "Emulated system state probably corrupt"; + } + sprintf(status_buf, "snd_plays:%4d, doc_ev:%4d, st_snd:%4d " + "snd_parms: %4d %s", + g_num_snd_plays, g_num_doc_events, g_num_start_sounds, + g_num_recalc_snd_parms, code_str1); + video_update_status_line(4, status_buf); + + draw_iwm_status(5, status_buf); + + sprintf(status_buf, "KEGS v%-6s BUILD v%s " + "Press F4 for Config Menu %s", + g_kegs_version_str, g_kegs_version_build,code_str2); + video_update_status_line(6, status_buf); + + g_video.g_status_refresh_needed = 1; + + g_sim65816.g_num_irq = 0; + g_sim65816.g_num_brk = 0; + g_sim65816.g_num_cop = 0; + g_sim65816.g_num_enter_engine = 0; + g_sim65816.g_io_amt = 0; + g_sim65816.g_engine_action = 0; + g_sim65816.g_engine_halt_event = 0; + g_sim65816.g_engine_scan_int = 0; + g_sim65816.g_engine_doc_int = 0; + + g_video.g_cycs_in_40col = 0; + g_video.g_cycs_in_xredraw = 0; + g_video.g_cycs_in_check_input = 0; + g_video.g_cycs_in_refresh_line = 0; + g_video.g_cycs_in_refresh_ximage = 0; + g_iwm.g_cycs_in_io_read = 0; + g_cycs_in_sound1 = 0; + g_cycs_in_sound2 = 0; + g_cycs_in_sound3 = 0; + g_cycs_in_sound4 = 0; + g_cycs_in_start_sound = 0; + g_cycs_in_est_sound = 0; + g_sim65816.g_dnatcycs_1sec = 0.0; + g_refresh_bytes_xfer = 0; + + g_num_snd_plays = 0; + g_num_doc_events = 0; + g_num_start_sounds = 0; + g_num_scan_osc = 0; + g_num_recalc_snd_parms = 0; + + g_fvoices = (float)0.0; + } + + dtime_this_vbl = dtime_now - g_sim65816.g_dtime_last_vbl; + if(dtime_this_vbl < 0.001) { + dtime_this_vbl = 0.001; + } + + g_sim65816.g_dtime_last_vbl = dtime_now; + + dadjcycs_this_vbl = g_sim65816.g_dadjcycs - g_sim65816.g_last_vbl_dadjcycs; + g_sim65816.g_last_vbl_dadjcycs = g_sim65816.g_dadjcycs; + + g_sim65816.g_dtime_expected += (1.0/60.0); + + eff_pmhz = ((dadjcycs_this_vbl) / (dtime_this_vbl)) / + DCYCS_1_MHZ; + + /* using eff_pmhz, predict how many cycles can be run by */ + /* g_sim65816.g_dtime_expected */ + + dtime_till_expected = g_sim65816.g_dtime_expected - dtime_now; + + dratio = 60.0 * dtime_till_expected; + + predicted_pmhz = eff_pmhz * dratio; + + if(! (predicted_pmhz < (1.4 * g_sim65816.g_projected_pmhz))) { + predicted_pmhz = 1.4 * g_sim65816.g_projected_pmhz; + } + + if(! (predicted_pmhz > (0.7 * g_sim65816.g_projected_pmhz))) { + predicted_pmhz = 0.7 * g_sim65816.g_projected_pmhz; + } + + if(!(predicted_pmhz >= 1.0)) { + irq_printf("predicted: %f, setting to 1.0\n", predicted_pmhz); + predicted_pmhz = 1.0; + } + + if(!(predicted_pmhz < 250.0)) { + irq_printf("predicted: %f, setting to 250.0\n", predicted_pmhz); + predicted_pmhz = 250.0; + } + + recip_predicted_pmhz = 1.0/predicted_pmhz; + g_sim65816.g_projected_pmhz = predicted_pmhz; + + g_sim65816.g_recip_projected_pmhz_unl.plus_1 = 1.0*recip_predicted_pmhz; + g_sim65816.g_recip_projected_pmhz_unl.plus_2 = 2.0*recip_predicted_pmhz; + g_sim65816.g_recip_projected_pmhz_unl.plus_3 = 3.0*recip_predicted_pmhz; + g_sim65816.g_recip_projected_pmhz_unl.plus_x_minus_1 = 1.01 - recip_predicted_pmhz; + + + if(dtime_till_expected < -0.125) { + /* If we were way off, get back on track */ + /* this happens because our sim took much longer than */ + /* expected, so we're going to skip some VBL */ + irq_printf("adj1: dtexp:%f, dt_new:%f\n", + g_sim65816.g_dtime_expected, dtime_now); + + dtime_diff = -dtime_till_expected; + + irq_printf("dtime_till_exp: %f, dtime_diff: %f, dcycs: %f\n", + dtime_till_expected, dtime_diff, dcycs); + + g_sim65816.g_dtime_expected += dtime_diff; + } + + double w = dtime_till_expected - (1.0/60.0); // OG was 3/60 !!! + +#ifdef USE_RASTER + x_wait_for_last_refresh(w); +#else + + + if(w>0.0) + { + /* we're running fast, usleep */ + double s = get_dtime(); + if (w>0.01) + micro_sleep(w); + // sur windows le micro_sleep est lgrement en retard! + while( get_dtime() < s+w); +#ifdef ENABLE_GRAPH + /* + double d = get_dtime() - s; + double d2 = d - w; + g_graph.add_graph(3,(float)d,g_sim65816.g_vbl_count); + g_graph.add_graph(2,(float)w,g_sim65816.g_vbl_count); + */ +#endif + } + +#endif + + CHANGE_BORDER(0,0xFF0000); + CHANGE_BORDER(2,0xFF0000); + + g_sim65816.g_dtime_this_vbl_array[prev_vbl_index] = dtime_this_vbl; + g_sim65816.g_dtime_exp_array[prev_vbl_index] = g_sim65816.g_dtime_expected; + g_sim65816.g_dtime_pmhz_array[prev_vbl_index] = predicted_pmhz; + g_sim65816.g_dtime_eff_pmhz_array[prev_vbl_index] = eff_pmhz; + + + if(g_moremem.g_c041_val & C041_EN_VBL_INTS) { + add_event_vbl(); + } + + g_sim65816.g_25sec_cntr++; + if(g_sim65816.g_25sec_cntr >= 16) { + g_sim65816.g_25sec_cntr = 0; + if(g_moremem.g_c041_val & C041_EN_25SEC_INTS) { + add_irq(IRQ_PENDING_C046_25SEC); + g_moremem.g_c046_val |= 0x10; + irq_printf("Setting c046 .25 sec int, g_irq_pend:%d\n", + g_moremem.g_irq_pending); + } + } + + g_sim65816.g_1sec_cntr++; + if(g_sim65816.g_1sec_cntr >= 60) { + g_sim65816.g_1sec_cntr = 0; + tmp = g_moremem.g_c023_val; + tmp |= 0x40; /* set 1sec int */ + if(tmp & 0x04) { + tmp |= 0x80; + add_irq(IRQ_PENDING_C023_1SEC); + irq_printf("Setting c023 to %02x irq_pend: %d\n", + tmp, g_moremem.g_irq_pending); + } + irq_printf("1s irq: %X new: %X\n",g_moremem.g_c023_val,tmp); + g_moremem.g_c023_val = tmp; + } + + /* + { + extern int g_delayed_c023_val; + if (g_delayed_c023_val) + { + g_moremem.g_c023_val = g_c023_val & 0xDF; + g_delayed_c023_val = 0; + printf("clearing c023 val\n"); + } + } + */ + + if(!g_sim65816.g_scan_int_events) { + check_scan_line_int(dcycs, 0); + } + + doit_3_persec = 0; + if(g_sim65816.g_config_iwm_vbl_count > 0) { + g_sim65816.g_config_iwm_vbl_count--; + } else { + g_sim65816.g_config_iwm_vbl_count = 20; + doit_3_persec = 1; + } + + iwm_vbl_update(doit_3_persec); + +// OG Disabling config update +#ifndef ACTIVEGS + config_vbl_update(doit_3_persec); +#else +// OG Added disk update + { + extern void checkImages(); + checkImages(); + } +#endif + +/* + +#if 0 //def USE_RASTER + + static double lastraster = 0; + double curraster = get_dtime(); + double target = lastraster+1/60.0; + double wait = target - curraster; + + // attend le rendu de la frame prcdente (ou la synchro) + + x_wait_for_vbl(); + + curraster = get_dtime(); + + double delay = curraster - lastraster; + double frame = 1/delay; + +#ifdef ENABLE_GRAPH +// g_graph.add_graph(2,frame,g_sim65816.g_vbl_count); +#endif + lastraster = curraster; +#endif + */ + g_video_offscreen_has_been_modified = 0; + + + CHANGE_BORDER(0,0xFF00FF); + CHANGE_BORDER(2,0xFF00FF); + + video_update(); + + DRAW_BORDER(); + + CHANGE_BORDER(0,0); + CHANGE_BORDER(2,0); + +#ifdef USE_RASTER + x_wait_for_vbl(); +#endif + refresh_video(0); + + CHANGE_BORDER(0,0x888888); + CHANGE_BORDER(2,0x888888); + sound_update(dcycs); + clock_update(); + scc_update(dcycs); + paddle_update_buttons(); + + CHANGE_BORDER(0,0); + CHANGE_BORDER(2,0xFF0000); + +} + +void +do_vbl_int() +{ + if(g_moremem.g_c041_val & C041_EN_VBL_INTS) { + g_moremem.g_c046_val |= 0x08; + add_irq(IRQ_PENDING_C046_VBL); + irq_printf("Setting c046 vbl_int_status to 1, irq_pend: %d\n", + g_moremem.g_irq_pending); + } +} + + +void +do_scan_int(double dcycs, int line) +{ + int c023_val; + g_sim65816.g_scan_int_events = 0; + + c023_val = g_moremem.g_c023_val; + if(c023_val & 0x20) { + halt_printf("c023 scan_int and another on line %03x\n", line); + } + + /* make sure scan int is still enabled for this line */ + if((g_slow_memory_ptr[0x19d00 + line] & 0x40) && + (g_video.g_cur_a2_stat & ALL_STAT_SUPER_HIRES)) { + /* valid interrupt, do it */ + c023_val |= 0xa0; /* vgc_int and scan_int */ + if(c023_val & 0x02) { + add_irq(IRQ_PENDING_C023_SCAN); + irq_printf("Setting c023 to %02x, irq_pend: %d\n", c023_val, g_moremem.g_irq_pending); + } + + g_moremem.g_c023_val = c023_val; + HALT_ON(HALT_ON_SCAN_INT, "In do_scan_int\n"); + } else { + /* scan int bit cleared on scan line control byte */ + /* look for next line, if any */ + check_scan_line_int(dcycs, line+1); + } +} + +void +check_scan_line_int(double dcycs, int cur_video_line) +{ + int delay; + int start; + int line; + int i; + /* Called during VBL interrupt phase */ + + if(!(g_video.g_cur_a2_stat & ALL_STAT_SUPER_HIRES)) { + return; + } + + if(g_moremem.g_c023_val & 0x20) { + /* don't check for any more */ + return; + } + + start = cur_video_line; + if(start < 0) { + halt_printf("check_scan_line_int: cur_video_line: %d\n", + cur_video_line); + start = 0; + } + + for(line = start; line < 200; line++) { + i = line; + + if(i < 0 || i >= 200) { + halt_printf("check_new_scan_int:i:%d, line:%d, st:%d\n", + i, line, start); + i = 0; + } + if(g_slow_memory_ptr[0x19d00+i] & 0x40) { + //printf("Adding scan_int for line %d\n", i); + delay = (int)( (DCYCS_IN_16MS/262.0) * ((double)line) ); + add_event_entry(g_sim65816.g_last_vbl_dcycs + delay, EV_SCAN_INT + + (line << 8)); + //add_event_entry(g_sim65816.g_last_vbl_dcycs + delay + (DCYCS_IN_16MS/262.0)*4/5 , EV_DELAY_WRITE_C023+ (line << 8)); + g_sim65816.g_scan_int_events = 1; + check_for_one_event_type(EV_SCAN_INT); + break; + } + } +} + +void +check_for_new_scan_int(double dcycs) +{ + int cur_video_line; + + cur_video_line = get_lines_since_vbl(dcycs) >> 8; + + check_scan_line_int(dcycs, cur_video_line); +} + +void +init_reg() +{ + g_sim65816.engine.acc = 0; + g_sim65816.engine.xreg = 0; + g_sim65816.engine.yreg = 0; + g_sim65816.engine.stack = 0x1ff; + g_sim65816.engine.direct = 0; + g_sim65816.engine.psr = 0x134; + g_sim65816.engine.fplus_ptr = 0; + +} + + +void +handle_action(word32 ret) +{ + int type; + + type = EXTRU(ret,3,4); + switch(type) { + case RET_BREAK: + do_break(ret & 0xff); + break; + case RET_COP: + do_cop(ret & 0xff); + break; +#if 0 + case RET_MVN: + do_mvn(ret & 0xffff); + break; +#endif + case RET_C700: + do_c700(ret); + break; + case RET_C70A: + do_c70a(ret); + break; + case RET_C70D: + do_c70d(ret); + break; +#if 0 + case RET_ADD_DEC_8: + do_add_dec_8(ret); + break; + case RET_ADD_DEC_16: + do_add_dec_16(ret); + break; +#endif + case RET_IRQ: + irq_printf("Special fast IRQ response. irq_pending: %x\n", + g_moremem.g_irq_pending); + break; + case RET_WDM: + do_wdm(ret & 0xff); + break; + case RET_STP: + do_stp(); + break; + default: + halt_printf("Unknown special action: %08x!\n", ret); + break; + } + +} + +#if 0 +void +do_add_dec_8(word32 ret) +{ + halt_printf("do_add_dec_8 called, ret: %08x\n", ret); +} + +void +do_add_dec_16(word32 ret) +{ + halt_printf("do_add_dec_16 called, ret: %08x\n", ret); +} +#endif + +void +do_break(word32 ret) +{ + if(!g_sim65816.g_testing) { + printf("I think I got a break, second byte: %02x!\n", ret); + printf("kpc: %06x\n", g_sim65816.engine.kpc); + } + + halt_printf("do_break, kpc: %06x\n", g_sim65816.engine.kpc); + g_sim65816.enter_debug = 1; +} + +void +do_cop(word32 ret) +{ + halt_printf("COP instr %02x!\n", ret); + fflush(stdout); +} + +#if 0 +void +do_mvn(word32 banks) +{ + int src_bank, dest_bank; + int dest, src; + int num; + int i; + int val; + + halt_printf("In MVN...just quitting\n"); + return; + printf("MVN instr with %04x, cycles: %08x\n", banks, g_sim65816.engine.cycles); + src_bank = banks >> 8; + dest_bank = banks & 0xff; + printf("psr: %03x\n", g_sim65816.engine.psr); + if((g_sim65816.engine.psr & 0x30) != 0) { + halt_printf("MVN in non-native mode unimplemented!\n"); + } + + dest = dest_bank << 16 | g_sim65816.engine.yreg; + src = src_bank << 16 | g_sim65816.engine.xreg; + num = g_sim65816.engine.acc; + printf("Moving %08x+1 bytes from %08x to %08x\n", num, src, dest); + + for(i = 0; i <= num; i++) { + val = get_memory_c(src, 0); + set_memory_c(dest, val, 0); + src = (src_bank << 16) | ((src + 1) & 0xffff); + dest = (dest_bank << 16) | ((dest + 1) & 0xffff); + } + g_sim65816.engine.dbank = dest_bank; + g_sim65816.engine.acc = 0xffff; + g_sim65816.engine.yreg = dest & 0xffff; + g_sim65816.engine.xreg = src & 0xffff; + g_sim65816.engine.kpc = (engine.kpc + 3); + printf("move done. db: %02x, acc: %04x, y: %04x, x: %04x, num: %08x\n", + g_sim65816.engine.dbank, engine.acc, engine.yreg, engine.xreg, num); +} +#endif + +void +do_wdm(word32 arg) +{ + switch(arg) { + case 0x8d: /* Bouncin Ferno does WDM 8d */ + break; + default: + halt_printf("do_wdm: %02x!\n", arg); + break; + } +} + +void +do_wai() +{ + halt_printf("do_wai!\n"); +} + +void +do_stp() +{ + if(!g_sim65816.g_stp_pending) { + g_sim65816.g_stp_pending = 1; + halt_printf("Hit STP instruction at: %06x, press RESET to " + "continue\n", g_sim65816.engine.kpc); + } +} + +void +size_fail(int val, word32 v1, word32 v2) +{ + halt_printf("Size failure, val: %08x, %08x %08x\n", val, v1, v2); +} + +int +fatal_printf(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + + if(g_fatal_log < 0) { + g_fatal_log = 0; + } + ret = kegs_vprintf(fmt, ap); + va_end(ap); + + return ret; +} + +int +kegs_vprintf(const char *fmt, va_list ap) +{ + char *bufptr, *buf2ptr; + int len; + int ret; + + bufptr = (char*)malloc(4096); // OG Added Cast + ret = vsnprintf(bufptr, 4090, fmt, ap); + + // OG Display warning + printf("Warning:%s",bufptr); + + len = strlen(bufptr); + if(g_fatal_log >= 0 && g_fatal_log < MAX_FATAL_LOGS) { + buf2ptr = (char*)malloc(len+1); // OG Added Cast + memcpy(buf2ptr, bufptr, len+1); + g_fatal_log_strs[g_fatal_log++] = buf2ptr; + } + must_write(1, bufptr, len); + if(g_debug_file_fd >= 0) { + must_write(g_debug_file_fd, bufptr, len); + } + free(bufptr); + + return ret; +} + +void +must_write(int fd, char *bufptr, int len) +{ + int ret; + + while(len > 0) { + ret = write(fd, bufptr, len); + if(ret >= 0) { + len -= ret; + bufptr += ret; + } else if(errno != EAGAIN && errno != EINTR) { + return; // just get out + } + } +} + +void +clear_fatal_logs() +{ + int i; + + for(i = 0; i < g_fatal_log; i++) { + free(g_fatal_log_strs[i]); + g_fatal_log_strs[i] = 0; + } + g_fatal_log = -1; +} + + char * +kegs_malloc_str(const char *in_str) +{ + char *str; + size_t len = strlen(in_str) + 1; + str = (char*)malloc(len); // OG Added cast + memcpy(str, in_str, len); + + return str; +} + +enum speedenum s_sim65816:: set_limit_speed(enum speedenum _speed) +{ + extern unsigned char transwarpcode[][32]; + + if ( (_speed<0) || (_speed>=SPEED_ENUMSIZE) ) + _speed = SPEED_GS; + + if (_speed == SPEED_ZIP || _speed ==SPEED_UNLIMITED) + { + // enable transwarp hardware + transwarpcode[0][0]='T'; + } + else + { + // disable transwarp hardware + transwarpcode[0][0]=0; + } + + x_refresh_panel(PANEL_SPEED|PANEL_RUNTIME); + printf("speed:%d\n",_speed); + g_limit_speed = _speed; + return _speed; +} + +void serialize_engine(Engine_reg& engine) +{ + int fpp = -1; + if (engine.fplus_ptr == &g_sim65816.g_recip_projected_pmhz_unl) + fpp = 0; + else + if (engine.fplus_ptr == &g_sim65816.g_recip_projected_pmhz_zip) + fpp = 1; + else + if (engine.fplus_ptr == &g_sim65816.g_recip_projected_pmhz_fast) + fpp = 2; + else +// if (engine.fplus_ptr == &g_sim65816.g_recip_projected_pmhz_slow) + fpp = 3; + engine.fplus_ptr = (Fplus*)fpp; +} + +void unserialize_engine(Engine_reg& engine) +{ + intptr_t fpp = (intptr_t)engine.fplus_ptr; + if (fpp==0) + engine.fplus_ptr = &g_sim65816.g_recip_projected_pmhz_unl; + else + if (fpp==1) + engine.fplus_ptr = &g_sim65816.g_recip_projected_pmhz_zip; + else + if (fpp==2) + engine.fplus_ptr =&g_sim65816.g_recip_projected_pmhz_fast; + else +// if (fpp ==3) + engine.fplus_ptr = &g_sim65816.g_recip_projected_pmhz_slow; +} + diff --git a/kegs/Src/sim65816.h b/kegs/Src/sim65816.h new file mode 100644 index 0000000..46dc32d --- /dev/null +++ b/kegs/Src/sim65816.h @@ -0,0 +1,392 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#define START_DCYCS (0.0) +#define MAX_EVENTS 64 + +extern byte *g_memory_ptr; +extern byte *g_slow_memory_ptr; + + +enum { + OFFSCREEN_AVAILABLE=256, + NO_INITIALIZED = 0, + INITIALIZING = 1, + RUNNING = 2 + OFFSCREEN_AVAILABLE, +// IN_REWIND = 3 + OFFSCREEN_AVAILABLE, + IN_PAUSE = 4 + OFFSCREEN_AVAILABLE, + PAUSE_REQUESTED = 5 + OFFSCREEN_AVAILABLE, + SHUTTING_DOWN = 5 +}; + +typedef enum _colormode +{ + COLORMODE_AUTO = 100, + COLORMODE_BW, + COLORMODE_AMBER, + COLORMODE_GREEN, + COLORMODE_MONO +} colormodeenum; + +typedef enum _videofx +{ + VIDEOFX_LCD = 200, + VIDEOFX_CRT +} videofxenum; + + +enum speedenum +{ + SPEED_UNLIMITED = 0, + SPEED_1MHZ = 1, + SPEED_GS = 2, // 2.8 Mhz + SPEED_ZIP = 3, // 8 Mhz Zip speed + SPEED_ENUMSIZE=4, + SPEED_AUTO = 4, +}; + +class run_sim65816 +{ + int g_savestate_enable; + +public: + int emulator_state; + int quit_requested; + int restart_requested; + colormodeenum color_mode; + videofxenum video_fx; + + int g_user_halt_bad ; + int g_halt_on_bad_read ; + int g_ignore_bad_acc; + int g_ignore_halts ; + + Page_info page_info_rd_wr[2*65536 + PAGE_INFO_PAD_SIZE]; + + run_sim65816() + { + memset(this,0,sizeof(*this)); + emulator_state = NO_INITIALIZED; + color_mode = COLORMODE_AUTO; + video_fx = VIDEOFX_LCD; + g_ignore_bad_acc = 1; + g_ignore_halts = 1; + + } + + // Emulator COnfig + + + videofxenum get_video_fx() { return video_fx; } + void set_video_fx(videofxenum _vfx); + colormodeenum get_color_mode() { return color_mode; } + void set_color_mode(colormodeenum _cm); + int is_emulator_initialized(); + int emulator_config_requested; + void request_update_emulator_runtime_config(); + void check_update_emulator_runtime_config(); + + // Emulator State + + void set_rewind_enable(int _onoff); + int get_rewind_enable() { return g_savestate_enable; }; + + void set_state(int _newstate); + int get_state(); + void quit_emulator() ; + void restart_emulator(); + void reset_quit(); + void reset_restart(); + + int pause(); + int resume(); + + // Emulator Info + + int is_emulator_in_640mode(); + int is_emulator_offscreen_available(); + int should_emulator_terminate(); + +}; + +extern run_sim65816 r_sim65816; +extern void unserialize_engine(Engine_reg& engine); +extern void serialize_engine(Engine_reg& engine); + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif +class s_sim65816 : public serialized +{ + +public: + enum speedenum g_limit_speed ; + + int get_limit_speed() { return (int)g_limit_speed; } + enum speedenum set_limit_speed(enum speedenum _speed); + + int g_speed_fast ; // OG Expose fast parameter + Engine_reg engine; + _ALIGNED(8) double g_fcycles_stop; + volatile int halt_sim ; + int enter_debug; + int g_rom_version ; + int g_code_red ; + int g_code_yellow ; + int g_use_alib ; + int g_raw_serial ; + int g_iw2_emul ; + int g_serial_out_masking ; + int g_serial_modem[2]; + + int g_config_iwm_vbl_count; + + _ALIGNED(8) double g_last_vbl_dcycs ; + _ALIGNED(8) double g_cur_dcycs ; + + _ALIGNED(8) double g_last_vbl_dadjcycs ; + _ALIGNED(8) double g_dadjcycs; + + int g_wait_pending ; + int g_stp_pending ; + + int g_num_irq ; + int g_num_brk ; + int g_num_cop ; + int g_num_enter_engine ; + int g_io_amt ; + int g_engine_action ; + int g_engine_halt_event; + int g_engine_scan_int ; + int g_engine_doc_int ; + + int g_testing ; + int g_testing_enabled ; + + word32 stop_run_at; + + int g_25sec_cntr ; + int g_1sec_cntr ; + + _ALIGNED(8) double g_dnatcycs_1sec ; + word32 g_natcycs_lastvbl ; + +// int Verbose ; + int Halt_on ; + + word32 g_mem_size_base ; + word32 g_mem_size_exp ; + word32 g_mem_size_total ; + + + word32 g_vbl_count; + word32 g_vbl_count_since_lastvblank; + int g_fixed_vblank; + + void set_fixed_vblank(int _nbframe,speedenum _defaultspeed); + + int g_vbl_index_count; + _ALIGNED(8) double dtime_array[60]; + _ALIGNED(8) double g_dadjcycs_array[60]; + _ALIGNED(8) double g_dtime_diff3_array[60]; + _ALIGNED(8) double g_dtime_this_vbl_array[60]; + _ALIGNED(8) double g_dtime_exp_array[60]; + _ALIGNED(8) double g_dtime_pmhz_array[60]; + _ALIGNED(8) double g_dtime_eff_pmhz_array[60]; + _ALIGNED(8) double sim_time[60]; + _ALIGNED(8) double g_sim_sum ; + + _ALIGNED(8) double g_cur_sim_dtime ; + _ALIGNED(8) double g_projected_pmhz; + _ALIGNED(8) double g_zip_pmhz ; + _ALIGNED(8) double g_sim_mhz ; + int g_line_ref_amt ; + int g_video_line_update_interval ; + + Fplus g_recip_projected_pmhz_slow; + Fplus g_recip_projected_pmhz_fast; + Fplus g_recip_projected_pmhz_zip; + Fplus g_recip_projected_pmhz_unl; + + _ALIGNED(8) double g_dtime_last_vbl ; + _ALIGNED(8) double g_dtime_expected ; + + int g_scan_int_events ; + + char g_display_env[512]; + int g_force_depth; + + Event g_event_list[MAX_EVENTS]; + Event g_event_free; + Event g_event_start; + +// Page_info page_info_rd_wr[2*65536 + PAGE_INFO_PAD_SIZE]; + + // OG unsupported 6502 opcodes are turned into NOP + int g_6502_emulation ; + int g_use_apple2e_rom ; + int g_enable_disk_sound; + + + s_sim65816() + { + INIT_SERIALIZED(); + + g_rom_version = -1; + // g_ignore_bad_acc = 1; + // g_ignore_halts = 1; + g_raw_serial = 1; + g_serial_modem[1] = 1; + + g_last_vbl_dcycs = START_DCYCS; + g_cur_dcycs = START_DCYCS; + + g_mem_size_base = 256*1024; /* size of motherboard memory */ + g_mem_size_exp = 2*1024*1024; /* size of expansion RAM card */ + g_mem_size_total = 256*1024; /* Total contiguous RAM from 0 */ + + g_projected_pmhz = 1.0; + g_zip_pmhz = 8.0; + g_sim_mhz = 100.0; + g_line_ref_amt = 1; + + g_dtime_expected = (1.0/60.0); + + g_force_depth = -1; + g_limit_speed = SPEED_GS; + + + } + #define RECALC_BASE_EVENT_PTR(X,BASE) \ + if (X) \ + { \ + X = (Event*)( (intptr_t)X + (intptr_t)BASE ) ; \ + } + + void in(serialize* _s) + { + extern byte* g_dummy_memory1_ptr; + + byte* ptr = (byte*)_s->data; + int ssize = *(int*)ptr; + if (ssize!=sizeof(*this)) + ALIGNMENT_ERROR("sim65816",ssize,sizeof(*this)); + ptr+=4; + memcpy(this,_s->data,sizeof(*this)); + + unserialize_engine(engine); + ptr += sizeof(*this); + + + memcpy(g_slow_memory_ptr,ptr,128*1024); + ptr+=128*1024; + memcpy(g_dummy_memory1_ptr,ptr,256); + ptr+=256; + memcpy(g_memory_ptr,ptr,g_mem_size_total); + + + intptr_t base = (intptr_t)g_event_list +1; // pour ne pas commencer zero! + for(int i = 1; i < MAX_EVENTS; i++) + { + RECALC_BASE_EVENT_PTR(g_event_list[i-1].next,+base); + } + RECALC_BASE_EVENT_PTR(g_event_free.next,+base); + RECALC_BASE_EVENT_PTR(g_event_start.next,+base); + + g_dtime_last_vbl += get_dtime(); + g_dtime_expected += get_dtime(); + + + } + + + int out(serialize* _s,int _fastalloc) + { +extern byte* g_dummy_memory1_ptr; + + int ssize = sizeof(*this); + int size = sizeof(ssize); + size += ssize; + size += 128*1024; // slow memory + size += 256; // dummy + size += g_mem_size_total; + + + _s->size = size; + _s->fastalloc = _fastalloc; + _s->data = (void*)x_malloc(size,_fastalloc); + + intptr_t base = (intptr_t)g_event_list +1; // pour ne pas commencer zero! + + // reinitialize les event avant de les copier + for(int i = 1; i < MAX_EVENTS; i++) + { + RECALC_BASE_EVENT_PTR(g_event_list[i-1].next,-base); + } + RECALC_BASE_EVENT_PTR(g_event_free.next,-base); + RECALC_BASE_EVENT_PTR(g_event_start.next,-base); + + serialize_engine(engine); + double old_g_dtime_last_vbl = g_dtime_last_vbl; + g_dtime_last_vbl -= get_dtime(); + double old_g_dtime_expected = g_dtime_expected; + g_dtime_expected -= get_dtime(); + + byte* ptr = (byte*)_s->data; + memcpy(ptr,&ssize,sizeof(ssize)); + ptr+=sizeof(ssize); + memcpy(_s->data,this,sizeof(*this)); + ptr += sizeof(*this); + + unserialize_engine(engine); + g_dtime_last_vbl = old_g_dtime_last_vbl; + g_dtime_expected = old_g_dtime_expected; + + + memcpy(ptr,g_slow_memory_ptr,128*1024); + ptr+= 128*1024; + memcpy(ptr,g_dummy_memory1_ptr,256); + ptr+=256; + memcpy(ptr,g_memory_ptr,g_mem_size_total); + + // reinitialize les event avant de les copier + for(int i = 1; i < MAX_EVENTS; i++) + { + RECALC_BASE_EVENT_PTR(g_event_list[i-1].next,base); + } + RECALC_BASE_EVENT_PTR(g_event_free.next,base); + RECALC_BASE_EVENT_PTR(g_event_start.next,base); + + g_dtime_last_vbl += get_dtime(); + + return size; + + } +} XCODE_PRAGMA_PACK; +#ifdef _WIN32 +#pragma pack(pop) +#endif + + +extern void x_update_info(const char* total_mhz_ptr); + +extern s_sim65816 g_sim65816; +extern int Verbose; +//extern int g_pause; + + +/* All EV_* must be less than 256, since upper bits reserved for other use */ +/* e.g., DOC_INT uses upper bits to encode oscillator */ +#define EV_60HZ 1 +#define EV_STOP 2 +#define EV_SCAN_INT 3 +#define EV_DOC_INT 4 +#define EV_VBL_INT 5 +#define EV_SCC 6 +#define EV_VID_UPD 7 +#define EV_SCC_ENABLE 8 \ No newline at end of file diff --git a/kegs/Src/size_c.h b/kegs/Src/size_c.h new file mode 100644 index 0000000..dc2cfc4 --- /dev/null +++ b/kegs/Src/size_c.h @@ -0,0 +1,270 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_S + .stringz "@(#)$KmKId: size_tab.h,v 1.13 2002-11-19 03:10:38-05 kadickey Exp $" +#else + + 0x1, /* 00 */ /* brk */ + 0x1, /* 01 */ /* ORA (Dloc,X) */ + 0x1, /* 02 */ /* COP */ + 0x1, /* 03 */ /* ORA Disp8,S */ + 0x1, /* 04 */ /* TSB Dloc */ + 0x1, /* 05 */ /* ORA Dloc */ + 0x1, /* 06 */ /* ASL Dloc */ + 0x1, /* 07 */ /* ORA [Dloc] */ + 0x0, /* 08 */ /* PHP */ + 0x4, /* 09 */ /* ORA #imm */ + 0x0, /* 0a */ /* ASL a */ + 0x0, /* 0b */ /* PHD */ + 0x2, /* 0c */ /* TSB abs */ + 0x2, /* 0d */ /* ORA abs */ + 0x2, /* 0e */ /* ASL abs */ + 0x3, /* 0f */ /* ORA long */ + 0x1, /* 10 */ /* BPL disp8 */ + 0x1, /* 11 */ /* ORA (),y */ + 0x1, /* 12 */ /* ORA () */ + 0x1, /* 13 */ /* ORA (disp8,s),y */ + 0x1, /* 14 */ /* TRB Dloc */ + 0x1, /* 15 */ /* ORA Dloc,x */ + 0x1, /* 16 */ /* ASL Dloc,x */ + 0x1, /* 17 */ /* ORA [],y */ + 0x0, /* 18 */ /* clc */ + 0x2, /* 19 */ /* ORA abs,y */ + 0x0, /* 1a */ /* INC a */ + 0x0, /* 1b */ /* TCS */ + 0x2, /* 1c */ /* TRB Abs */ + 0x2, /* 1d */ /* ORA Abs,X */ + 0x2, /* 1e */ /* ASL abs,x */ + 0x3, /* 1f */ /* ORA Long,x */ + 0x2, /* 20 */ /* JSR abs */ + 0x1, /* 21 */ /* AND (Dloc,X) */ + 0x3, /* 22 */ /* JSL Abslong */ + 0x1, /* 23 */ /* AND Disp8,S */ + 0x1, /* 24 */ /* BIT Dloc */ + 0x1, /* 25 */ /* AND Dloc */ + 0x1, /* 26 */ /* ROL Dloc */ + 0x1, /* 27 */ /* AND [Dloc] */ + 0x0, /* 28 */ /* PLP */ + 0x4, /* 29 */ /* AND #imm */ + 0x0, /* 2a */ /* ROL a */ + 0x0, /* 2b */ /* PLD */ + 0x2, /* 2c */ /* BIT abs */ + 0x2, /* 2d */ /* AND abs */ + 0x2, /* 2e */ /* ROL abs */ + 0x3, /* 2f */ /* AND long */ + 0x1, /* 30 */ /* BMI disp8 */ + 0x1, /* 31 */ /* AND (),y */ + 0x1, /* 32 */ /* AND () */ + 0x1, /* 33 */ /* AND (disp8,s),y */ + 0x1, /* 34 */ /* BIT Dloc,X */ + 0x1, /* 35 */ /* AND Dloc,x */ + 0x1, /* 36 */ /* ROL Dloc,x */ + 0x1, /* 37 */ /* AND [],y */ + 0x0, /* 38 */ /* SEC */ + 0x2, /* 39 */ /* AND abs,y */ + 0x0, /* 3a */ /* DEC a */ + 0x0, /* 3b */ /* TSC */ + 0x2, /* 3c */ /* BIT Abs,X */ + 0x2, /* 3d */ /* AND Abs,X */ + 0x2, /* 3e */ /* ROL abs,x */ + 0x3, /* 3f */ /* AND Long,x */ + 0x0, /* 40 */ /* RTI */ + 0x1, /* 41 */ /* EOR (Dloc,X) */ + 0x1, /* 42 */ /* WDM */ + 0x1, /* 43 */ /* EOR Disp8,S */ + 0x2, /* 44 */ /* MVP I,J */ + 0x1, /* 45 */ /* EOR Dloc */ + 0x1, /* 46 */ /* LSR Dloc */ + 0x1, /* 47 */ /* EOR [Dloc] */ + 0x0, /* 48 */ /* PHA */ + 0x4, /* 49 */ /* EOR #imm */ + 0x0, /* 4a */ /* LSR a */ + 0x0, /* 4b */ /* PHK */ + 0x2, /* 4c */ /* JMP abs */ + 0x2, /* 4d */ /* EOR abs */ + 0x2, /* 4e */ /* LSR abs */ + 0x3, /* 4f */ /* EOR long */ + 0x1, /* 50 */ /* BVC disp8 */ + 0x1, /* 51 */ /* EOR (),y */ + 0x1, /* 52 */ /* EOR () */ + 0x1, /* 53 */ /* EOR (disp8,s),y */ + 0x2, /* 54 */ /* MVN I,J */ + 0x1, /* 55 */ /* EOR Dloc,x */ + 0x1, /* 56 */ /* LSR Dloc,x */ + 0x1, /* 57 */ /* EOR [],y */ + 0x0, /* 58 */ /* CLI */ + 0x2, /* 59 */ /* EOR abs,y */ + 0x0, /* 5a */ /* PHY */ + 0x0, /* 5b */ /* TCD */ + 0x3, /* 5c */ /* JMP Long */ + 0x2, /* 5d */ /* EOR Abs,X */ + 0x2, /* 5e */ /* LSR abs,x */ + 0x3, /* 5f */ /* EOR Long,x */ + 0x0, /* 60 */ /* RTS */ + 0x1, /* 61 */ /* ADC (Dloc,X) */ + 0x2, /* 62 */ /* PER DISP16 */ + 0x1, /* 63 */ /* ADC Disp8,S */ + 0x1, /* 64 */ /* STZ Dloc */ + 0x1, /* 65 */ /* ADC Dloc */ + 0x1, /* 66 */ /* ROR Dloc */ + 0x1, /* 67 */ /* ADC [Dloc] */ + 0x0, /* 68 */ /* PLA */ + 0x4, /* 69 */ /* ADC #imm */ + 0x0, /* 6a */ /* ROR a */ + 0x0, /* 6b */ /* RTL */ + 0x2, /* 6c */ /* JMP (abs) */ + 0x2, /* 6d */ /* ADC abs */ + 0x2, /* 6e */ /* ROR abs */ + 0x3, /* 6f */ /* ADC long */ + 0x1, /* 70 */ /* BVS disp8 */ + 0x1, /* 71 */ /* ADC (),y */ + 0x1, /* 72 */ /* ADC () */ + 0x1, /* 73 */ /* ADC (disp8,s),y */ + 0x1, /* 74 */ /* STZ Dloc,X */ + 0x1, /* 75 */ /* ADC Dloc,x */ + 0x1, /* 76 */ /* ROR Dloc,x */ + 0x1, /* 77 */ /* ADC [],y */ + 0x0, /* 78 */ /* SEI */ + 0x2, /* 79 */ /* ADC abs,y */ + 0x0, /* 7a */ /* PLY */ + 0x0, /* 7b */ /* TDC */ + 0x2, /* 7c */ /* JMP (abs,x) */ + 0x2, /* 7d */ /* ADC Abs,X */ + 0x2, /* 7e */ /* ROR abs,x */ + 0x3, /* 7f */ /* ADC Long,x */ + 0x1, /* 80 */ /* BRA Disp8 */ + 0x1, /* 81 */ /* STA (Dloc,X) */ + 0x2, /* 82 */ /* BRL DISP16 */ + 0x1, /* 83 */ /* STA Disp8,S */ + 0x1, /* 84 */ /* STY Dloc */ + 0x1, /* 85 */ /* STA Dloc */ + 0x1, /* 86 */ /* STX Dloc */ + 0x1, /* 87 */ /* STA [Dloc] */ + 0x0, /* 88 */ /* DEY */ + 0x4, /* 89 */ /* BIT #imm */ + 0x0, /* 8a */ /* TXA */ + 0x0, /* 8b */ /* PHB */ + 0x2, /* 8c */ /* STY abs */ + 0x2, /* 8d */ /* STA abs */ + 0x2, /* 8e */ /* STX abs */ + 0x3, /* 8f */ /* STA long */ + 0x1, /* 90 */ /* BCC disp8 */ + 0x1, /* 91 */ /* STA (),y */ + 0x1, /* 92 */ /* STA () */ + 0x1, /* 93 */ /* STA (disp8,s),y */ + 0x1, /* 94 */ /* STY Dloc,X */ + 0x1, /* 95 */ /* STA Dloc,x */ + 0x1, /* 96 */ /* STX Dloc,y */ + 0x1, /* 97 */ /* STA [],y */ + 0x0, /* 98 */ /* TYA */ + 0x2, /* 99 */ /* STA abs,y */ + 0x0, /* 9a */ /* TXS */ + 0x0, /* 9b */ /* TXY */ + 0x2, /* 9c */ /* STX abs */ + 0x2, /* 9d */ /* STA Abs,X */ + 0x2, /* 9e */ /* STZ abs,x */ + 0x3, /* 9f */ /* STA Long,x */ + 0x5, /* a0 */ /* LDY #imm */ + 0x1, /* a1 */ /* LDA (Dloc,X) */ + 0x5, /* a2 */ /* LDX #imm */ + 0x1, /* a3 */ /* LDA Disp8,S */ + 0x1, /* a4 */ /* LDY Dloc */ + 0x1, /* a5 */ /* LDA Dloc */ + 0x1, /* a6 */ /* LDX Dloc */ + 0x1, /* a7 */ /* LDA [Dloc] */ + 0x0, /* a8 */ /* TAY */ + 0x4, /* a9 */ /* LDA #imm */ + 0x0, /* aa */ /* TAX */ + 0x0, /* ab */ /* PLB */ + 0x2, /* ac */ /* LDY abs */ + 0x2, /* ad */ /* LDA abs */ + 0x2, /* ae */ /* LDX abs */ + 0x3, /* af */ /* LDA long */ + 0x1, /* b0 */ /* BCS disp8 */ + 0x1, /* b1 */ /* LDA (),y */ + 0x1, /* b2 */ /* LDA () */ + 0x1, /* b3 */ /* LDA (disp8,s),y */ + 0x1, /* b4 */ /* LDY Dloc,X */ + 0x1, /* b5 */ /* LDA Dloc,x */ + 0x1, /* b6 */ /* LDX Dloc,y */ + 0x1, /* b7 */ /* LDA [],y */ + 0x0, /* b8 */ /* CLV */ + 0x2, /* b9 */ /* LDA abs,y */ + 0x0, /* ba */ /* TSX */ + 0x0, /* bb */ /* TYX */ + 0x2, /* bc */ /* LDY abs,x */ + 0x2, /* bd */ /* LDA Abs,X */ + 0x2, /* be */ /* LDX abs,y */ + 0x3, /* bf */ /* LDA Long,x */ + 0x5, /* c0 */ /* CPY #Imm */ + 0x1, /* c1 */ /* CMP (Dloc,X) */ + 0x1, /* c2 */ /* REP #8bit */ + 0x1, /* c3 */ /* CMP Disp8,S */ + 0x1, /* c4 */ /* CPY Dloc */ + 0x1, /* c5 */ /* CMP Dloc */ + 0x1, /* c6 */ /* DEC Dloc */ + 0x1, /* c7 */ /* CMP [Dloc] */ + 0x0, /* c8 */ /* INY */ + 0x4, /* c9 */ /* CMP #imm */ + 0x0, /* ca */ /* DEX */ + 0x0, /* cb */ /* WAI */ + 0x2, /* cc */ /* CPY abs */ + 0x2, /* cd */ /* CMP abs */ + 0x2, /* ce */ /* DEC abs */ + 0x3, /* cf */ /* CMP long */ + 0x1, /* d0 */ /* BNE disp8 */ + 0x1, /* d1 */ /* CMP (),y */ + 0x1, /* d2 */ /* CMP () */ + 0x1, /* d3 */ /* CMP (disp8,s),y */ + 0x1, /* d4 */ /* PEI Dloc */ + 0x1, /* d5 */ /* CMP Dloc,x */ + 0x1, /* d6 */ /* DEC Dloc,x */ + 0x1, /* d7 */ /* CMP [],y */ + 0x0, /* d8 */ /* CLD */ + 0x2, /* d9 */ /* CMP abs,y */ + 0x0, /* da */ /* PHX */ + 0x0, /* db */ /* STP */ + 0x2, /* dc */ /* JML (Abs) */ + 0x2, /* dd */ /* CMP Abs,X */ + 0x2, /* de */ /* DEC abs,x */ + 0x3, /* df */ /* CMP Long,x */ + 0x5, /* e0 */ /* CPX #Imm */ + 0x1, /* e1 */ /* SBC (Dloc,X) */ + 0x1, /* e2 */ /* SEP #8bit */ + 0x1, /* e3 */ /* SBC Disp8,S */ + 0x1, /* e4 */ /* CPX Dloc */ + 0x1, /* e5 */ /* SBC Dloc */ + 0x1, /* e6 */ /* INC Dloc */ + 0x1, /* e7 */ /* SBC [Dloc] */ + 0x0, /* e8 */ /* INX */ + 0x4, /* e9 */ /* SBC #imm */ + 0x0, /* ea */ /* NOP */ + 0x0, /* eb */ /* XBA */ + 0x2, /* ec */ /* CPX abs */ + 0x2, /* ed */ /* SBC abs */ + 0x2, /* ee */ /* INC abs */ + 0x3, /* ef */ /* SBC long */ + 0x1, /* f0 */ /* BEQ disp8 */ + 0x1, /* f1 */ /* SBC (),y */ + 0x1, /* f2 */ /* SBC () */ + 0x1, /* f3 */ /* SBC (disp8,s),y */ + 0x2, /* f4 */ /* PEA Imm */ + 0x1, /* f5 */ /* SBC Dloc,x */ + 0x1, /* f6 */ /* INC Dloc,x */ + 0x1, /* f7 */ /* SBC [],y */ + 0x0, /* f8 */ /* SED */ + 0x2, /* f9 */ /* SBC abs,y */ + 0x0, /* fa */ /* PLX */ + 0x0, /* fb */ /* XCE */ + 0x2, /* fc */ /* JSR (Abs,x) */ + 0x2, /* fd */ /* SBC Abs,X */ + 0x2, /* fe */ /* INC abs,x */ + 0x3, /* ff */ /* SBC Long,x */ + + + +#endif diff --git a/kegs/Src/size_tab.h b/kegs/Src/size_tab.h new file mode 100644 index 0000000..1682fad --- /dev/null +++ b/kegs/Src/size_tab.h @@ -0,0 +1,270 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifdef INCLUDE_RCSID_S + .stringz "@(#)$KmKId: size_tab.h,v 1.13 2002-11-19 03:10:38-05 kadickey Exp $" +#else + + .word inst00_SYM+1 /* brk */ + .word inst01_SYM+1 /* ORA (Dloc,X) */ + .word inst02_SYM+1 /* COP */ + .word inst03_SYM+1 /* ORA Disp8,S */ + .word inst04_SYM+1 /* TSB Dloc */ + .word inst05_SYM+1 /* ORA Dloc */ + .word inst06_SYM+1 /* ASL Dloc */ + .word inst07_SYM+1 /* ORA [Dloc] */ + .word inst08_SYM+0 /* PHP */ + .word inst09_SYM+4 /* ORA #imm */ + .word inst0a_SYM+0 /* ASL a */ + .word inst0b_SYM+0 /* PHD */ + .word inst0c_SYM+2 /* TSB abs */ + .word inst0d_SYM+2 /* ORA abs */ + .word inst0e_SYM+2 /* ASL abs */ + .word inst0f_SYM+3 /* ORA long */ + .word inst10_SYM+1 /* BPL disp8 */ + .word inst11_SYM+1 /* ORA (),y */ + .word inst12_SYM+1 /* ORA () */ + .word inst13_SYM+1 /* ORA (disp8,s),y */ + .word inst14_SYM+1 /* TRB Dloc */ + .word inst15_SYM+1 /* ORA Dloc,x */ + .word inst16_SYM+1 /* ASL Dloc,x */ + .word inst17_SYM+1 /* ORA [],y */ + .word inst18_SYM+0 /* clc */ + .word inst19_SYM+2 /* ORA abs,y */ + .word inst1a_SYM+0 /* INC a */ + .word inst1b_SYM+0 /* TCS */ + .word inst1c_SYM+2 /* TRB Abs */ + .word inst1d_SYM+2 /* ORA Abs,X */ + .word inst1e_SYM+2 /* ASL abs,x */ + .word inst1f_SYM+3 /* ORA Long,x */ + .word inst20_SYM+2 /* JSR abs */ + .word inst21_SYM+1 /* AND (Dloc,X) */ + .word inst22_SYM+3 /* JSL Abslong */ + .word inst23_SYM+1 /* AND Disp8,S */ + .word inst24_SYM+1 /* BIT Dloc */ + .word inst25_SYM+1 /* AND Dloc */ + .word inst26_SYM+1 /* ROL Dloc */ + .word inst27_SYM+1 /* AND [Dloc] */ + .word inst28_SYM+0 /* PLP */ + .word inst29_SYM+4 /* AND #imm */ + .word inst2a_SYM+0 /* ROL a */ + .word inst2b_SYM+0 /* PLD */ + .word inst2c_SYM+2 /* BIT abs */ + .word inst2d_SYM+2 /* AND abs */ + .word inst2e_SYM+2 /* ROL abs */ + .word inst2f_SYM+3 /* AND long */ + .word inst30_SYM+1 /* BMI disp8 */ + .word inst31_SYM+1 /* AND (),y */ + .word inst32_SYM+1 /* AND () */ + .word inst33_SYM+1 /* AND (disp8,s),y */ + .word inst34_SYM+1 /* BIT Dloc,X */ + .word inst35_SYM+1 /* AND Dloc,x */ + .word inst36_SYM+1 /* ROL Dloc,x */ + .word inst37_SYM+1 /* AND [],y */ + .word inst38_SYM+0 /* SEC */ + .word inst39_SYM+2 /* AND abs,y */ + .word inst3a_SYM+0 /* DEC a */ + .word inst3b_SYM+0 /* TSC */ + .word inst3c_SYM+2 /* BIT Abs,X */ + .word inst3d_SYM+2 /* AND Abs,X */ + .word inst3e_SYM+2 /* ROL abs,x */ + .word inst3f_SYM+3 /* AND Long,x */ + .word inst40_SYM+0 /* RTI */ + .word inst41_SYM+1 /* EOR (Dloc,X) */ + .word inst42_SYM+1 /* WDM */ + .word inst43_SYM+1 /* EOR Disp8,S */ + .word inst44_SYM+2 /* MVP I,J */ + .word inst45_SYM+1 /* EOR Dloc */ + .word inst46_SYM+1 /* LSR Dloc */ + .word inst47_SYM+1 /* EOR [Dloc] */ + .word inst48_SYM+0 /* PHA */ + .word inst49_SYM+4 /* EOR #imm */ + .word inst4a_SYM+0 /* LSR a */ + .word inst4b_SYM+0 /* PHK */ + .word inst4c_SYM+2 /* JMP abs */ + .word inst4d_SYM+2 /* EOR abs */ + .word inst4e_SYM+2 /* LSR abs */ + .word inst4f_SYM+3 /* EOR long */ + .word inst50_SYM+1 /* BVC disp8 */ + .word inst51_SYM+1 /* EOR (),y */ + .word inst52_SYM+1 /* EOR () */ + .word inst53_SYM+1 /* EOR (disp8,s),y */ + .word inst54_SYM+2 /* MVN I,J */ + .word inst55_SYM+1 /* EOR Dloc,x */ + .word inst56_SYM+1 /* LSR Dloc,x */ + .word inst57_SYM+1 /* EOR [],y */ + .word inst58_SYM+0 /* CLI */ + .word inst59_SYM+2 /* EOR abs,y */ + .word inst5a_SYM+0 /* PHY */ + .word inst5b_SYM+0 /* TCD */ + .word inst5c_SYM+3 /* JMP Long */ + .word inst5d_SYM+2 /* EOR Abs,X */ + .word inst5e_SYM+2 /* LSR abs,x */ + .word inst5f_SYM+3 /* EOR Long,x */ + .word inst60_SYM+0 /* RTS */ + .word inst61_SYM+1 /* ADC (Dloc,X) */ + .word inst62_SYM+2 /* PER DISP16 */ + .word inst63_SYM+1 /* ADC Disp8,S */ + .word inst64_SYM+1 /* STZ Dloc */ + .word inst65_SYM+1 /* ADC Dloc */ + .word inst66_SYM+1 /* ROR Dloc */ + .word inst67_SYM+1 /* ADC [Dloc] */ + .word inst68_SYM+0 /* PLA */ + .word inst69_SYM+4 /* ADC #imm */ + .word inst6a_SYM+0 /* ROR a */ + .word inst6b_SYM+0 /* RTL */ + .word inst6c_SYM+2 /* JMP (abs) */ + .word inst6d_SYM+2 /* ADC abs */ + .word inst6e_SYM+2 /* ROR abs */ + .word inst6f_SYM+3 /* ADC long */ + .word inst70_SYM+1 /* BVS disp8 */ + .word inst71_SYM+1 /* ADC (),y */ + .word inst72_SYM+1 /* ADC () */ + .word inst73_SYM+1 /* ADC (disp8,s),y */ + .word inst74_SYM+1 /* STZ Dloc,X */ + .word inst75_SYM+1 /* ADC Dloc,x */ + .word inst76_SYM+1 /* ROR Dloc,x */ + .word inst77_SYM+1 /* ADC [],y */ + .word inst78_SYM+0 /* SEI */ + .word inst79_SYM+2 /* ADC abs,y */ + .word inst7a_SYM+0 /* PLY */ + .word inst7b_SYM+0 /* TDC */ + .word inst7c_SYM+2 /* JMP (abs,x) */ + .word inst7d_SYM+2 /* ADC Abs,X */ + .word inst7e_SYM+2 /* ROR abs,x */ + .word inst7f_SYM+3 /* ADC Long,x */ + .word inst80_SYM+1 /* BRA Disp8 */ + .word inst81_SYM+1 /* STA (Dloc,X) */ + .word inst82_SYM+2 /* BRL DISP16 */ + .word inst83_SYM+1 /* STA Disp8,S */ + .word inst84_SYM+1 /* STY Dloc */ + .word inst85_SYM+1 /* STA Dloc */ + .word inst86_SYM+1 /* STX Dloc */ + .word inst87_SYM+1 /* STA [Dloc] */ + .word inst88_SYM+0 /* DEY */ + .word inst89_SYM+4 /* BIT #imm */ + .word inst8a_SYM+0 /* TXA */ + .word inst8b_SYM+0 /* PHB */ + .word inst8c_SYM+2 /* STY abs */ + .word inst8d_SYM+2 /* STA abs */ + .word inst8e_SYM+2 /* STX abs */ + .word inst8f_SYM+3 /* STA long */ + .word inst90_SYM+1 /* BCC disp8 */ + .word inst91_SYM+1 /* STA (),y */ + .word inst92_SYM+1 /* STA () */ + .word inst93_SYM+1 /* STA (disp8,s),y */ + .word inst94_SYM+1 /* STY Dloc,X */ + .word inst95_SYM+1 /* STA Dloc,x */ + .word inst96_SYM+1 /* STX Dloc,y */ + .word inst97_SYM+1 /* STA [],y */ + .word inst98_SYM+0 /* TYA */ + .word inst99_SYM+2 /* STA abs,y */ + .word inst9a_SYM+0 /* TXS */ + .word inst9b_SYM+0 /* TXY */ + .word inst9c_SYM+2 /* STX abs */ + .word inst9d_SYM+2 /* STA Abs,X */ + .word inst9e_SYM+2 /* STZ abs,x */ + .word inst9f_SYM+3 /* STA Long,x */ + .word insta0_SYM+5 /* LDY #imm */ + .word insta1_SYM+1 /* LDA (Dloc,X) */ + .word insta2_SYM+5 /* LDX #imm */ + .word insta3_SYM+1 /* LDA Disp8,S */ + .word insta4_SYM+1 /* LDY Dloc */ + .word insta5_SYM+1 /* LDA Dloc */ + .word insta6_SYM+1 /* LDX Dloc */ + .word insta7_SYM+1 /* LDA [Dloc] */ + .word insta8_SYM+0 /* TAY */ + .word insta9_SYM+4 /* LDA #imm */ + .word instaa_SYM+0 /* TAX */ + .word instab_SYM+0 /* PLB */ + .word instac_SYM+2 /* LDY abs */ + .word instad_SYM+2 /* LDA abs */ + .word instae_SYM+2 /* LDX abs */ + .word instaf_SYM+3 /* LDA long */ + .word instb0_SYM+1 /* BCS disp8 */ + .word instb1_SYM+1 /* LDA (),y */ + .word instb2_SYM+1 /* LDA () */ + .word instb3_SYM+1 /* LDA (disp8,s),y */ + .word instb4_SYM+1 /* LDY Dloc,X */ + .word instb5_SYM+1 /* LDA Dloc,x */ + .word instb6_SYM+1 /* LDX Dloc,y */ + .word instb7_SYM+1 /* LDA [],y */ + .word instb8_SYM+0 /* CLV */ + .word instb9_SYM+2 /* LDA abs,y */ + .word instba_SYM+0 /* TSX */ + .word instbb_SYM+0 /* TYX */ + .word instbc_SYM+2 /* LDY abs,x */ + .word instbd_SYM+2 /* LDA Abs,X */ + .word instbe_SYM+2 /* LDX abs,y */ + .word instbf_SYM+3 /* LDA Long,x */ + .word instc0_SYM+5 /* CPY #Imm */ + .word instc1_SYM+1 /* CMP (Dloc,X) */ + .word instc2_SYM+1 /* REP #8bit */ + .word instc3_SYM+1 /* CMP Disp8,S */ + .word instc4_SYM+1 /* CPY Dloc */ + .word instc5_SYM+1 /* CMP Dloc */ + .word instc6_SYM+1 /* DEC Dloc */ + .word instc7_SYM+1 /* CMP [Dloc] */ + .word instc8_SYM+0 /* INY */ + .word instc9_SYM+4 /* CMP #imm */ + .word instca_SYM+0 /* DEX */ + .word instcb_SYM+0 /* WAI */ + .word instcc_SYM+2 /* CPY abs */ + .word instcd_SYM+2 /* CMP abs */ + .word instce_SYM+2 /* DEC abs */ + .word instcf_SYM+3 /* CMP long */ + .word instd0_SYM+1 /* BNE disp8 */ + .word instd1_SYM+1 /* CMP (),y */ + .word instd2_SYM+1 /* CMP () */ + .word instd3_SYM+1 /* CMP (disp8,s),y */ + .word instd4_SYM+1 /* PEI Dloc */ + .word instd5_SYM+1 /* CMP Dloc,x */ + .word instd6_SYM+1 /* DEC Dloc,x */ + .word instd7_SYM+1 /* CMP [],y */ + .word instd8_SYM+0 /* CLD */ + .word instd9_SYM+2 /* CMP abs,y */ + .word instda_SYM+0 /* PHX */ + .word instdb_SYM+0 /* STP */ + .word instdc_SYM+2 /* JML (Abs) */ + .word instdd_SYM+2 /* CMP Abs,X */ + .word instde_SYM+2 /* DEC abs,x */ + .word instdf_SYM+3 /* CMP Long,x */ + .word inste0_SYM+5 /* CPX #Imm */ + .word inste1_SYM+1 /* SBC (Dloc,X) */ + .word inste2_SYM+1 /* SEP #8bit */ + .word inste3_SYM+1 /* SBC Disp8,S */ + .word inste4_SYM+1 /* CPX Dloc */ + .word inste5_SYM+1 /* SBC Dloc */ + .word inste6_SYM+1 /* INC Dloc */ + .word inste7_SYM+1 /* SBC [Dloc] */ + .word inste8_SYM+0 /* INX */ + .word inste9_SYM+4 /* SBC #imm */ + .word instea_SYM+0 /* NOP */ + .word insteb_SYM+0 /* XBA */ + .word instec_SYM+2 /* CPX abs */ + .word insted_SYM+2 /* SBC abs */ + .word instee_SYM+2 /* INC abs */ + .word instef_SYM+3 /* SBC long */ + .word instf0_SYM+1 /* BEQ disp8 */ + .word instf1_SYM+1 /* SBC (),y */ + .word instf2_SYM+1 /* SBC () */ + .word instf3_SYM+1 /* SBC (disp8,s),y */ + .word instf4_SYM+2 /* PEA Imm */ + .word instf5_SYM+1 /* SBC Dloc,x */ + .word instf6_SYM+1 /* INC Dloc,x */ + .word instf7_SYM+1 /* SBC [],y */ + .word instf8_SYM+0 /* SED */ + .word instf9_SYM+2 /* SBC abs,y */ + .word instfa_SYM+0 /* PLX */ + .word instfb_SYM+0 /* XCE */ + .word instfc_SYM+2 /* JSR (Abs,x) */ + .word instfd_SYM+2 /* SBC Abs,X */ + .word instfe_SYM+2 /* INC abs,x */ + .word instff_SYM+3 /* SBC Long,x */ + + .block 4*16 + +#endif diff --git a/kegs/Src/smartport.cpp b/kegs/Src/smartport.cpp new file mode 100644 index 0000000..4120310 --- /dev/null +++ b/kegs/Src/smartport.cpp @@ -0,0 +1,798 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "sim65816.h" +#include "iwm.h" + + +#define LEN_SMPT_LOG 16 +STRUCT(Smpt_log) { + word32 start_addr; + int cmd; + int rts_addr; + int cmd_list; + int extras; + int unit; + int buf; + int blk; +}; + +Smpt_log g_smpt_log[LEN_SMPT_LOG]; +int g_smpt_log_pos = 0; + +void +smartport_error(void) +{ + int pos; + int i; + + pos = g_smpt_log_pos; + printf("Smartport log pos: %d\n", pos); + for(i = 0; i < LEN_SMPT_LOG; i++) { + pos--; + if(pos < 0) { + pos = LEN_SMPT_LOG - 1; + } + printf("%d:%d: t:%04x, cmd:%02x, rts:%04x, " + "cmd_l:%04x, x:%d, unit:%d, buf:%04x, blk:%04x\n", + i, pos, + g_smpt_log[pos].start_addr, + g_smpt_log[pos].cmd, + g_smpt_log[pos].rts_addr, + g_smpt_log[pos].cmd_list, + g_smpt_log[pos].extras, + g_smpt_log[pos].unit, + g_smpt_log[pos].buf, + g_smpt_log[pos].blk); + } +} +void +smartport_log(word32 start_addr, int cmd, int rts_addr, int cmd_list) +{ + int pos; + + pos = g_smpt_log_pos; + if(start_addr != 0) { + g_smpt_log[pos].start_addr = start_addr; + g_smpt_log[pos].cmd = cmd; + g_smpt_log[pos].rts_addr = rts_addr; + g_smpt_log[pos].cmd_list = cmd_list; + g_smpt_log[pos].extras = 0; + g_smpt_log[pos].unit = 0; + g_smpt_log[pos].buf = 0; + g_smpt_log[pos].blk = 0; + } else { + pos--; + if(pos < 0) { + pos = LEN_SMPT_LOG - 1; + } + g_smpt_log[pos].extras = 1; + g_smpt_log[pos].unit = cmd; + g_smpt_log[pos].buf = rts_addr; + g_smpt_log[pos].blk = cmd_list; + } + pos++; + if(pos >= LEN_SMPT_LOG) { + pos = 0; + } + g_smpt_log_pos = pos; +} + +void +do_c70d(word32 arg0) +{ + int cmd; + int cmd_list_lo, cmd_list_mid, cmd_list_hi; + int rts_lo, rts_hi; + word32 rts_addr; + word32 cmd_list; + int unit; + int param_cnt; + int status_ptr_lo, status_ptr_mid, status_ptr_hi; + int buf_ptr_lo, buf_ptr_hi; + int buf_ptr; + int block_lo, block_mid, block_hi; + int block; + word32 status_ptr; + int status_code; + int ctl_ptr_lo, ctl_ptr_hi; + int ctl_ptr; + int ctl_code; + int mask; + int stat_val; + int size; + int ret; + int ext; + int i; + + set_memory_c(0x7f8, 0xc7, 0); + + if((g_sim65816.engine.psr & 0x100) == 0) { + disk_printf("c70d called in native mode!\n"); + if((g_sim65816.engine.psr & 0x30) != 0x30) { + halt_printf("c70d called native, psr: %03x!\n", + g_sim65816.engine.psr); + } + } + + g_sim65816.engine.stack = ((g_sim65816.engine.stack + 1) & 0xff) + 0x100; + rts_lo = get_memory_c(g_sim65816.engine.stack, 0); + g_sim65816.engine.stack = ((g_sim65816.engine.stack + 1) & 0xff) + 0x100; + rts_hi = get_memory_c(g_sim65816.engine.stack, 0); + rts_addr = (rts_lo + (256*rts_hi) + 1) & 0xffff; + disk_printf("rts_addr: %04x\n", rts_addr); + + cmd = get_memory_c(rts_addr, 0); + cmd_list_lo = get_memory_c((rts_addr + 1) & 0xffff, 0); + cmd_list_mid = get_memory_c((rts_addr + 2) & 0xffff, 0); + cmd_list_hi = 0; + mask = 0xffff; + if(cmd & 0x40) { + /* extended */ + mask = 0xffffff; + cmd_list_hi = get_memory_c((rts_addr + 3) & 0xffff, 0); + } + + cmd_list = cmd_list_lo + (256*cmd_list_mid) + (65536*cmd_list_hi); + + disk_printf("cmd: %02x, cmd_list: %06x\n", cmd, cmd_list); + param_cnt = get_memory_c(cmd_list, 0); + + ext = 0; + if(cmd & 0x40) { + ext = 2; + } + + smartport_log(0xc70d, cmd, rts_addr, cmd_list); + + switch(cmd & 0x3f) { + case 0x00: /* Status == 0x00 and 0x40 */ + if(param_cnt != 3) { + disk_printf("param_cnt %d is != 3!\n", param_cnt); + x_exit(8); + } + unit = get_memory_c((cmd_list+1) & mask, 0); + status_ptr_lo = get_memory_c((cmd_list+2) & mask, 0); + status_ptr_mid = get_memory_c((cmd_list+3) & mask, 0); + status_ptr_hi = 0; + if(cmd & 0x40) { + status_ptr_hi = get_memory_c((cmd_list+4) & mask, 0); + } + + status_ptr = status_ptr_lo + (256*status_ptr_mid) + + (65536*status_ptr_hi); + if(cmd & 0x40) { + status_code = get_memory_c((cmd_list+6) & mask, 0); + } else { + status_code = get_memory_c((cmd_list+4) & mask, 0); + } + + smartport_log(0, unit, status_ptr, status_code); + + disk_printf("unit: %02x, status_ptr: %06x, code: %02x\n", + unit, status_ptr, status_code); + if(unit == 0 && status_code == 0) { + /* Smartport driver status */ + /* see technotes/smpt/tn-smpt-002 */ + set_memory_c(status_ptr, g_iwm.g_highest_smartport_unit+1, 0); + set_memory_c(status_ptr+1, 0xff, 0); /* interrupt stat*/ + set_memory16_c(status_ptr+2, 0x0002, 0); /* vendor id */ + set_memory16_c(status_ptr+4, 0x1000, 0); /* version */ + set_memory16_c(status_ptr+6, 0x0000, 0); + + g_sim65816.engine.xreg = 8; + g_sim65816.engine.yreg = 0; + g_sim65816.engine.acc &= 0xff00; + g_sim65816.engine.psr &= ~1; + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & mask; + return; + } else if(unit > 0 && status_code == 0) { + /* status for unit x */ + if(unit > MAX_C7_DISKS || g_iwm.iwm.smartport[unit-1].fd < 0){ + stat_val = 0x80; + size = 0; + } else { + stat_val = 0xf8; + size = g_iwm.iwm.smartport[unit-1].image_size; + size = (size+511) / 512; + } + set_memory_c(status_ptr, stat_val, 0); + set_memory24_c(status_ptr +1, size, 0); + g_sim65816.engine.xreg = 4; + if(cmd & 0x40) { + set_memory_c(status_ptr + 4, + (size >> 16) & 0xff, 0); + g_sim65816.engine.xreg = 5; + } + g_sim65816.engine.yreg = 0; + g_sim65816.engine.acc &= 0xff00; + g_sim65816.engine.psr &= ~1; + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & mask; + + disk_printf("just finished unit %d, stat 0\n", unit); + return; + } else if(status_code == 3) { + if(unit > MAX_C7_DISKS || g_iwm.iwm.smartport[unit-1].fd < 0){ + stat_val = 0x80; + size = 0; + } else { + stat_val = 0xf8; + size = g_iwm.iwm.smartport[unit-1].image_size; + size = (size+511) / 512; + } + if(cmd & 0x40) { + disk_printf("extended for stat_code 3!\n"); + } + /* DIB for unit 1 */ + set_memory_c(status_ptr, stat_val, 0); + set_memory24_c(status_ptr +1, size, 0); + if(cmd & 0x40) { + set_memory_c(status_ptr + 4, + (size >> 24) & 0xff, 0); + status_ptr++; + } + set_memory_c(status_ptr +4, 4, 0); + for(i = 5; i < 21; i++) { + set_memory_c(status_ptr +i, 0x20, 0); + } + set_memory_c(status_ptr +5, 'K', 0); + set_memory_c(status_ptr +6, 'E', 0); + set_memory_c(status_ptr +7, 'G', 0); + set_memory_c(status_ptr +8, 'S', 0); + + /* hard disk supporting extended calls */ + set_memory16_c(status_ptr + 21, 0xa002, 0); + set_memory16_c(status_ptr + 23, 0x0000, 0); + + if(cmd & 0x40) { + g_sim65816.engine.xreg = 26; + } else { + g_sim65816.engine.xreg = 25; + } + g_sim65816.engine.yreg = 0; + g_sim65816.engine.acc &= 0xff00; + g_sim65816.engine.psr &= ~1; + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & 0xffff; + + disk_printf("Just finished unit %d, stat 3\n", unit); + if(unit == 0 || unit > MAX_C7_DISKS) { + g_sim65816.engine.acc |= 0x28; + g_sim65816.engine.psr |= 1; + } + return; + } + printf("cmd: 00, unknown unit/status code!\n"); + break; + case 0x01: /* Read Block == 0x01 and 0x41 */ + if(param_cnt != 3) { + halt_printf("param_cnt %d is != 3!\n", param_cnt); + return; + } + unit = get_memory_c((cmd_list+1) & mask, 0); + buf_ptr_lo = get_memory_c((cmd_list+2) & mask, 0); + buf_ptr_hi = get_memory_c((cmd_list+3) & mask, 0); + + buf_ptr = buf_ptr_lo + (256*buf_ptr_hi); + if(cmd & 0x40) { + buf_ptr_lo = get_memory_c((cmd_list+4) & mask, 0); + buf_ptr_hi = get_memory_c((cmd_list+5) & mask, 0); + buf_ptr += ((buf_ptr_hi*256) + buf_ptr_lo)*65536; + cmd_list += 2; + } + block_lo = get_memory_c((cmd_list+4) & mask, 0); + block_mid = get_memory_c((cmd_list+5) & mask, 0); + block_hi = get_memory_c((cmd_list+6) & mask, 0); + block = ((block_hi*256) + block_mid)*256 + block_lo; + disk_printf("smartport read unit %d of block %04x into %04x\n", + unit, block, buf_ptr); + if(unit < 1 || unit > MAX_C7_DISKS) { + halt_printf("Unknown unit #: %d\n", unit); + } + + smartport_log(0, unit - 1, buf_ptr, block); + + ret = do_read_c7(unit - 1, buf_ptr, block); + g_sim65816.engine.xreg = 0; + g_sim65816.engine.yreg = 2; + g_sim65816.engine.acc = (g_sim65816.engine.acc & 0xff00) | (ret & 0xff); + g_sim65816.engine.psr &= ~1; + if(ret != 0) { + g_sim65816.engine.psr |= 1; + } + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & 0xffff; + + return; + break; + case 0x02: /* Write Block == 0x02 and 0x42 */ + if(param_cnt != 3) { + halt_printf("param_cnt %d is != 3!\n", param_cnt); + return; + } + unit = get_memory_c((cmd_list+1) & mask, 0); + buf_ptr_lo = get_memory_c((cmd_list+2) & mask, 0); + buf_ptr_hi = get_memory_c((cmd_list+3) & mask, 0); + + buf_ptr = buf_ptr_lo + (256*buf_ptr_hi); + if(cmd & 0x40) { + buf_ptr_lo = get_memory_c((cmd_list+4) & mask, 0); + buf_ptr_hi = get_memory_c((cmd_list+5) & mask, 0); + buf_ptr += ((buf_ptr_hi*256) + buf_ptr_lo)*65536; + cmd_list += 2; + } + block_lo = get_memory_c((cmd_list+4) & mask, 0); + block_mid = get_memory_c((cmd_list+5) & mask, 0); + block_hi = get_memory_c((cmd_list+6) & mask, 0); + block = ((block_hi*256) + block_mid)*256 + block_lo; + disk_printf("smartport write unit %d of block %04x from %04x\n", + unit, block, buf_ptr); + if(unit < 1 || unit > MAX_C7_DISKS) { + halt_printf("Unknown unit #: %d\n", unit); + } + + smartport_log(0, unit - 1, buf_ptr, block); + + ret = do_write_c7(unit - 1, buf_ptr, block); + g_sim65816.engine.xreg = 0; + g_sim65816.engine.yreg = 2; + g_sim65816.engine.acc = (g_sim65816.engine.acc & 0xff00) | (ret & 0xff); + g_sim65816.engine.psr &= ~1; + if(ret != 0) { + g_sim65816.engine.psr |= 1; + } + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & 0xffff; + + HALT_ON(HALT_ON_C70D_WRITES, "c70d Write done\n"); + return; + break; + case 0x03: /* Format == 0x03 and 0x43 */ + if(param_cnt != 1) { + halt_printf("param_cnt %d is != 1!\n", param_cnt); + return; + } + unit = get_memory_c((cmd_list+1) & mask, 0); + + if(unit < 1 || unit > MAX_C7_DISKS) { + halt_printf("Unknown unit #: %d\n", unit); + } + + smartport_log(0, unit - 1, 0, 0); + + ret = do_format_c7(unit - 1); + g_sim65816.engine.xreg = 0; + g_sim65816.engine.yreg = 2; + g_sim65816.engine.acc = (g_sim65816.engine.acc & 0xff00) | (ret & 0xff); + g_sim65816.engine.psr &= ~1; + if(ret != 0) { + g_sim65816.engine.psr |= 1; + } + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & 0xffff; + + HALT_ON(HALT_ON_C70D_WRITES, "c70d Format done\n"); + return; + break; + case 0x04: /* Control == 0x04 and 0x44 */ + if(cmd == 0x44) { + halt_printf("smartport code 0x44 not supported\n"); + } + if(param_cnt != 3) { + halt_printf("param_cnt %d is != 3!\n", param_cnt); + return; + } + unit = get_memory_c((cmd_list+1) & mask, 0); + ctl_ptr_lo = get_memory_c((cmd_list+2) & mask, 0); + ctl_ptr_hi = get_memory_c((cmd_list+3) & mask, 0); + + ctl_ptr = (ctl_ptr_hi << 8) + ctl_ptr_lo; + if(cmd & 0x40) { + ctl_ptr_lo = get_memory_c((cmd_list+4) & mask, 0); + ctl_ptr_hi = get_memory_c((cmd_list+5) & mask, 0); + ctl_ptr += ((ctl_ptr_hi << 8) + ctl_ptr_lo) << 16; + cmd_list += 2; + } + + ctl_code = get_memory_c((cmd_list +4) & mask, 0); + + switch(ctl_code) { + case 0x00: + printf("Performing a reset on unit %d\n", unit); + break; + default: + halt_printf("control code: %02x unknown!\n", ctl_code); + } + + g_sim65816.engine.xreg = 0; + g_sim65816.engine.yreg = 2; + g_sim65816.engine.acc &= 0xff00; + g_sim65816.engine.psr &= ~1; + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & 0xffff; + return; + break; + default: /* Unknown command! */ + /* set acc = 1, and set carry, and set kpc */ + g_sim65816.engine.xreg = (rts_addr) & 0xff; + g_sim65816.engine.yreg = (rts_addr >> 8) & 0xff; + g_sim65816.engine.acc = (g_sim65816.engine.acc & 0xff00) + 0x01; + g_sim65816.engine.psr |= 0x01; /* set carry */ + g_sim65816.engine.kpc = (rts_addr + 3 + ext) & 0xffff; + if(cmd != 0x4a && cmd != 0x48) { + /* Finder does 0x4a call before formatting disk */ + /* Many things do 0x48 call to see online drives */ + halt_printf("Just did smtport cmd:%02x rts_addr:%04x, " + "cmdlst:%06x\n", cmd, rts_addr, cmd_list); + } + return; + } + + halt_printf("Unknown smtport cmd:%02x, cmd_list:%06x, rts_addr:%06x\n", + cmd, cmd_list, rts_addr); +} + +void +do_c70a(word32 arg0) +{ + int cmd, unit; + int buf_lo, buf_hi; + int blk_lo, blk_hi; + int blk, buf; + int prodos_unit; + int size; + int ret; + + set_memory_c(0x7f8, 0xc7, 0); + + cmd = get_memory_c((g_sim65816.engine.direct + 0x42) & 0xffff, 0); + prodos_unit = get_memory_c((g_sim65816.engine.direct + 0x43) & 0xffff, 0); + buf_lo = get_memory_c((g_sim65816.engine.direct + 0x44) & 0xffff, 0); + buf_hi = get_memory_c((g_sim65816.engine.direct + 0x45) & 0xffff, 0); + blk_lo = get_memory_c((g_sim65816.engine.direct + 0x46) & 0xffff, 0); + blk_hi = get_memory_c((g_sim65816.engine.direct + 0x47) & 0xffff, 0); + + blk = (blk_hi << 8) + blk_lo; + buf = (buf_hi << 8) + buf_lo; + disk_printf("cmd: %02x, pro_unit: %02x, buf: %04x, blk: %04x\n", + cmd, prodos_unit, buf, blk); + + if((prodos_unit & 0x7f) == 0x70) { + unit = 0 + (prodos_unit >> 7); + } else if((prodos_unit & 0x7f) == 0x40) { + unit = 2 + (prodos_unit >> 7); + } else { + halt_printf("Unknown prodos_unit: %d\n", prodos_unit); + return; + } + + smartport_log(0xc70a, cmd, blk, buf); + + g_sim65816.engine.psr &= ~1; /* clear carry */ + if(g_sim65816.g_rom_version >= 3) { + g_sim65816.engine.kpc = 0xc764; + } else { + g_sim65816.engine.kpc = 0xc765; + } + + ret = 0x27; /* I/O error */ + if(cmd == 0x00) { + size = g_iwm.iwm.smartport[unit].image_size; + size = (size+511) / 512; + + smartport_log(0, unit, size, 0); + + ret = 0; + g_sim65816.engine.xreg = size & 0xff; + g_sim65816.engine.yreg = size >> 8; + } else if(cmd == 0x01) { + smartport_log(0, unit, buf, blk); + ret = do_read_c7(unit, buf, blk); + } else if(cmd == 0x02) { + smartport_log(0, unit, buf, blk); + ret = do_write_c7(unit, buf, blk); + } else if(cmd == 0x03) { /* format */ + smartport_log(0, unit, buf, blk); + ret = do_format_c7(unit); + } + + g_sim65816.engine.acc = (g_sim65816.engine.acc & 0xff00) | (ret & 0xff); + if(ret != 0) { + g_sim65816.engine.psr |= 1; + } + return; +} + +int +do_read_c7(int unit_num, word32 buf, int blk) +{ + byte local_buf[0x200]; + register word32 start_time; + register word32 end_time; + word32 val; + int len; + int fd; + int image_start; + int image_size; + int ret; + int i; + + if(unit_num < 0 || unit_num > MAX_C7_DISKS) { + halt_printf("do_read_c7: unit_num: %d\n", unit_num); + smartport_error(); + return 0x28; + } + + fd = g_iwm.iwm.smartport[unit_num].fd; + image_start = g_iwm.iwm.smartport[unit_num].image_start; + image_size = g_iwm.iwm.smartport[unit_num].image_size; + if(fd < 0) { + printf("c7_fd == %d!\n", fd); +#if 0 + if(blk != 2 && blk != 0) { + /* don't print error if only reading directory */ + smartport_error(); + halt_printf("Read unit:%02x blk:%04x\n", unit_num, blk); + } +#endif + return 0x2f; + } + + ret = lseek(fd, image_start + blk*0x200, SEEK_SET); + if(ret != image_start + blk*0x200) { + halt_printf("lseek returned %08x, errno: %d\n", ret, errno); + smartport_error(); + return 0x27; + } + + if(ret >= image_start + image_size) { + halt_printf("Tried to read from pos %08x on disk, (blk:%04x)\n", + ret, blk); + smartport_error(); + return 0x27; + } + + len = read(fd, (char*)&local_buf[0], 0x200); + if(len != 0x200) { + printf("read returned %08x, errno:%d, blk:%04x, unit: %02x\n", + len, errno, blk, unit_num); + halt_printf("name: %s\n", g_iwm.iwm.smartport[unit_num].name_ptr); + smartport_error(); + return 0x27; + } + + g_sim65816.g_io_amt += 0x200; + + if(buf >= 0xfc0000) { + disk_printf("reading into ROM, just returning\n"); + return 0; + } + + GET_ITIMER(start_time); + + for(i = 0; i < 0x200; i += 2) { + val = (local_buf[i+1] << 8) + local_buf[i]; + set_memory16_c(buf + i, val, 0); + } + + GET_ITIMER(end_time); + + g_iwm.g_cycs_in_io_read += (end_time - start_time); + + return 0; + +} + +int +do_write_c7(int unit_num, word32 buf, int blk) +{ + word32 local_buf[0x200/4]; + Disk *dsk; + word32 *ptr; + word32 val1, val2; + word32 val; + int len; + int ret; + int fd; + int image_start; + int image_size; + int i; + + if(unit_num < 0 || unit_num > MAX_C7_DISKS) { + halt_printf("do_write_c7: unit_num: %d\n", unit_num); + smartport_error(); + return 0x28; + } + + dsk = &(g_iwm.iwm.smartport[unit_num]); + fd = dsk->fd; + image_start = dsk->image_start; + image_size = dsk->image_size; + if(fd < 0) { + halt_printf("c7_fd == %d!\n", fd); + smartport_error(); + return 0x28; + } + + ptr = &(local_buf[0]); + for(i = 0; i < 0x200; i += 4) { + val1 = get_memory16_c(buf + i, 0); + val2 = get_memory16_c(buf + i + 2, 0); + /* reorder the little-endian bytes to be big-endian */ +#ifdef KEGS_LITTLE_ENDIAN + val = (val2 << 16) + val1; +#else + val = (val1 << 24) + ((val1 << 8) & 0xff0000) + + ((val2 << 8) & 0xff00) + (val2 >> 8); +#endif + *ptr++ = val; + } + + ret = lseek(fd, image_start + blk*0x200, SEEK_SET); + if(ret != image_start + blk*0x200) { + halt_printf("lseek returned %08x, errno: %d\n", ret, errno); + smartport_error(); + return 0x27; + } + + if(ret >= image_start + image_size) { + halt_printf("Tried to write to %08x\n", ret); + smartport_error(); + return 0x27; + } + + if(dsk->write_prot) { + printf("Write, but %s is write protected!\n", dsk->name_ptr); + return 0x2b; + } + + if(dsk->write_through_to_unix == 0) { + halt_printf("Write to %s, but not wr_thru!\n", dsk->name_ptr); + return 0x00; + } + + len = write(fd, (byte *)&local_buf[0], 0x200); + if(len != 0x200) { + halt_printf("write ret %08x bytes, errno: %d\n", len, errno); + smartport_error(); + return 0x27; + } + + g_sim65816.g_io_amt += 0x200; + + return 0; + +} + +int +do_format_c7(int unit_num) +{ + byte local_buf[0x1000]; + Disk *dsk; + int len; + int ret; + int sum; + int total; + int max; + int image_start; + int image_size; + int fd; + int i; + + if(unit_num < 0 || unit_num > MAX_C7_DISKS) { + halt_printf("do_format_c7: unit_num: %d\n", unit_num); + smartport_error(); + return 0x28; + } + + dsk = &(g_iwm.iwm.smartport[unit_num]); + fd = dsk->fd; + image_start = dsk->image_start; + image_size = dsk->image_size; + if(fd < 0) { + halt_printf("c7_fd == %d!\n", fd); + smartport_error(); + return 0x28; + } + + for(i = 0; i < 0x1000; i++) { + local_buf[i] = 0; + } + + ret = lseek(fd, image_start, SEEK_SET); + if(ret != image_start) { + halt_printf("lseek returned %08x, errno: %d\n", ret, errno); + smartport_error(); + return 0x27; + } + + if(dsk->write_prot) { + printf("Format, but %s is write protected!\n", dsk->name_ptr); + return 0x2b; + } + + if(dsk->write_through_to_unix == 0) { + printf("Format of %s ignored\n", dsk->name_ptr); + return 0x00; + } + + sum = 0; + total = image_size; + + while(sum < total) { + max = MIN(0x1000, total-sum); + len = write(fd, &local_buf[0], max); + if(len != max) { + halt_printf("write ret %08x, errno:%d\n", len, errno); + smartport_error(); + return 0x27; + } + sum += len; + } + + return 0; +} + + +void +do_c700(word32 ret) +{ + disk_printf("do_c700 called, ret: %08x\n", ret); + + ret = do_read_c7(0, 0x800, 0); + + set_memory_c(0x7f8, 7, 0); + set_memory16_c(0x42, 0x7001, 0); + set_memory16_c(0x44, 0x0800, 0); + set_memory16_c(0x46, 0x0000, 0); + g_sim65816.engine.xreg = 0x70; + g_sim65816.engine.kpc = 0x801; + + if(ret != 0) { + printf("Failure reading boot disk in s7d1!\n"); +#if defined(_DEBUG) || defined(DRIVER_IOS) + const byte iphonebootstrap[][0x80]={ + { + 0x20,0x58,0xFC, // call FC58 CLS + 0xa0,0x00, // ldy 0 + 0xb9,0x80,0x3, // @loop lda 380,y + 0xf0,0x13, // beq @end + 0x5A, // phy + 0xc9,0x0d, // cmp 0d + 0xd0,0x05, // bne @reg + 0x20,0x62,0xFC, // call lf + 0x80,0x05, // bra @next + 0x09,0x80, // ora 80 + 0x20,0xED,0xFD, // call cout + 0x7A, // ply + 0xC8, // @next iny + 0x80,0xE8, // @bra loop + // 0x4c,0x59,0xFF, // @end call FF59 dbg + 0x4c,0x00,0xe0, + 0x00 + }, + { + 0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D, + ']','W','e','l','c','o','m','e',' ','t','o',' ', + +#if 0 + 'B','e','s','t',' ','O','f',' ','F','T','A', +#else + 'A','c','t','i','v','e','G','S', +#endif + 0x0D, + ' ','S','w','i','p','e',' ','u','p','/','d','o','w','n',' ','f','o','r',' ','m','e','n','u',0x0D, + 0x0D, + 0 + } + }; + + extern byte* g_memory_ptr; + memcpy(g_memory_ptr+0x300,&iphonebootstrap,sizeof(iphonebootstrap)); + + g_sim65816.engine.kpc = 0x0300; /* Jump to monitor, fix $36-$39 */ +#else + g_sim65816.engine.kpc = 0xff59; /* Jump to monitor, fix $36-$39 */ +#endif + } +} + diff --git a/kegs/Src/sound.cpp b/kegs/Src/sound.cpp new file mode 100644 index 0000000..365e5a1 --- /dev/null +++ b/kegs/Src/sound.cpp @@ -0,0 +1,1925 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "moremem.h" +#include "sim65816.h" +#include "StdString.h" +#include "driver.h" + +#define INCLUDE_RCSID_C +#include "sound.h" +#undef INCLUDE_RCSID_C + +s_sound g_sound; + +system_sound g_system_sounds[] = +{ + { "floppy_eject.wav", 0 }, + { "Spin Up Search 1.wav", 0 }, + { "Spin Up Search 2.wav", 0 }, + { "Search Skip Search 1.wav", 0 }, + { "Search Skip Search 2.wav", 0 }, + { "Search Skip Search 3.wav", 0 }, + { "Search Skip Search 4.wav", 0 }, + { "Search Skip Search 5.wav", 0 }, +}; + +#if 0 +# define DO_DOC_LOG +#endif + +extern int g_use_shmem; +word32 *g_sound_shm_addr ; + +//extern int g_preferred_rate; + +void U_STACK_TRACE(); + +/* local function prototypes */ +void doc_write_ctl_reg(int osc, int val, double dsamps); + +#define LEN_DOC_LOG 128 + +#define UPDATE_G_DCYCS_PER_DOC_UPDATE(osc_en) \ + g_sound.g_dcycs_per_doc_update = (double)((osc_en + 2) * DCYCS_1_MHZ) / \ + DOC_SCAN_RATE; \ + g_sound.g_dupd_per_dcyc = 1.0 / g_sound.g_dcycs_per_doc_update; \ + g_sound.g_drecip_osc_en_plus_2 = 1.0 / (double)(osc_en + 2); + +#define DOC_SCAN_RATE (DCYCS_28_MHZ/32.0) + +#define SND_PTR_SHIFT 14 +#define SND_PTR_SHIFT_DBL ((double)(1 << SND_PTR_SHIFT)) + +STRUCT(Doc_log) { + char *msg; + int osc; + double dsamps; + double dtmp2; + int etc; + Doc_reg doc_reg; +}; + +Doc_log g_doc_log[LEN_DOC_LOG]; +int g_doc_log_pos = 0; + + +#ifdef DO_DOC_LOG +# define DOC_LOG(a,b,c,d) doc_log_rout(a,b,c,d) +#else +# define DOC_LOG(a,b,c,d) +#endif + +word32 g_cycs_in_sound1 = 0; +word32 g_cycs_in_sound2 = 0; +word32 g_cycs_in_sound3 = 0; +word32 g_cycs_in_sound4 = 0; +word32 g_cycs_in_start_sound = 0; +word32 g_cycs_in_est_sound = 0; + +int g_num_snd_plays = 0; +int g_num_doc_events = 0; +int g_num_start_sounds = 0; +int g_num_scan_osc = 0; +int g_num_recalc_snd_parms = 0; + +int g_sound_file_num = 0; +int g_sound_file_fd = -1; +int g_send_sound_to_file = 0; +int g_send_file_bytes = 0; + +float g_fvoices = 0.0f; + + +void +doc_log_rout(char *msg, int osc, double dsamps, int etc) +{ + int pos; + + pos = g_doc_log_pos; + g_doc_log[pos].msg = msg; + g_doc_log[pos].osc = osc; + g_doc_log[pos].dsamps = dsamps; + g_doc_log[pos].dtmp2 = g_sound.g_last_sound_play_dsamp; + g_doc_log[pos].etc = etc; + if(osc >= 0 && osc < 32) { + g_doc_log[pos].doc_reg = g_sound.g_doc_regs[osc]; + } + pos++; + if(pos >= LEN_DOC_LOG) { + pos = 0; + } + + doc_printf("log: %s, osc:%d dsamp:%f, etc:%d\n", msg, osc, dsamps, etc); + + g_doc_log_pos = pos; +} + + +void +show_doc_log(void) +{ + FILE *docfile; + Doc_reg *rptr; + double dsamp_start; + int osc, ctl, freq; + int pos; + int i; + + docfile = fopen("doc_log_out", "w"); + if(docfile == 0) { + printf("fopen failed, errno: %d\n", errno); + return; + } + pos = g_doc_log_pos; + fprintf(docfile, "DOC log pos: %d\n", pos); + dsamp_start = g_doc_log[pos].dsamps; + for(i = 0; i < LEN_DOC_LOG; i++) { + rptr = &(g_doc_log[pos].doc_reg); + osc = g_doc_log[pos].osc; + ctl = rptr->ctl; + freq = rptr->freq; + if(osc < 0) { + ctl = 0; + freq = 0; + } + fprintf(docfile, "%03x:%03x: %-11s ds:%11.1f dt2:%10.1f " + "etc:%08x o:%02x c:%02x fq:%04x\n", + i, pos, g_doc_log[pos].msg, + g_doc_log[pos].dsamps - dsamp_start, + g_doc_log[pos].dtmp2, + g_doc_log[pos].etc, osc & 0xff, ctl, freq); + if(osc >= 0) { + fprintf(docfile, " ire:%d,%d,%d ptr4:%08x " + "inc4:%08x comp_ds:%.1f left:%04x, vol:%02x " + "wptr:%02x, wsz:%02x, 4st:%08x, 4end:%08x\n", + rptr->has_irq_pending, rptr->running, + rptr->event, 4*rptr->cur_acc, 4*rptr->cur_inc, + rptr->complete_dsamp - dsamp_start, + rptr->samps_left, rptr->vol, rptr->waveptr, + rptr->wavesize, 4*rptr->cur_start, + 4*rptr->cur_end); + } + pos++; + if(pos >= LEN_DOC_LOG) { + pos = 0; + } + } + + fprintf(docfile, "cur_dcycs: %f\n", g_sim65816.g_cur_dcycs); + fprintf(docfile, "dsamps_now: %f\n", + (g_sim65816.g_cur_dcycs * g_sound.g_dsamps_per_dcyc) - dsamp_start); + fprintf(docfile, "g_sound.g_doc_num_osc_en: %d\n", g_sound.g_doc_num_osc_en); + fclose(docfile); +} + +void +sound_init() +{ + Doc_reg *rptr; + int i; + + for(i = 0; i < 32; i++) { + rptr = &(g_sound.g_doc_regs[i]); + rptr->dsamp_ev = 0.0; + rptr->dsamp_ev2 = 0.0; + rptr->complete_dsamp = 0.0; + rptr->samps_left = 0; + rptr->cur_acc = 0; + rptr->cur_inc = 0; + rptr->cur_start = 0; + rptr->cur_end = 0; + rptr->cur_mask = 0; + rptr->size_bytes = 0; + rptr->event = 0; + rptr->running = 0; + rptr->has_irq_pending = 0; + rptr->freq = 0; + rptr->vol = 0; + rptr->waveptr = 0; + rptr->ctl = 1; + rptr->wavesize = 0; + rptr->last_samp_val = 0; + } + + // OG sound globals initialization + g_sound.g_num_c030_fsamps = 0; + g_sound.g_sound_shm_pos = 0; + g_sound.g_queued_samps = 0; + g_sound.g_queued_nonsamps = 0; + + g_sound.doc_sound_ctl = 0; + g_sound.doc_saved_val = 0; + g_sound.g_doc_num_osc_en = 1; + g_sound.g_dcycs_per_doc_update = 1.0; + g_sound.g_dupd_per_dcyc = 1.0; + g_sound.g_drecip_osc_en_plus_2 = 1.0 / (double)(1 + 2); + + g_sound.doc_reg_e0 = 0xff; + //g_sound.g_audio_rate = 0; + g_sound.g_daudio_rate = 0.0; + g_sound.g_drecip_audio_rate = 0.0; + g_sound.g_dsamps_per_dcyc = 0.0; + g_sound.g_dcycs_per_samp = 0.0; + g_sound.g_fsamps_per_dcyc = 0.0; + + g_sound.g_doc_vol = 2; + + g_sound.g_last_sound_play_dsamp = 0.0; + + sound_init_general(); +} + + +void +sound_init_general() +{ + + int size; + int ret; + + ret = 0; + + if(g_sound.g_audio_enable == 0) + { + set_audio_rate(g_sound.g_audio_rate); + // set_audio_rate(g_preferred_rate); + return; + } + + size = SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE; + g_sound_shm_addr = x_sound_allocate(size);; + + fflush(stdout); + + x_snd_init(g_sound_shm_addr); + + child_sound_loop(-1, -1, g_sound_shm_addr); + + +} + +void +parent_sound_get_sample_rate(int read_fd) +{ + word32 tmp; + int ret; + + ret = read(read_fd, (char*)&tmp, 4); + if(ret != 4) { + printf("parent dying, could not get sample rate from child\n"); + printf("ret: %d, fd: %d errno:%d\n", ret, read_fd, errno); + x_exit(1); + } + close(read_fd); + + set_audio_rate(tmp); +} + +void +set_audio_rate(int rate) +{ + printf("set audio rate : %d\n",rate); + g_sound.g_audio_rate = rate; + g_sound.g_daudio_rate = (rate)*1.0; + g_sound.g_drecip_audio_rate = 1.0/(rate); + g_sound.g_dsamps_per_dcyc = ((rate*1.0) / DCYCS_1_MHZ); + g_sound.g_dcycs_per_samp = (DCYCS_1_MHZ / (rate*1.0)); + g_sound.g_fsamps_per_dcyc = (float)((rate*1.0) / DCYCS_1_MHZ); +} + +void +sound_reset(double dcycs) +{ + double dsamps; + int i; + + dsamps = dcycs * g_sound.g_dsamps_per_dcyc; + for(i = 0; i < 32; i++) { + doc_write_ctl_reg(i, g_sound.g_doc_regs[i].ctl | 1, dsamps); + g_sound.doc_reg_e0 = 0xff; // OG : Don't understand???? + if(g_sound.g_doc_regs[i].has_irq_pending) { + halt_printf("reset: has_irq[%02x] = %d\n", i, + g_sound.g_doc_regs[i].has_irq_pending); + } + g_sound.g_doc_regs[i].has_irq_pending = 0; + } + if(g_sound.g_num_osc_interrupting) { + halt_printf("reset: num_osc_int:%d\n", g_sound.g_num_osc_interrupting); + } + g_sound.g_num_osc_interrupting = 0; + +// OG No reason to reset the number of active oscillo on reset : this should only be done on startup. + /* + g_sound.g_doc_num_osc_en = 1; + UPDATE_G_DCYCS_PER_DOC_UPDATE(1); + */ +} + + +void sound_shutdown() +{ + // OG stop sound and free memory on sound_shutdown + sound_reset(g_sim65816.g_cur_dcycs); + + x_snd_shutdown(); + + extern void x_sound_free(word32* mem); + x_sound_free(g_sound_shm_addr); + g_sound_shm_addr = NULL; + + +} + + + +void +sound_update(double dcycs) +{ + double dsamps; + /* Called every VBL time to update sound status */ + + /* "play" sounds for this vbl */ + + dsamps = dcycs * g_sound.g_dsamps_per_dcyc; + DOC_LOG("do_snd_pl", -1, dsamps, 0); + sound_play(dsamps); +} + + +void +open_sound_file() +{ + char name[256]; + int fd; + + sprintf(name, "snd.out.%d", g_sound_file_num); + + fd = open(name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0x1ff); + if(fd < 0) { + printf("open_sound_file open ret: %d, errno: %d\n", fd, errno); + x_exit(1); + } + + g_sound_file_fd = fd; + g_sound_file_num++; + g_send_file_bytes = 0; +} + +void +close_sound_file() +{ + if(g_sound_file_fd >= 0) { + close(g_sound_file_fd); + } + + g_sound_file_fd = -1; +} + +void +check_for_range(word32 *addr, int num_samps, int offset) +{ + short *shortptr; + int i; + int left; + int right; + int max; + + max = -32768; + + if(num_samps > SOUND_SHM_SAMP_SIZE) { + halt_printf("num_samps: %d > %d!\n", num_samps, + SOUND_SHM_SAMP_SIZE); + } + + for(i = 0; i < num_samps; i++) { + shortptr = (short *)&(addr[i]); + left = shortptr[0]; + right = shortptr[1]; + if((left > 0x3000) || (right > 0x3000)) { + halt_printf("Sample %d of %d at snd_buf: %p is: " + "%d/%d\n", i + offset, num_samps, + &addr[i], left, right); + return; + } + + max = MAX(max, left); + max = MAX(max, right); + } + + printf("check4 max: %d over %d\n", max, num_samps); +} + +void +send_sound_to_file(word32 *addr, int shm_pos, int num_samps) +{ + int size; + int ret; + + if(g_sound_file_fd < 0) { + open_sound_file(); + } + + size = 0; + if((num_samps + shm_pos) > SOUND_SHM_SAMP_SIZE) { + size = SOUND_SHM_SAMP_SIZE - shm_pos; + g_send_file_bytes += (size * 4); + + ret = write(g_sound_file_fd, &(addr[shm_pos]), 4*size); + if(ret != 4*size) { + halt_printf("wrote %d not %d\n", ret, 4*size); + } + + if(g_sound.g_doc_vol < 3) { + check_for_range(&(addr[shm_pos]), size, 0); + } else { + printf("Not checking %d bytes since vol: %d\n", + 4*size, g_sound.g_doc_vol); + } + shm_pos = 0; + num_samps -= size; + } + + g_send_file_bytes += (num_samps * 4); + + ret = write(g_sound_file_fd, &(addr[shm_pos]), 4*num_samps); + if(ret != 4*num_samps) { + halt_printf("wrote %d not %d\n", ret, 4*num_samps); + } + + if(g_sound.g_doc_vol < 3) { + check_for_range(&(addr[shm_pos]), num_samps, size); + } else { + printf("Not checking2 %d bytes since vol: %d\n", + 4*num_samps, g_sound.g_doc_vol); + } + +} + +void +send_sound(int real_samps, int size) +{ + word32 tmp; + int ret; + + if(g_sound.g_audio_enable == 0) { + printf("Entered send_sound but audio off!\n"); + x_exit(2); + } + + if(real_samps) { + tmp = size + 0xa2000000; + } else { + tmp = size + 0xa1000000; + } + DOC_LOG("send_sound", -1, g_sound.g_last_sound_play_dsamp, + (real_samps << 30) + size); + +#if !defined(DRIVER_LINUX) + ret = 0; + child_sound_playit(tmp); +#else + /* Although this looks like a big/little-endian issue, since the */ + /* child is also reading an int, it just works with no byte swap */ + ret = write(g_pipe_fd[1], &tmp, 4); + if(ret != 4) { + halt_printf("send_sound, wr ret: %d, errno: %d\n", ret, errno); + } +#endif +} + +void +show_c030_state() +{ + show_c030_samps(&(g_sound.g_samp_buf[0]), 100); +} + +void +show_c030_samps(int *outptr, int num) +{ + int i; + + printf("c030_fsamps[]: %d\n", g_sound.g_num_c030_fsamps); + + for(i = 0; i < g_sound.g_num_c030_fsamps+2; i++) { + printf("%3d: %5.3f\n", i, g_sound.c030_fsamps[i]); + } + + printf("Samples[] = %d\n", num); + + for(i = 0; i < num+2; i++) { + printf("%4d: %d %d\n", i, outptr[0], outptr[1]); + outptr += 2; + } +} + + +void +sound_play(double dsamps) +{ + register word32 start_time1, start_time2, start_time3, start_time4; + register word32 end_time1, end_time2, end_time3; + Doc_reg *rptr; + int *outptr; + int *outptr_start; + word32 *sndptr; + double complete_dsamp; + double cur_dsamp; + double last_dsamp; + double dsamp_now; + double dnum_samps; + int val, val2; + int new_val; + float ftmp; + int imul; + int off; + int num; + float fsampnum; + float next_fsampnum; + int c030_lo_val, c030_hi_val; + float fc030_range; + float fc030_base; + int sampnum; + int next_sampnum; + float fpercent; + int c030_state; + int val0, val1; + word32 cur_acc; + word32 cur_pos; + word32 cur_mask; + word32 cur_inc; + word32 cur_end; + int ctl; + int num_osc_en; + int samps_left; + int samps_to_do; + int samps_played; + int samp_offset; + int snd_buf_init; + int pos; + int num_running; + int num_samps; + int osc; + int done; + int i, j; + + + GET_ITIMER(start_time1); + + g_num_snd_plays++; + if(g_sound.g_sound_play_depth) { + halt_printf("Nested sound_play!\n"); + } + + g_sound.g_sound_play_depth++; + + /* calc sample num */ + + last_dsamp = g_sound.g_last_sound_play_dsamp; + num_samps = (int)(dsamps - g_sound.g_last_sound_play_dsamp); + dnum_samps = (double)num_samps; + + dsamp_now = last_dsamp + dnum_samps; + + if(num_samps < 1) { + /* just say no */ + g_sound.g_sound_play_depth--; + return; + } + + DOC_LOG("sound_play", -1, dsamp_now, num_samps); + + if(num_samps > MAX_SND_BUF) { + printf("num_samps: %d, too big!\n", num_samps); + g_sound.g_sound_play_depth--; + return; + } + + + GET_ITIMER(start_time4); + + outptr_start = &(g_sound.g_samp_buf[0]); + outptr = outptr_start; + + snd_buf_init = 0; + + samps_played = 0; + + num = g_sound.g_num_c030_fsamps; + + if(num || ((g_sim65816.g_vbl_count - g_sound.g_last_c030_vbl_count) < 240)) { + + if(num) { + g_sound.g_last_c030_vbl_count = g_sim65816.g_vbl_count; + } + + pos = 0; + outptr = outptr_start; + c030_state = g_sound.g_c030_state; + + c030_hi_val = ((VAL_C030_BASE + VAL_C030_RANGE)*g_sound.g_doc_vol) >> 4; + c030_lo_val = (VAL_C030_BASE * g_sound.g_doc_vol) >> 4; + + fc030_range = (float)(((VAL_C030_RANGE) * g_sound.g_doc_vol) >> 4); + fc030_base = (float)(((VAL_C030_BASE) * g_sound.g_doc_vol) >> 4); + + val = c030_lo_val; + if(c030_state) { + val = c030_hi_val; + } + + snd_buf_init++; + + g_sound.c030_fsamps[num] = (float)(num_samps); + g_sound.c030_fsamps[num+1] = (float)(num_samps+1); + + ftmp = (float)num_samps; + /* ensure that all samps are in range */ + for(i = num - 1; i >= 0; i--) { + if(g_sound.c030_fsamps[i] > ftmp) { + g_sound.c030_fsamps[i] = ftmp; + } + } + + num++; + fsampnum = g_sound.c030_fsamps[0]; + sampnum = (int)fsampnum; + fpercent = (float)0.0; + i = 0; + + while(i < num) { + next_fsampnum = g_sound.c030_fsamps[i+1]; + next_sampnum = (int)next_fsampnum; + if(sampnum < 0 || sampnum > num_samps) { + halt_printf("play c030: [%d]:%f is %d, > %d\n", + i, fsampnum, sampnum, num_samps); + break; + } + + /* write in samples to all samps < me */ + new_val = c030_lo_val; + if(c030_state) { + new_val = c030_hi_val; + } + for(j = pos; j < sampnum; j++) { + outptr[0] = new_val; + outptr[1] = new_val; + outptr += 2; + pos++; + } + + /* now, calculate me */ + fpercent = (float)0.0; + if(c030_state) { + fpercent = (fsampnum - (float)sampnum); + } + + c030_state = !c030_state; + + while(next_sampnum == sampnum) { + if(c030_state) { + fpercent += (next_fsampnum - fsampnum); + } + i++; + fsampnum = next_fsampnum; + + next_fsampnum = g_sound.c030_fsamps[i+1]; + next_sampnum = (int)next_fsampnum; + c030_state = !c030_state; + } + + if(c030_state) { + /* add in fractional time */ + ftmp = (float)(int)(fsampnum + 1.0f); //OG added cast + fpercent += (ftmp - fsampnum); + } + + if((fpercent < (float)0.0) || (fpercent > (float)1.0)) { + halt_printf("fpercent: %d = %f\n", i, fpercent); + show_c030_samps(outptr_start, num_samps); + break; + } + + val = (int)((fpercent * fc030_range) + fc030_base); + outptr[0] = val; + outptr[1] = val; + outptr += 2; + pos++; + i++; + + sampnum = next_sampnum; + fsampnum = next_fsampnum; + } + + samps_played += num_samps; + + /* since we pretended to get one extra sample, we will */ + /* have toggled the speaker one time too many. Fix it */ + g_sound.g_c030_state = !c030_state; + + if(g_send_sound_to_file) { + show_c030_samps(outptr_start, num_samps); + } + } + + g_sound.g_num_c030_fsamps = 0; + + GET_ITIMER(start_time2); + + num_running = 0; + + num_osc_en = g_sound.g_doc_num_osc_en; + + done = 0; + while(!done) { + done = 1; + for(j = 0; j < num_osc_en; j++) { + osc = j; + rptr = &(g_sound.g_doc_regs[osc]); + complete_dsamp = rptr->complete_dsamp; + samps_left = rptr->samps_left; + cur_acc = rptr->cur_acc; + cur_mask = rptr->cur_mask; + cur_inc = rptr->cur_inc; + cur_end = rptr->cur_end; + if(!rptr->running || cur_inc == 0 || + (complete_dsamp >= dsamp_now)) { + continue; + } + + done = 0; + ctl = rptr->ctl; + + samp_offset = 0; + if(complete_dsamp > last_dsamp) { + samp_offset = (int)(complete_dsamp- last_dsamp); + if(samp_offset > num_samps) { + rptr->complete_dsamp = dsamp_now; + continue; + } + } + outptr = outptr_start + 2 * samp_offset; + if(ctl & 0x10) { + /* other channel */ + outptr += 1; + } + + imul = (rptr->vol * g_sound.g_doc_vol); + off = imul * 128; + + samps_to_do = MIN(samps_left, num_samps - samp_offset); + if(imul == 0 || samps_to_do == 0) { + /* produce no sound */ + samps_left = samps_left - samps_to_do; + cur_acc += cur_inc * samps_to_do; + rptr->samps_left = samps_left; + rptr->cur_acc = cur_acc; + cur_dsamp = last_dsamp + + (double)(samps_to_do + samp_offset); + DOC_LOG("nosnd", osc, cur_dsamp, samps_to_do); + rptr->complete_dsamp = dsamp_now; + cur_pos = rptr->cur_start+(cur_acc & cur_mask); + if(samps_left <= 0) { + doc_sound_end(osc, 1, cur_dsamp, + dsamp_now); + val = 0; + j--; + } else { + val = g_sound.doc_ram[cur_pos >> SND_PTR_SHIFT]; + } + rptr->last_samp_val = val; + continue; + } + + if(snd_buf_init == 0) { + memset(outptr_start, 0, + 2*sizeof(outptr_start[0])*num_samps); + snd_buf_init++; + } + + val = 0; + rptr->complete_dsamp = dsamp_now; + cur_pos = rptr->cur_start + (cur_acc & cur_mask); + for(i = 0; i < samps_to_do; i++) { + pos = cur_pos >> SND_PTR_SHIFT; + cur_pos += cur_inc; + cur_acc += cur_inc; + val = g_sound.doc_ram[pos]; + + val2 = (val * imul - off) >> 4; + if((val == 0) || (cur_pos >= cur_end)) { + cur_dsamp = last_dsamp + + (double)(samp_offset + i + 1); + rptr->cur_acc = cur_acc; + rptr->samps_left = 0; + DOC_LOG("end or 0", osc, cur_dsamp, + (pos << 16) + ((i &0xff) << 8) + + val); + doc_sound_end(osc, val, cur_dsamp, + dsamp_now); + val = 0; + break; + } + + val2 = outptr[0] + val2; + + samps_left--; + *outptr = val2; + outptr += 2; + } + + rptr->last_samp_val = val; + + if(val != 0) { + rptr->cur_acc = cur_acc; + rptr->samps_left = samps_left; + rptr->complete_dsamp = dsamp_now; + } + + samps_played += samps_to_do; + DOC_LOG("splayed", osc, dsamp_now, + (samps_to_do << 16) + (pos & 0xffff)); + } + } + + GET_ITIMER(end_time2); + + g_cycs_in_sound2 += (end_time2 - start_time2); + + g_sound.g_last_sound_play_dsamp = dsamp_now; + + GET_ITIMER(start_time3); + + outptr = outptr_start; + + pos = g_sound.g_sound_shm_pos; + sndptr = g_sound_shm_addr; + +#if 0 + printf("samps_left: %d, num_samps: %d\n", samps_left, num_samps); +#endif + + if(g_sound.g_audio_enable != 0) { + + if(snd_buf_init) { + /* convert sound buf */ + + for(i = 0; i < num_samps; i++) { + val0 = outptr[0]; + val1 = outptr[1]; + val = val0; + if(val0 > 32767) { + val = 32767; + } + if(val0 < -32768) { + val = -32768; + } + + val0 = val; + val = val1; + if(val1 > 32767) { + val = 32767; + } + if(val1 < -32768) { + val = -32768; + } + + + outptr += 2; + +#if defined(__linux__) || defined(OSS) + /* Linux seems to expect little-endian */ + /* samples always, even on PowerPC */ +# ifdef KEGS_LITTLE_ENDIAN + sndptr[pos] = (val << 16) + (val0 & 0xffff); +# else + sndptr[pos] = ((val & 0xff) << 24) + + ((val & 0xff00) << 8) + + ((val0 & 0xff) << 8) + + ((val0 >> 8) & 0xff); +# endif +#else +# ifdef KEGS_LITTLE_ENDIAN + sndptr[pos] = (val << 16) + (val0 & 0xffff); +# else + sndptr[pos] = (val0 << 16) + (val & 0xffff); +# endif +#endif + pos++; + if(pos >= SOUND_SHM_SAMP_SIZE) { + pos = 0; + } + } + + if(g_sound.g_queued_nonsamps) { + /* force out old 0 samps */ + send_sound(0, g_sound.g_queued_nonsamps); + g_sound.g_queued_nonsamps = 0; + } + + if(g_send_sound_to_file) { + send_sound_to_file(g_sound_shm_addr, + g_sound.g_sound_shm_pos, num_samps); + } + + g_sound.g_queued_samps += num_samps; + } else { + /* move pos */ + pos += num_samps; + while(pos >= SOUND_SHM_SAMP_SIZE) { + pos -= SOUND_SHM_SAMP_SIZE; + } + + if(g_send_sound_to_file) { + send_sound_to_file(g_sound.zero_buf, g_sound.g_sound_shm_pos, + num_samps); + } + + if(g_sound.g_queued_samps) { + /* force out old non-0 samps */ + send_sound(1, g_sound.g_queued_samps); + g_sound.g_queued_samps = 0; + } + + g_sound.g_queued_nonsamps += num_samps; + } + + } + + g_sound.g_sound_shm_pos = pos; + + + GET_ITIMER(end_time3); + + g_fvoices += ((float)(samps_played) * (float)(g_sound.g_drecip_audio_rate)); + + if(g_sound.g_audio_enable != 0) { + if(g_sound.g_queued_samps >= (g_sound.g_audio_rate/32)) { + send_sound(1, g_sound.g_queued_samps); + g_sound.g_queued_samps = 0; + } + + if(g_sound.g_queued_nonsamps >= (g_sound.g_audio_rate/32)) { + send_sound(0, g_sound.g_queued_nonsamps); + g_sound.g_queued_nonsamps = 0; + } + } + + GET_ITIMER(end_time1); + + g_cycs_in_sound1 += (end_time1 - start_time1); + g_cycs_in_sound3 += (end_time3 - start_time3); + g_cycs_in_sound4 += (start_time2 - start_time4); + + g_sound.g_last_sound_play_dsamp = dsamp_now; + + g_sound.g_sound_play_depth--; +} + + +void +doc_handle_event(int osc, double dcycs) +{ + double dsamps; + + /* handle osc stopping and maybe interrupting */ + + g_num_doc_events++; + + dsamps = dcycs * g_sound.g_dsamps_per_dcyc; + + DOC_LOG("doc_ev", osc, dcycs, 0); + + g_sound.g_doc_regs[osc].event = 0; + + sound_play(dsamps); + +} + +void +doc_sound_end(int osc, int can_repeat, double eff_dsamps, double dsamps) +{ + Doc_reg *rptr, *orptr; + int mode, omode; + int other_osc; + int one_shot_stop; + int ctl; + + /* handle osc stopping and maybe interrupting */ + + if(osc < 0 || osc > 31) { + printf("doc_handle_event: osc: %d!\n", osc); + return; + } + + rptr = &(g_sound.g_doc_regs[osc]); + ctl = rptr->ctl; + + if(rptr->event) { + remove_event_doc(osc); + } + rptr->event = 0; + rptr->cur_acc = 0; /* reset internal accumulator*/ + + /* check to make sure osc is running */ + if(ctl & 0x01) { + /* Oscillator already stopped. */ + halt_printf("Osc %d interrupt, but it was already stop!\n",osc); +#ifdef HPUX + U_STACK_TRACE(); +#endif + return; + } + + if(ctl & 0x08) { + if(rptr->has_irq_pending == 0) { + add_sound_irq(osc); + } + } + + if(!rptr->running) { + halt_printf("Doc event for osc %d, but ! running\n", osc); + } + + rptr->running = 0; + + mode = (ctl >> 1) & 3; + other_osc = osc ^ 1; + orptr = &(g_sound.g_doc_regs[other_osc]); + omode = (orptr->ctl >> 1) & 3; + + /* If either this osc or it's partner is in swap mode, treat the */ + /* pair as being in swap mode. This Ensoniq feature pointed out */ + /* by Ian Schmidt */ + if(mode == 0 && can_repeat) { + /* free-running mode with no 0 byte! */ + /* start doing it again */ + + start_sound(osc, eff_dsamps, dsamps); + + return; + } else if((mode == 3) || (omode == 3)) { + /* swap mode (even if we're one_shot and partner is swap)! */ + /* unless we're one-shot and we hit a 0-byte--then */ + /* Olivier Goguel says just stop */ + rptr->ctl |= 1; + one_shot_stop = (mode == 1) && (!can_repeat); + if(!one_shot_stop && !orptr->running && + (orptr->ctl & 0x1)) { + orptr->ctl = orptr->ctl & (~1); + start_sound(other_osc, eff_dsamps, dsamps); + } + return; + } else { + /* stop the oscillator */ + rptr->ctl |= 1; + } + + return; +} + +void +add_sound_irq(int osc) +{ + int num_osc_interrupting; + + if(g_sound.g_doc_regs[osc].has_irq_pending) { + halt_printf("Adding sound_irq for %02x, but irq_p: %d\n", osc, + g_sound.g_doc_regs[osc].has_irq_pending); + } + + num_osc_interrupting = g_sound.g_num_osc_interrupting + 1; + g_sound.g_doc_regs[osc].has_irq_pending = num_osc_interrupting; + g_sound.g_num_osc_interrupting = num_osc_interrupting; + + add_irq(IRQ_PENDING_DOC); + if(num_osc_interrupting == 1) { + g_sound.doc_reg_e0 = 0x00 + (osc << 1); + } + + DOC_LOG("add_irq", osc, g_cur_dcycs * g_sound.g_dsamps_per_dcyc, 0); +} + +void +remove_sound_irq(int osc, int must) +{ + Doc_reg *rptr; + int num_osc_interrupt; + int has_irq_pending; + int first; + int i; + + doc_printf("remove irq for osc: %d, has_irq: %d\n", + osc, g_sound.g_doc_regs[osc].has_irq_pending); + + num_osc_interrupt = g_sound.g_doc_regs[osc].has_irq_pending; + first = 0; + if(num_osc_interrupt) { + g_sound.g_num_osc_interrupting--; + g_sound.g_doc_regs[osc].has_irq_pending = 0; + DOC_LOG("rem_irq", osc, g_cur_dcycs * g_sound.g_dsamps_per_dcyc, 0); + if(g_sound.g_num_osc_interrupting == 0) { + remove_irq(IRQ_PENDING_DOC); + } + + first = 0x40 | (g_sound.doc_reg_e0 >> 1); + /* if none found, then def = no ints */ + for(i = 0; i < g_sound.g_doc_num_osc_en; i++) { + rptr = &(g_sound.g_doc_regs[i]); + has_irq_pending = rptr->has_irq_pending; + if(has_irq_pending > num_osc_interrupt) { + has_irq_pending--; + rptr->has_irq_pending = has_irq_pending; + } + if(has_irq_pending == 1) { + first = i; + } + } + if(num_osc_interrupt == 1) { + g_sound.doc_reg_e0 = (first << 1); + } else { +#if 0 + halt_printf("remove_sound_irq[%02x]=%d, first:%d\n", + osc, num_osc_interrupt, first); +#endif + } + } else { +#if 0 + /* make sure no int pending */ + if(g_sound.doc_reg_e0 != 0xff) { + halt_printf("remove_sound_irq[%02x]=0, but e0: %02x\n", + osc, g_sound.doc_reg_e0); + } +#endif + if(must) { + halt_printf("REMOVE_sound_irq[%02x]=0, but e0: %02x\n", + osc, g_sound.doc_reg_e0); + } + } + + if(g_sound.doc_reg_e0 & 0x80) { + for(i = 0; i < 0x20; i++) { + has_irq_pending = g_sound.g_doc_regs[i].has_irq_pending; + if(has_irq_pending) { + halt_printf("remove_sound_irq[%02x], but " + "[%02x]=%d!\n", osc,i,has_irq_pending); + printf("num_osc_int: %d, first: %02x\n", + num_osc_interrupt, first); + } + } + } +} + +void +start_sound(int osc, double eff_dsamps, double dsamps) +{ + register word32 start_time1; + register word32 end_time1; + Doc_reg *rptr; + int ctl; + int mode; + word32 sz; + word32 size; + word32 wave_size; + + if(osc < 0 || osc > 31) { + halt_printf("start_sound: osc: %02x!\n", osc); + } + + g_num_start_sounds++; + + rptr = &(g_sound.g_doc_regs[osc]); + + if(osc >= g_sound.g_doc_num_osc_en) { + rptr->ctl |= 1; + return; + } + + GET_ITIMER(start_time1); + + ctl = rptr->ctl; + + mode = (ctl >> 1) & 3; + + wave_size = rptr->wavesize; + + sz = ((wave_size >> 3) & 7) + 8; + size = 1 << sz; + + if(size < 0x100) { + halt_printf("size: %08x is too small, sz: %08x!\n", size, sz); + } + + if(rptr->running) { + halt_printf("start_sound osc: %d, already running!\n", osc); + } + + rptr->running = 1; + + rptr->complete_dsamp = eff_dsamps; + + doc_printf("Starting osc %02x, dsamp: %f\n", osc, dsamps); + doc_printf("size: %04x\n", size); + + if((mode == 2) && ((osc & 1) == 0)) { + printf("Sync mode osc %d starting!\n", osc); + /* set_halt(1); */ + + /* see if we should start our odd partner */ + if((rptr[1].ctl & 7) == 5) { + /* odd partner stopped in sync mode--start him */ + rptr[1].ctl &= (~1); + start_sound(osc + 1, eff_dsamps, dsamps); + } else { + printf("Osc %d starting sync, but osc %d ctl: %02x\n", + osc, osc+1, rptr[1].ctl); + } + } + + wave_end_estimate(osc, eff_dsamps, dsamps); + + DOC_LOG("st playing", osc, eff_dsamps, size); +#if 0 + if(rptr->cur_acc != 0) { + halt_printf("Start osc %02x, acc: %08x\n", osc, rptr->cur_acc); + } +#endif + + GET_ITIMER(end_time1); + + g_cycs_in_start_sound += (end_time1 - start_time1); +} + +void +wave_end_estimate(int osc, double eff_dsamps, double dsamps) +{ + register word32 start_time1; + register word32 end_time1; + Doc_reg *rptr; + byte *ptr1; + double event_dsamp; + double event_dcycs; + double dcycs_per_samp; + double dsamps_per_byte; + double num_dsamps; + double dcur_inc; + word32 tmp1; + word32 cur_inc; + word32 save_val; + int save_size; + int pos; + int size; + int estimate; + + GET_ITIMER(start_time1); + + dcycs_per_samp = g_sound.g_dcycs_per_samp; + + rptr = &(g_sound.g_doc_regs[osc]); + + cur_inc = rptr->cur_inc; + dcur_inc = (double)cur_inc; + dsamps_per_byte = 0.0; + if(cur_inc) { + dsamps_per_byte = SND_PTR_SHIFT_DBL / (double)dcur_inc; + } + + /* see if there's a zero byte */ + tmp1 = rptr->cur_start + (rptr->cur_acc & rptr->cur_mask); + pos = tmp1 >> SND_PTR_SHIFT; + size = ((rptr->cur_end) >> SND_PTR_SHIFT) - pos; + + ptr1 = &g_sound.doc_ram[pos]; + + estimate = 0; + if(rptr->ctl & 0x08 || g_sound.g_doc_regs[osc ^ 1].ctl & 0x08) { + estimate = 1; + } + +#if 0 + estimate = 1; +#endif + if(estimate) { + save_size = size; + save_val = ptr1[size]; + ptr1[size] = 0; + size = strlen((char *)ptr1); + ptr1[save_size] = save_val; + } + + /* calc samples to play */ + num_dsamps = (dsamps_per_byte * (double)size) + 1.0; + + rptr->samps_left = (int)num_dsamps; + + if(rptr->event) { + remove_event_doc(osc); + } + rptr->event = 0; + + event_dsamp = eff_dsamps + num_dsamps; + if(estimate) { + rptr->event = 1; + rptr->dsamp_ev = event_dsamp; + rptr->dsamp_ev2 = dsamps; + event_dcycs = (event_dsamp * dcycs_per_samp) + 1.0; + add_event_doc(event_dcycs, osc); + } + + GET_ITIMER(end_time1); + + g_cycs_in_est_sound += (end_time1 - start_time1); +} + + +void +remove_sound_event(int osc) +{ + if(g_sound.g_doc_regs[osc].event) { + g_sound.g_doc_regs[osc].event = 0; + remove_event_doc(osc); + } +} + + +void +doc_write_ctl_reg(int osc, int val, double dsamps) +{ + Doc_reg *rptr; + double eff_dsamps; + word32 old_halt; + word32 new_halt; + int old_val; + int mode; + + if(osc < 0 || osc >= 0x20) { + halt_printf("doc_write_ctl_reg: osc: %02x, val: %02x\n", + osc, val); + return; + } + + eff_dsamps = dsamps; + rptr = &(g_sound.g_doc_regs[osc]); + old_val = rptr->ctl; + g_sound.g_doc_saved_ctl = old_val; + + if(old_val == val) { + return; + } + + DOC_LOG("ctl_reg", osc, dsamps, (old_val << 16) + val); + + mode = (val >> 1) & 3; + + old_halt = (old_val & 1); + new_halt = (val & 1); + + /* bits are: 28: old int bit */ + /* 29: old halt bit */ + /* 30: new int bit */ + /* 31: new halt bit */ + +#if 0 + if(osc == 0x10) { + printf("osc %d new_ctl: %02x, old: %02x\n", osc, val, old_val); + } +#endif + + /* no matter what, remove any pending IRQs on this osc */ + remove_sound_irq(osc, 0); + +#if 0 + if(old_halt) { + printf("doc_write_ctl to osc %d, val: %02x, old: %02x\n", + osc, val, old_val); + } +#endif + + if(new_halt != 0) { + /* make sure sound is stopped */ + remove_sound_event(osc); + if(old_halt == 0) { + /* it was playing, finish it up */ +#if 0 + halt_printf("Aborted osc %d at eff_dsamps: %f, ctl: " + "%02x, oldctl: %02x\n", osc, eff_dsamps, + val, old_val); +#endif + sound_play(eff_dsamps); + } + if(((old_val >> 1) & 3) > 0) { + /* don't clear acc if free-running */ + g_sound.g_doc_regs[osc].cur_acc = 0; + } + + g_sound.g_doc_regs[osc].ctl = val; + g_sound.g_doc_regs[osc].running = 0; + } else { + /* new halt == 0 = make sure sound is running */ + if(old_halt != 0) { + /* start sound */ + DOC_LOG("ctl_sound_play", osc, eff_dsamps, val); + + // OG If the sound_play is executed, it may restart a oscillo we thought was stopped at time, + // hence crashing the start_sound function (cf. game Arrgh!) + //sound_play(eff_dsamps); + g_sound.g_doc_regs[osc].ctl = val; + + start_sound(osc, eff_dsamps, dsamps); + } else { + /* was running, and something changed */ + doc_printf("osc %d old ctl:%02x new:%02x!\n", + osc, old_val, val); +#if 0 + sound_play(eff_dsamps); +/* HACK: fix this??? */ +#endif + g_sound.g_doc_regs[osc].ctl = val; + if((old_val ^ val) & val & 0x8) { + /* now has ints on */ + wave_end_estimate(osc, dsamps, dsamps); + } + } + } +} + +void +doc_recalc_sound_parms(int osc, double eff_dcycs, double dsamps) +{ + Doc_reg *rptr; + double dfreq; + double dtmp1; + double dacc, dacc_recip; + word32 res; + word32 sz; + word32 size; + word32 wave_size; + word32 cur_start; + word32 shifted_size; + + g_num_recalc_snd_parms++; + + rptr = &(g_sound.g_doc_regs[osc]); + + wave_size = rptr->wavesize; + + dfreq = (double)rptr->freq; + + sz = ((wave_size >> 3) & 7) + 8; + size = 1 << sz; + rptr->size_bytes = size; + res = wave_size & 7; + + shifted_size = size << SND_PTR_SHIFT; + + cur_start = (rptr->waveptr << (8 + SND_PTR_SHIFT)) & (-(int)shifted_size); // OG + + dtmp1 = dfreq * (DOC_SCAN_RATE * g_sound.g_drecip_audio_rate); + dacc = (double)(1 << (20 - (17 - sz + res))); + dacc_recip = (SND_PTR_SHIFT_DBL) / ((double)(1 << 20)); + dtmp1 = dtmp1 * g_sound.g_drecip_osc_en_plus_2 * dacc * dacc_recip; + + rptr->cur_inc = (int)(dtmp1); + rptr->cur_start = cur_start; + rptr->cur_end = cur_start + shifted_size; + rptr->cur_mask = (shifted_size - 1); + + DOC_LOG("recalc", osc, dsamps, (rptr->waveptr << 16) + wave_size); +} + +int +doc_read_c030(double dcycs) +{ + int num; + + num = g_sound.g_num_c030_fsamps; + if(num >= MAX_C030_TIMES) { + halt_printf("Too many clicks per vbl: %d\n", num); + return 0; + } + + g_sound.c030_fsamps[num] = (float)(dcycs * g_sound.g_dsamps_per_dcyc - g_sound.g_last_sound_play_dsamp); + g_sound.g_num_c030_fsamps = num + 1; + + doc_printf("read c030, num this vbl: %04x\n", num); + + return 0; +} + +int +doc_read_c03c(double dcycs) +{ + return g_sound.doc_sound_ctl; +} + +int +doc_read_c03d(double dcycs) +{ + double dsamps; + Doc_reg *rptr; + int osc; + int type; + int ret; + + ret = g_sound.doc_saved_val; + dsamps = dcycs * g_sound.g_dsamps_per_dcyc; + + if(g_sound.doc_sound_ctl & 0x40) { + /* Read RAM */ + g_sound.doc_saved_val = g_sound.doc_ram[g_moremem.g_c03ef_doc_ptr]; + } else { + /* Read DOC */ + g_sound.doc_saved_val = 0; + + osc = g_moremem.g_c03ef_doc_ptr & 0x1f; + type = (g_moremem.g_c03ef_doc_ptr >> 5) & 0x7; + rptr = &(g_sound.g_doc_regs[osc]); + + switch(type) { + case 0x0: /* freq lo */ + g_sound.doc_saved_val = rptr->freq & 0xff; + break; + case 0x1: /* freq hi */ + g_sound.doc_saved_val = rptr->freq >> 8; + break; + case 0x2: /* vol */ + g_sound.doc_saved_val = rptr->vol; + break; + case 0x3: /* data register */ + /* HACK: make this call sound_play sometimes */ + g_sound.doc_saved_val = rptr->last_samp_val; + break; + case 0x4: /* wave ptr register */ + g_sound.doc_saved_val = rptr->waveptr; + break; + case 0x5: /* control register */ + g_sound.doc_saved_val = rptr->ctl; + break; + case 0x6: /* control register */ + g_sound.doc_saved_val = rptr->wavesize; + break; + case 0x7: /* 0xe0-0xff */ + switch(osc) { + case 0x00: /* 0xe0 */ + g_sound.doc_saved_val = g_sound.doc_reg_e0; + doc_printf("Reading doc 0xe0, ret: %02x\n", + g_sound.doc_saved_val); + + /* Clear IRQ on read of e0, if any irq pend */ + if((g_sound.doc_reg_e0 & 0x80) == 0) { + remove_sound_irq(g_sound.doc_reg_e0 >> 1, 1); + } + break; + case 0x01: /* 0xe1 */ + g_sound.doc_saved_val = (g_sound.g_doc_num_osc_en - 1) << 1; + break; + case 0x02: /* 0xe2 */ + g_sound.doc_saved_val = 0x80; +#if 0 + halt_printf("Reading doc 0xe2, ret: %02x\n", + g_sound.doc_saved_val); +#endif + break; + default: + g_sound.doc_saved_val = 0; + halt_printf("Reading bad doc_reg[%04x]: %02x\n", + g_moremem.g_c03ef_doc_ptr, g_sound.doc_saved_val); + } + break; + default: + g_sound.doc_saved_val = 0; + halt_printf("Reading bad doc_reg[%04x]: %02x\n", + g_moremem.g_c03ef_doc_ptr, g_sound.doc_saved_val); + } + } + + doc_printf("read c03d, doc_ptr: %04x, ret: %02x, saved: %02x\n", + g_moremem.g_c03ef_doc_ptr, ret, g_sound.doc_saved_val); + + DOC_LOG("read c03d", -1, dsamps, (g_moremem.g_c03ef_doc_ptr << 16) + + (g_sound.doc_saved_val << 8) + ret); + + if(g_sound.doc_sound_ctl & 0x20) { + g_moremem.g_c03ef_doc_ptr = (g_moremem.g_c03ef_doc_ptr + 1) & 0xffff; + } + + + return ret; +} + +void +doc_write_c03c(int val, double dcycs) +{ + int vol; + + vol = val & 0xf; + if(g_sound.g_doc_vol != vol) { + /* don't bother playing sound..wait till next update */ + /* sound_play(dcycs); */ + + g_sound.g_doc_vol = vol; + doc_printf("Setting doc vol to 0x%x at %f\n", + vol, dcycs); + } + DOC_LOG("c03c write", -1, dcycs * g_sound.g_dsamps_per_dcyc, val); + + g_sound.doc_sound_ctl = val; +} + +void +doc_write_c03d(int val, double dcycs) +{ + double dsamps; + double eff_dsamps; + Doc_reg *rptr; + int osc; + int type; + int ctl; + int tmp; + int i; + + val = val & 0xff; + + dsamps = dcycs * g_sound.g_dsamps_per_dcyc; + eff_dsamps = dsamps; + doc_printf("write c03d, doc_ptr: %04x, val: %02x\n", + g_moremem.g_c03ef_doc_ptr, val); + + DOC_LOG("write c03d", -1, dsamps, (g_moremem.g_c03ef_doc_ptr << 16) + val); + + if(g_sound.doc_sound_ctl & 0x40) { + /* RAM */ + g_sound.doc_ram[g_moremem.g_c03ef_doc_ptr] = val; + } else { + /* DOC */ + osc = g_moremem.g_c03ef_doc_ptr & 0x1f; + type = (g_moremem.g_c03ef_doc_ptr >> 5) & 0x7; + + rptr = &(g_sound.g_doc_regs[osc]); + ctl = rptr->ctl; +#if 0 + if((ctl & 1) == 0) { + if(type < 2 || type == 4 || type == 6) { + halt_printf("Osc %d is running, old ctl: %02x, " + "but write reg %02x=%02x\n", + osc, ctl, g_moremem.g_c03ef_doc_ptr & 0xff, val); + } + } +#endif + + switch(type) { + case 0x0: /* freq lo */ + if((rptr->freq & 0xff) == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("flo_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->freq = (rptr->freq & 0xff00) + val; + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x1: /* freq hi */ + if((rptr->freq >> 8) == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("fhi_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->freq = (rptr->freq & 0xff) + (val << 8); + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x2: /* vol */ + if(rptr->vol == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("vol_sound_play", osc, dsamps, val); + sound_play(dsamps); +#if 0 + halt_printf("vol_sound_play at %.1f osc:%d " + "val:%d\n", dsamps, osc, val); +#endif + } + rptr->vol = val; + break; + case 0x3: /* data register */ +#if 0 + printf("Writing %02x into doc_data_reg[%02x]!\n", + val, osc); +#endif + break; + case 0x4: /* wave ptr register */ + if(rptr->waveptr == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("wptr_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->waveptr = val; + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x5: /* control register */ +#if 0 + printf("doc_write ctl osc %d, val: %02x\n", osc, val); +#endif + if(rptr->ctl == (word32)val) { + break; + } + doc_write_ctl_reg(osc, val, dsamps); + break; + case 0x6: /* wavesize register */ + if(rptr->wavesize == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("wsz_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->wavesize = val; + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x7: /* 0xe0-0xff */ + switch(osc) { + case 0x00: /* 0xe0 */ + doc_printf("writing doc 0xe0 with %02x, " + "was:%02x\n", val, g_sound.doc_reg_e0); +#if 0 + if(val != g_sound.doc_reg_e0) { + halt_printf("writing doc 0xe0 with " + "%02x, was:%02x\n", val, + doc_reg_e0); + } +#endif + break; + case 0x01: /* 0xe1 */ + doc_printf("Writing doc 0xe1 with %02x\n", val); + tmp = val & 0x3e; + tmp = (tmp >> 1) + 1; + if(tmp < 1) { + tmp = 1; + } + if(tmp > 32) { + halt_printf("doc 0xe1: %02x!\n", val); + tmp = 32; + } + g_sound.g_doc_num_osc_en = tmp; + UPDATE_G_DCYCS_PER_DOC_UPDATE(tmp); + + // OG Update any oscs that were running to take care of the new numbers of oscillo + for(i = 0; ictl, rptr->waveptr, rptr->wavesize, rptr->freq, + rptr->vol, rptr->event, rptr->running, + rptr->has_irq_pending, rptr->size_bytes); + printf(" acc:%08x inc:%08x st:%08x end:%08x m:%08x\n", + rptr->cur_acc, rptr->cur_inc, rptr->cur_start, + rptr->cur_end, rptr->cur_mask); + printf(" compl_ds:%f samps_left:%d ev:%f ev2:%f\n", + rptr->complete_dsamp, rptr->samps_left, + rptr->dsamp_ev, rptr->dsamp_ev2); + } + +#if 0 + for(osc = 0; osc < 32; osc++) { + fmax = 0.0; + printf("osc %d has %d samps\n", osc, g_fsamp_num[osc]); + for(i = 0; i < g_fsamp_num[osc]; i++) { + printf("%4d: %f\n", i, g_fsamps[osc][i]); + fmax = MAX(fmax, g_fsamps[osc][i]); + } + printf("osc %d, fmax: %f\n", osc, fmax); + } +#endif +} + + + +extern void x_play_sound(enum_sound _hSound); +void play_sound(enum_sound _hSound) +{ + if ( (_hSound == SOUND_EJECTION) && (g_driver.x_notify_eject !=NULL) ) + g_driver.x_notify_eject(); + + x_play_sound(_hSound); + +} + diff --git a/kegs/Src/sound.h b/kegs/Src/sound.h new file mode 100644 index 0000000..376cfc8 --- /dev/null +++ b/kegs/Src/sound.h @@ -0,0 +1,210 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#ifdef INCLUDE_RCSID_C +const char rcsid_sound_h[] = "@(#)$KmKId: sound.h,v 1.17 2003-11-21 15:15:57-05 kentd Exp $"; +#endif + +#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(DRIVER_ANDROID) +# include +# include +#endif + +#define SOUND_SHM_SAMP_SIZE (32*1024) + +#define SAMPLE_SIZE 2 +#define NUM_CHANNELS 2 +#define SAMPLE_CHAN_SIZE (SAMPLE_SIZE * NUM_CHANNELS) + +#define MAX_SND_BUF 65536 +#define VAL_C030_RANGE (32768) +#define VAL_C030_BASE (-16384) + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +STRUCT(Doc_reg) { + _ALIGNED(8) double dsamp_ev; + _ALIGNED(8) double dsamp_ev2; + _ALIGNED(8) double complete_dsamp; + int samps_left; + word32 cur_acc; + word32 cur_inc; + word32 cur_start; + word32 cur_end; + word32 cur_mask; + int size_bytes; + int event; + int running; + int has_irq_pending; + word32 freq; + word32 vol; + word32 waveptr; + word32 ctl; + word32 wavesize; + word32 last_samp_val; + + +} XCODE_PRAGMA_PACK; + +/* prototypes for hardware specific snd_driver.c functions */ +void x_snd_init(word32 *); +void x_snd_shutdown(); +void x_snd_child_init(); +int x_snd_send_audio(byte *ptr, int size); +word32* x_sound_allocate(int size); + +#define MAX_C030_TIMES 18000 + +class s_sound : public serialized +{ +public: + + byte doc_ram[0x10000 + 16]; + + word32 doc_sound_ctl ; + word32 doc_saved_val ; + int g_doc_num_osc_en ; + _ALIGNED(8) double g_dcycs_per_doc_update ; + _ALIGNED(8) double g_dupd_per_dcyc ; + _ALIGNED(8) double g_drecip_osc_en_plus_2 ; + + int g_doc_saved_ctl ; + int g_queued_samps ; + int g_queued_nonsamps ; + int g_num_osc_interrupting ; + + int g_audio_enable; + + Doc_reg g_doc_regs[32]; + + word32 doc_reg_e0 ; + + int g_audio_rate ; // OG Preferred Audio Rate + _ALIGNED(8) double g_daudio_rate ; + _ALIGNED(8) double g_drecip_audio_rate ; + _ALIGNED(8) double g_dsamps_per_dcyc ; + _ALIGNED(8) double g_dcycs_per_samp ; + float g_fsamps_per_dcyc ; + + int g_doc_vol ; + + _ALIGNED(8) double g_last_sound_play_dsamp ; + + float c030_fsamps[MAX_C030_TIMES + 1]; + int g_num_c030_fsamps ; + + int g_sound_shm_pos ; + + int g_samp_buf[2*MAX_SND_BUF]; + word32 zero_buf[SOUND_SHM_SAMP_SIZE]; + + _ALIGNED(8) double g_doc_dsamps_extra ; + + word32 g_last_c030_vbl_count; + int g_c030_state ; + + // TO CHECK! + int g_sound_play_depth ; + + + // sound_driver.c + + int g_bytes_written ; + + #define ZERO_BUF_SIZE 2048 + + word32 g_snd_zero_buf[ZERO_BUF_SIZE]; + + int g_zeroes_buffered ; + int g_zeroes_seen ; + int g_sound_paused ; + int g_childsnd_vbl ; + int g_childsnd_pos ; + + + s_sound() + { + + INIT_SERIALIZED(); + + g_doc_num_osc_en = 1; + g_dcycs_per_doc_update = 1.0; + g_dupd_per_dcyc = 1.0; + g_drecip_osc_en_plus_2 = 1.0 / (double)(1 + 2); + + g_audio_enable = -1; + + doc_reg_e0 = 0xff; + + g_audio_rate = 44100; // OG Preferred Audio Rate + g_doc_vol = 2; + } + + DEFAULT_SERIALIZE_IN_OUT ; + +} XCODE_PRAGMA_PACK; + + +#ifdef _WIN32 +#pragma pack(pop) +#endif + + +extern s_sound g_sound; +extern void x_async_sound_init(); +extern void x_async_snd_shutdown(); +extern void x_preload_sounds(); + +// WAV SUPPORT + + +struct OASound +{ + + int m_BufferId; + int m_SourceId; + int frequency; + int depth; + int nbchannel; + int successfullyLoaded; +}; + + +typedef struct +{ + const char* filename; + // unsigned int ref; + OASound sound; +} system_sound; + +extern system_sound g_system_sounds[]; + +typedef enum +{ + SOUND_EJECTION=0, + SOUND_SPIN_UP_SEARCH_1, + SOUND_SPIN_UP_SEARCH_2, + SOUND_SKIP_SEARCH_1, + SOUND_SKIP_SEARCH_2, + SOUND_SKIP_SEARCH_3, + SOUND_SKIP_SEARCH_4, + SOUND_SKIP_SEARCH_5, + SOUND_NB +} enum_sound; + +void play_sound(enum_sound hSound); + + + +bool x_load_wav(const char* _Path, unsigned char** _outDataBuffer, unsigned int & _outFileSize, OASound & _sound); +OASound async_init_wav(const char* _file); +int async_release_wav(OASound* _pSound); +int async_stop_wav(OASound* _pSound); +int async_play_wav(OASound* _pSound, int _Loop, float _Attenuation, float _StartAt ); diff --git a/kegs/Src/sound_driver.cpp b/kegs/Src/sound_driver.cpp new file mode 100644 index 0000000..b5e3465 --- /dev/null +++ b/kegs/Src/sound_driver.cpp @@ -0,0 +1,192 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "defc.h" +#include "sound.h" + +#ifndef UNDER_CE +#include +#endif + +extern int Verbose; + +#define ZERO_PAUSE_SAFETY_SAMPS (g_sound.g_audio_rate >> 5) +#define ZERO_PAUSE_NUM_SAMPS (4*g_sound.g_audio_rate) + + + +/* +int g_bytes_written = 0; + +#define ZERO_BUF_SIZE 2048 + +word32 g_snd_zero_buf[ZERO_BUF_SIZE]; + +#define ZERO_PAUSE_SAFETY_SAMPS (g_sound.g_audio_rate >> 5) +#define ZERO_PAUSE_NUM_SAMPS (4*g_sound.g_audio_rate) + +int g_zeroes_buffered = 0; +int g_zeroes_seen = 0; +int g_sound_paused = 0; +int g_childsnd_vbl = 0; +int g_childsnd_pos = 0; + + +*/ + +word32 *g_childsnd_shm_addr = 0; + + +void +reliable_buf_write(word32 *shm_addr, int pos, int size) +{ + byte *ptr; + int ret; + + if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE || + size > SOUND_SHM_SAMP_SIZE || + (pos + size) > SOUND_SHM_SAMP_SIZE) { + printf("reliable_buf_write: pos: %04x, size: %04x\n", + pos, size); + x_exit(1); + } + + ptr = (byte *)&(shm_addr[pos]); + size = size * 4; + + while(size > 0) + { + + ret = x_snd_send_audio(ptr, size); + + if(ret < 0) { + printf("audio write, errno: %d\n", errno); + x_exit(1); + } + size = size - ret; + ptr += ret; + g_sound.g_bytes_written += ret; + } + +} + +void +reliable_zero_write(int amt) +{ + int len; + + while(amt > 0) { + len = MIN(amt, ZERO_BUF_SIZE); + reliable_buf_write(g_sound.g_snd_zero_buf, 0, len); + amt -= len; + } +} + + +void +child_sound_loop(int read_fd, int write_fd, word32 *shm_addr) +{ + + + doc_printf("Child pipe fd: %d\n", read_fd); + +// g_audio_rate = g_preferred_rate; + + g_sound.g_zeroes_buffered = 0; + g_sound.g_zeroes_seen = 0; + g_sound.g_sound_paused = 0; + + g_sound.g_childsnd_pos = 0; + g_sound.g_childsnd_vbl = 0; + g_childsnd_shm_addr = shm_addr; + + x_snd_child_init(); + +} + +void +child_sound_playit(word32 tmp) +{ + int size; + + size = tmp & 0xffffff; + + //printf("child_sound_playit: %08x\n", tmp); + + if((tmp >> 24) == 0xa2) { + /* play sound here */ + + +#if 0 + g_childsnd_pos += g_zeroes_buffered; + while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) { + g_childsnd_pos -= SOUND_SHM_SAMP_SIZE; + } +#endif + + if(g_sound.g_zeroes_buffered) { + reliable_zero_write(g_sound.g_zeroes_buffered); + } + + g_sound.g_zeroes_buffered = 0; + g_sound.g_zeroes_seen = 0; + + if((size + g_sound.g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) { + reliable_buf_write(g_childsnd_shm_addr, g_sound.g_childsnd_pos, + SOUND_SHM_SAMP_SIZE - g_sound.g_childsnd_pos); + size = (g_sound.g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE; + g_sound.g_childsnd_pos = 0; + } + + reliable_buf_write(g_childsnd_shm_addr, g_sound.g_childsnd_pos, size); + + if(g_sound.g_sound_paused) { + printf("Unpausing sound, zb: %d\n", g_sound.g_zeroes_buffered); + g_sound.g_sound_paused = 0; + } + + } else if((tmp >> 24) == 0xa1) { + if(g_sound.g_sound_paused) { + if(g_sound.g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) { + g_sound.g_zeroes_buffered += size; + } + } else { + /* not paused, send it through */ + g_sound.g_zeroes_seen += size; + + reliable_zero_write(size); + + if(g_sound.g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) { + printf("Pausing sound\n"); + g_sound.g_sound_paused = 1; + } + } + } else { + printf("tmp received bad: %08x\n", tmp); + x_exit(3); + } + + g_sound.g_childsnd_pos += size; + while(g_sound.g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) { + g_sound.g_childsnd_pos -= SOUND_SHM_SAMP_SIZE; + } + + g_sound.g_childsnd_vbl++; + if(g_sound.g_childsnd_vbl >= 60) { + g_sound.g_childsnd_vbl = 0; +#if 0 + printf("sound bytes written: %06x\n", g_bytes_written); + printf("Sample samples[0]: %08x %08x %08x %08x\n", + g_childsnd_shm_addr[0], g_childsnd_shm_addr[1], + g_childsnd_shm_addr[2], g_childsnd_shm_addr[3]); + printf("Sample samples[100]: %08x %08x %08x %08x\n", + g_childsnd_shm_addr[100], g_childsnd_shm_addr[101], + g_childsnd_shm_addr[102], g_childsnd_shm_addr[103]); +#endif + g_sound.g_bytes_written = 0; + } +} + diff --git a/kegs/Src/superhires.h b/kegs/Src/superhires.h new file mode 100644 index 0000000..1477ea6 --- /dev/null +++ b/kegs/Src/superhires.h @@ -0,0 +1,231 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#ifndef SUPERHIRES_INCLUDED +const char rcsid_superhires_h[] = "@(#)$KmKId: superhires.h,v 1.9 2003-10-29 02:02:59-05 kentd Exp $"; +# define SUPERHIRES_INCLUDED +#endif + +void +SUPER_TYPE(byte *screen_data, int pixels_per_line, int y, int scan, + word32 ch_mask, int use_a2vid_palette, int mode_640) +{ + word32 *palptr; + word32 mem_ptr; + byte val0; + int x1, x2; + byte *b_ptr; + word32 *img_ptr; + word32 tmp, tmp2; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; +#endif + word32 ch_tmp; + byte *slow_mem_ptr; + int shift_per; + word32 pal; + word32 pal_word; + word32 pix0, pix1, pix2, pix3; + word32 save_pix; + int offset, next_line_offset; + int dopr; + + mem_ptr = 0xa0 * y + 0x12000; + tmp2 = 0; + tmp = 0; + + shift_per = (1 << SHIFT_PER_CHANGE); + if(use_a2vid_palette) { + pal = (g_video.g_a2vid_palette & 0xf); + } else { + pal = (scan & 0xf); + } + + if(SUPER_FILL) { + ch_mask = -1; + save_pix = 0; + } + + if(use_a2vid_palette) { + palptr = &(g_video.g_a2vid_palette_remap[0]); + } else { + palptr = &(g_palette_8to1624[pal * 16]); + } + + dopr = 0; +#if 0 + if(y == 1) { + dopr = 1; + printf("superhires line %d has ch_mask: %08x\n", y, ch_mask); + } +#endif + for(x1 = 0; x1 < 0xa0; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + pal_word = (pal << 28) + (pal << 20) + (pal << 12) + + (pal << 4); + + if(mode_640 && !use_a2vid_palette) { +#ifdef KEGS_LITTLE_ENDIAN + pal_word += 0x04000c08; +#else + pal_word += 0x080c0004; +#endif + } + + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + offset = y*VIDEO_VFACTOR*pixels_per_line + x1*2*VIDEO_HFACTOR; + next_line_offset = pixels_per_line; +#if SUPER_PIXEL_SIZE == 16 + offset *= 2; + next_line_offset *= 2; +#elif SUPER_PIXEL_SIZE == 32 + offset *= 4; + next_line_offset *= 4; +#endif + b_ptr = &screen_data[offset]; + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + next_line_offset); +#endif + if(mode_640) { + for(x2 = 0; x2 < shift_per; x2++) { + val0 = *slow_mem_ptr++; + + pix0 = (val0 >> 6) & 0x3; + pix1 = (val0 >> 4) & 0x3; + pix2 = (val0 >> 2) & 0x3; + pix3 = val0 & 0x3; + if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){ + pix0 = palptr[pix0+8]; + pix1 = palptr[pix1+12]; + pix2 = palptr[pix2+0]; + pix3 = palptr[pix3+4]; + } +#if SUPER_PIXEL_SIZE == 8 +# ifdef KEGS_LITTLE_ENDIAN + tmp = (pix3 << 24) + (pix2 << 16) + + (pix1 << 8) + pix0 + pal_word; +# else + tmp = (pix0 << 24) + (pix1 << 16) + + (pix2 << 8) + pix3 + pal_word; +# endif + *img_ptr++ = tmp; +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = tmp; +#endif +#elif SUPER_PIXEL_SIZE == 16 +# ifdef KEGS_LITTLE_ENDIAN + tmp = (pix1 << 16) + pix0; + tmp2 = (pix3 << 16) + pix2; +# else + tmp = (pix0 << 16) + pix1; + tmp2 = (pix2 << 16) + pix3; +# endif + *img_ptr++ = tmp; + *img_ptr++ = tmp2; +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = tmp; + *img_ptr2++ = tmp2; +#endif +#else /* SUPER_PIXEL_SIZE == 32 */ + *img_ptr++ = pix0; + *img_ptr++ = pix1; + *img_ptr++ = pix2; + *img_ptr++ = pix3; +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = pix0; + *img_ptr2++ = pix1; + *img_ptr2++ = pix2; + *img_ptr2++ = pix3; +#endif +#endif + +#if 0 + if(y == 1 && x1 == 0 && x2 == 0) { + printf("y==1,x1,x2=0, %02x = %08x %08x " + "%08x %08x, pal: %04x\n", val0, + pix0, pix1, pix2, pix3, pal); + printf("offset: %04x, nlo:%04x, ppl:" + "%04x, %d\n", offset, + next_line_offset, + pixels_per_line, SUPER_PIXEL_SIZE); + } +#endif + } + + } else { /* 320 mode */ + for(x2 = 0; x2 < shift_per; x2++) { + val0 = *slow_mem_ptr++; + pix0 = (val0 >> 4); + if(SUPER_FILL) { + if(pix0) { + save_pix = pix0; + } else { + pix0 = save_pix; + } + } + pix1 = (val0 & 0xf); + if(SUPER_FILL) { + if(pix1) { + save_pix = pix1; + } else { + pix1 = save_pix; + } + } + if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){ + pix0 = palptr[pix0]; + pix1 = palptr[pix1]; + } + if(dopr && x1 == 0) { + printf("y:%d, x2:%d, val:%02x = %08x %08x\n", y, x2, val0, pix0, pix1); + } +#if SUPER_PIXEL_SIZE == 8 +# ifdef KEGS_LITTLE_ENDIAN + tmp = (pix1 << 24) + (pix1 << 16) + + (pix0 << 8) + pix0 + pal_word; +# else + tmp = (pix0 << 24) + (pix0 << 16) + + (pix1 << 8) + pix1 + pal_word; +# endif + *img_ptr++ = tmp; +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = tmp; +#endif +#elif SUPER_PIXEL_SIZE == 16 + tmp = (pix0 << 16) + pix0; + tmp2 = (pix1 << 16) + pix1; + *img_ptr++ = tmp; + *img_ptr++ = tmp2; +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = tmp; + *img_ptr2++ = tmp2; +#endif +#else /* SUPER_PIXEL_SIZE == 32 */ + *img_ptr++ = pix0; +#ifdef VIDEO_DOUBLEHLINE + *img_ptr++ = pix0; +#endif + *img_ptr++ = pix1; +#ifdef VIDEO_DOUBLEHLINE + + *img_ptr++ = pix1; +#endif + +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = pix0; + *img_ptr2++ = pix0; + *img_ptr2++ = pix1; + *img_ptr2++ = pix1; +#endif +#endif + } + } + } +} + diff --git a/kegs/Src/video.cpp b/kegs/Src/video.cpp new file mode 100644 index 0000000..6f7dc07 --- /dev/null +++ b/kegs/Src/video.cpp @@ -0,0 +1,4224 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include + +#include "defc.h" +#include "moremem.h" +#include "sim65816.h" +#include "video.h" +#ifdef ACTIVEGS +#include "graphcounter.h" +#endif + +sd_video g_video; +ss_video s_video; + +Kimage g_kimage_offscreen; +int g_video_offscreen_has_been_modified = 0 ; + +//extern int g_save_cur_a2_stat; + +extern int g_config_control_panel; + +typedef byte Change; + word32 g_refresh_bytes_xfer = 0; + + + +char g_status_buf[MAX_STATUS_LINES][STATUS_LINE_LENGTH + 1]; +char *g_status_ptrs[MAX_STATUS_LINES] = { 0 }; + + word32 g_font40_even_bits[0x100][8][16/4]; + word32 g_font40_odd_bits[0x100][8][16/4]; + word32 g_font80_off0_bits[0x100][8][12/4]; + word32 g_font80_off1_bits[0x100][8][12/4]; + word32 g_font80_off2_bits[0x100][8][12/4]; + word32 g_font80_off3_bits[0x100][8][12/4]; + + word32 g_palette_8to1624[256]; + word32 g_a2palette_8to1624[256]; + + int g_expanded_col_0[16]; + int g_expanded_col_1[16]; + int g_expanded_col_2[16]; + +int g_video_act_margin_left = BASE_MARGIN_LEFT; +int g_video_act_margin_right = BASE_MARGIN_RIGHT; +int g_video_act_margin_top = BASE_MARGIN_TOP; + int g_video_act_margin_bottom = BASE_MARGIN_BOTTOM; + int g_video_act_width = X_A2_WINDOW_WIDTH; + int g_video_act_height = X_A2_WINDOW_HEIGHT; + +const int xxxg_dbhires_colors[] = { + /* rgb */ + 0x000, /* 0x0 black */ + 0xd03, /* 0x1 deep red */ + 0x852, /* 0x2 brown */ + 0xf60, /* 0x3 orange */ + 0x070, /* 0x4 dark green */ + 0x555, /* 0x5 dark gray */ + 0x0d0, /* 0x6 green */ + 0xff0, /* 0x7 yellow */ + 0x009, /* 0x8 dark blue */ + 0xd0d, /* 0x9 purple */ + 0xaaa, /* 0xa light gray */ + 0xf98, /* 0xb pink */ + 0x22f, /* 0xc medium blue */ + 0x6af, /* 0xd light blue */ + 0x0f9, /* 0xe aquamarine */ + 0xfff /* 0xf white */ +}; + +word32 g_dhires_convert[4096]; /* look up table of 7 bits (concat): */ + /* { 4 bits, |3 prev bits| } */ + +const byte g_dhires_colors_16[] = { + 0x00, /* 0x0 black */ + 0x02, /* 0x1 dark blue */ + 0x04, /* 0x2 dark green */ + 0x06, /* 0x3 medium blue */ + 0x08, /* 0x4 brown */ + 0x0a, /* 0x5 light gray */ + 0x0c, /* 0x6 green */ + 0x0e, /* 0x7 aquamarine */ + 0x01, /* 0x8 deep red */ + 0x03, /* 0x9 purple */ + 0x05, /* 0xa dark gray */ + 0x07, /* 0xb light blue */ + 0x09, /* 0xc orange */ + 0x0b, /* 0xd pink */ + 0x0d, /* 0xe yellow */ + 0x0f/* 0xf white */ +}; + + int g_lores_colors[] = { + /* rgb */ + 0x000, /* 0x0 black */ + 0xd03, /* 0x1 deep red */ + 0x009, /* 0x2 dark blue */ + 0xd0d, /* 0x3 purple */ + 0x070, /* 0x4 dark green */ + 0x555, /* 0x5 dark gray */ + 0x22f, /* 0x6 medium blue */ + 0x6af, /* 0x7 light blue */ + 0x852, /* 0x8 brown */ + 0xf60, /* 0x9 orange */ + 0xaaa, /* 0xa light gray */ + 0xf98, /* 0xb pink */ + 0x0d0, /* 0xc green */ + 0xff0, /* 0xd yellow */ + 0x0f9, /* 0xe aquamarine */ + 0xfff /* 0xf white */ +}; + +const word32 g_bw_hires_convert[4] = { + BIGEND(0x00000000), + BIGEND(0x0f0f0000), + BIGEND(0x00000f0f), + BIGEND(0x0f0f0f0f) +}; + +const word32 g_bw_dhires_convert[16] = { + BIGEND(0x00000000), + BIGEND(0x0f000000), + BIGEND(0x000f0000), + BIGEND(0x0f0f0000), + + BIGEND(0x00000f00), + BIGEND(0x0f000f00), + BIGEND(0x000f0f00), + BIGEND(0x0f0f0f00), + + BIGEND(0x0000000f), + BIGEND(0x0f00000f), + BIGEND(0x000f000f), + BIGEND(0x0f0f000f), + + BIGEND(0x00000f0f), + BIGEND(0x0f000f0f), + BIGEND(0x000f0f0f), + BIGEND(0x0f0f0f0f), +}; + +const word32 g_hires_convert[64] = { + BIGEND(0x00000000), /* 00,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 00,0001 = black, black, black, black */ + BIGEND(0x03030000), /* 00,0010 = purp , purp , black, black */ + BIGEND(0x0f0f0000), /* 00,0011 = white, white, black, black */ + BIGEND(0x00000c0c), /* 00,0100 = black, black, green, green */ + BIGEND(0x0c0c0c0c), /* 00,0101 = green, green, green, green */ + BIGEND(0x0f0f0f0f), /* 00,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 00,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 00,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 00,1001 = black, black, black, black */ + BIGEND(0x03030303), /* 00,1010 = purp , purp , purp , purp */ + BIGEND(0x0f0f0303), /* 00,1011 = white ,white, purp , purp */ + BIGEND(0x00000f0f), /* 00,1100 = black ,black, white, white */ + BIGEND(0x0c0c0f0f), /* 00,1101 = green ,green, white, white */ + BIGEND(0x0f0f0f0f), /* 00,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 00,1111 = white ,white, white, white */ + + BIGEND(0x00000000), /* 01,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 01,0001 = black, black, black, black */ + BIGEND(0x06060000), /* 01,0010 = blue , blue , black, black */ + BIGEND(0x0f0f0000), /* 01,0011 = white, white, black, black */ + BIGEND(0x00000c0c), /* 01,0100 = black, black, green, green */ + BIGEND(0x09090c0c), /* 01,0101 = orang, orang, green, green */ + BIGEND(0x0f0f0f0f), /* 01,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 01,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 01,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 01,1001 = black, black, black, black */ + BIGEND(0x06060303), /* 01,1010 = blue , blue , purp , purp */ + BIGEND(0x0f0f0303), /* 01,1011 = white ,white, purp , purp */ + BIGEND(0x00000f0f), /* 01,1100 = black ,black, white, white */ + BIGEND(0x09090f0f), /* 01,1101 = orang ,orang, white, white */ + BIGEND(0x0f0f0f0f), /* 01,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 01,1111 = white ,white, white, white */ + + BIGEND(0x00000000), /* 10,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 10,0001 = black, black, black, black */ + BIGEND(0x03030000), /* 10,0010 = purp , purp , black, black */ + BIGEND(0x0f0f0000), /* 10,0011 = white, white, black, black */ + BIGEND(0x00000909), /* 10,0100 = black, black, orang, orang */ + BIGEND(0x0c0c0909), /* 10,0101 = green, green, orang, orang */ + BIGEND(0x0f0f0f0f), /* 10,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 10,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 10,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 10,1001 = black, black, black, black */ + BIGEND(0x03030606), /* 10,1010 = purp , purp , blue , blue */ + BIGEND(0x0f0f0606), /* 10,1011 = white ,white, blue , blue */ + BIGEND(0x00000f0f), /* 10,1100 = black ,black, white, white */ + BIGEND(0x0c0c0f0f), /* 10,1101 = green ,green, white, white */ + BIGEND(0x0f0f0f0f), /* 10,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 10,1111 = white ,white, white, white */ + + BIGEND(0x00000000), /* 11,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 11,0001 = black, black, black, black */ + BIGEND(0x06060000), /* 11,0010 = blue , blue , black, black */ + BIGEND(0x0f0f0000), /* 11,0011 = white, white, black, black */ + BIGEND(0x00000909), /* 11,0100 = black, black, orang, orang */ + BIGEND(0x09090909), /* 11,0101 = orang, orang, orang, orang */ + BIGEND(0x0f0f0f0f), /* 11,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 11,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 11,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 11,1001 = black, black, black, black */ + BIGEND(0x06060606), /* 11,1010 = blue , blue , blue , blue */ + BIGEND(0x0f0f0606), /* 11,1011 = white ,white, blue , blue */ + BIGEND(0x00000f0f), /* 11,1100 = black ,black, white, white */ + BIGEND(0x09090f0f), /* 11,1101 = orang ,orang, white, white */ + BIGEND(0x0f0f0f0f), /* 11,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 11,1111 = white ,white, white, white */ +}; + + int g_screen_index[] = { + 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, + 0x028, 0x0a8, 0x128, 0x1a8, 0x228, 0x2a8, 0x328, 0x3a8, + 0x050, 0x0d0, 0x150, 0x1d0, 0x250, 0x2d0, 0x350, 0x3d0 +}; + + +void +video_init() +{ + word32 col[4]; + Kimage *kimage_ptr; + word32 *ptr; + word32 val0, val1, val2, val3; + word32 match_col; + word32 next_col, next2_col, next3_col; + word32 val; + word32 cur_col; + int width, height; + int total_bytes; + int i, j; + +// OG Reinit globals + g_video.g_a2_screen_buffer_changed = (word32)-1; + g_video.g_full_refresh_needed = (word32)-1; + g_video.g_cycs_in_40col = 0; + g_video.g_cycs_in_xredraw = 0; + + g_refresh_bytes_xfer = 0; + + g_video.g_video_dcycs_check_input = 0.0; + //g_video.g_video_extra_check_inputs = 0; // OG Initialized + + g_video.g_need_redraw = 1; + g_video.g_palette_change_summary = 0; + + g_video.g_border_sides_refresh_needed = 1; + g_video.g_border_special_refresh_needed = 1; + g_video.g_border_line24_refresh_needed = 1; + g_video.g_status_refresh_needed = 1; + + g_video.g_vbl_border_color = 0; + g_video.g_border_last_vbl_changes = 0; + + g_video.g_use_dhr140 = 0; +// s_video.g_use_bw_hires = 0; + + g_video.g_new_a2_stat_cur_line = 0; + g_video.g_vid_update_last_line = 0; + + g_video.g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |(0xf << BIT_ALL_STAT_TEXT_COLOR); + + + g_video.g_a2vid_palette = 0xe; + s_video.g_installed_full_superhires_colormap = 0; + + g_video.Max_color_size = 256; + + g_video.g_saved_a2vid_palette = -1; + + g_video.g_cycs_in_refresh_line = 0; + g_video.g_cycs_in_refresh_ximage = 0; + + g_video.g_num_lines_superhires = 0; + g_video.g_num_lines_superhires640 = 0; + g_video.g_num_lines_prev_superhires = 0; + g_video.g_num_lines_prev_superhires640 = 0; + + g_video.g_flash_count = 0; + + g_video.g_screen_redraw_skip_count = 0; + // g_video.g_screen_redraw_skip_amt = -1; + + g_video.g_cycs_in_check_input = 0; + + g_video.g_needfullrefreshfornextframe = 1 ; + + + g_video.g_num_a2vid_palette_checks = 1; + + g_video.g_border_color = 0; // OG Expose border color + + g_video.g_num_border_changes = 0; + + +/* Initialize video system */ + + for(i = 0; i < 200; i++) { + g_video.g_a2_line_kimage[i] = (Kimage *)0; // OG Changed from void* to kimage* + g_video.g_a2_line_stat[i] = -1; + g_video.g_a2_line_left_edge[i] = 0; + g_video.g_a2_line_right_edge[i] = 0; + } + for(i = 0; i < 200; i++) { + g_video.g_a2_new_all_stat[i] = 0; + g_video.g_a2_cur_all_stat[i] = 1; + for(j = 0; j < 8; j++) { + s_video.g_saved_line_palettes[i][j] = (word32)-1; + } + } + for(i = 0; i < 262; i++) { + g_video.g_cur_border_colors[i] = -1; + } + + g_video.g_new_a2_stat_cur_line = 0; + + x_video_init(); + + read_a2_font(); + + vid_printf("Zeroing out video memory\n"); + + for(i = 0; i < 8; i++) { + switch(i) { + case 0: + kimage_ptr = &(s_video.g_kimage_text[0]); + break; + case 1: + kimage_ptr = &(s_video.g_kimage_text[1]); + break; + case 2: + kimage_ptr = &(s_video.g_kimage_hires[0]); + break; + case 3: + kimage_ptr = &(s_video.g_kimage_hires[1]); + break; + case 4: + kimage_ptr = &s_video.g_kimage_superhires; + break; + case 5: + kimage_ptr = &s_video.g_kimage_border_sides; + break; + case 6: + kimage_ptr = &s_video.g_kimage_border_special; + break; + case 7: + kimage_ptr = &s_video.g_kimage_border_special2; + break; + + default: + printf("i: %d, unknown\n", i); + x_exit(3); + break; + } + + width = kimage_ptr->width_act; + height = kimage_ptr->height; + total_bytes = (kimage_ptr->mdepth >> 3) * width * height; + + ptr = (word32 *)kimage_ptr->data_ptr; + for(j = 0; j < total_bytes >> 2; j++) { + *ptr++ = 0; + } + + } + + for(i = 0; i < SLOW_MEM_CH_SIZE; i++) { + s_video.slow_mem_changed[i] = (word32)-1; + } + + /* create g_expanded_col_* */ + for(i = 0; i < 16; i++) { + val = (g_lores_colors[i] >> 0) & 0xf; + g_expanded_col_0[i] = val; + + val = (g_lores_colors[i] >> 4) & 0xf; + g_expanded_col_1[i] = val; + + val = (g_lores_colors[i] >> 8) & 0xf; + g_expanded_col_2[i] = val; + } + + /* create g_dhires_convert[] array */ + for(i = 0; i < 4096; i++) { + /* Convert index bits 11:0 where 3:0 is the previous color */ + /* and 7:4 is the current color to translate */ + /* Bit 4 will be the first pixel displayed on the screen */ + match_col = i & 0xf; + for(j = 0; j < 4; j++) { + cur_col = (i >> (1 + j)) & 0xf; + next_col = (i >> (2 + j)) & 0xf; + next2_col = (i >> (3 + j)) & 0xf; + next3_col = (i >> (4 + j)) & 0xf; + cur_col = (((cur_col << 4) + cur_col) >> (3 - j)) & 0xf; + + if((cur_col == 0xf) || (next_col == 0xf) || + (next2_col == 0xf) || + (next3_col == 0xf)) { + cur_col = 0xf; + col[j] = cur_col; + match_col = cur_col; + } else if((cur_col == 0) || (next_col == 0) || + (next2_col == 0) || (next3_col == 0)) { + cur_col = 0; + col[j] = cur_col; + match_col = cur_col; + } else { + col[j] = cur_col; + match_col = cur_col; + } + } + if(g_video.g_use_dhr140) { + for(j = 0; j < 4; j++) { + col[j] = (i >> 4) & 0xf; + } + } + val0 = g_dhires_colors_16[col[0] & 0xf]; + val1 = g_dhires_colors_16[col[1] & 0xf]; + val2 = g_dhires_colors_16[col[2] & 0xf]; + val3 = g_dhires_colors_16[col[3] & 0xf]; +#ifdef KEGS_LITTLE_ENDIAN + val = (val3 << 24) + (val2 << 16) + (val1 << 8) + val0; +#else + val = (val0 << 24) + (val1 << 16) + (val2 << 8) + val3; +#endif + g_dhires_convert[i] = val; + } +// printf("change_display_mode"); + change_display_mode(g_sim65816.g_cur_dcycs); +// printf("video_reset"); + video_reset(); +// printf("display_screen"); + display_screen(); + + fflush(stdout); +} + +void +show_a2_line_stuff() +{ + int i; + + for(i = 0; i < 200; i++) { + printf("line: %d: stat: %04x, ptr: %p, " + "left_edge:%d, right_edge:%d\n", + i, g_video.g_a2_line_stat[i], g_video.g_a2_line_kimage[i], + g_video.g_a2_line_left_edge[i], + g_video.g_a2_line_right_edge[i]); + } + + printf("new_a2_stat_cur_line: %d, cur_a2_stat:%04x\n", + g_video.g_new_a2_stat_cur_line, g_video.g_cur_a2_stat); + for(i = 0; i < 200; i++) { + printf("cur_all[%d]: %03x new_all: %03x\n", i, + g_video.g_a2_cur_all_stat[i], g_video.g_a2_new_all_stat[i]); + } + +} + +void +video_reset() +{ + int stat; + int i; + + s_video.g_installed_full_superhires_colormap = (s_video.g_screen_depth != 8); + stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 | + (0xf << BIT_ALL_STAT_TEXT_COLOR); + + if(r_sim65816.get_color_mode()==COLORMODE_BW) + { + stat |= ALL_STAT_COLOR_C021; + } + + if(g_config_control_panel) + { + extern int g_save_cur_a2_stat; + /* Don't update cur_a2_stat when in configuration panel */ + g_save_cur_a2_stat = stat; + } else { + g_video.g_cur_a2_stat = stat; + } + + g_video.g_palette_change_summary = 0; + for(i = 0; i < 16; i++) { + g_video.g_palette_change_cnt[i] = 0; + } + + /* install_a2vid_colormap(); */ + video_update_colormap(); +} + + +void video_update() +{ + + int did_video; + + // OG g_needfullrefreshfornextframe + if (g_video.g_needfullrefreshfornextframe) + { + + g_video.g_full_refresh_needed = -1; + g_video.g_a2_screen_buffer_changed = -1; + g_video.g_status_refresh_needed = 1; + g_video.g_border_sides_refresh_needed = 1; + g_video.g_border_special_refresh_needed = 1; + g_video.g_needfullrefreshfornextframe = 0; + } + + update_border_info(); + + video_check_input_events(); + + g_video.g_screen_redraw_skip_count--; + did_video = 0; + if(g_video.g_screen_redraw_skip_count < 0) { + did_video = 1; + video_update_event_line(262); + g_video.g_screen_redraw_skip_count = g_video.g_screen_redraw_skip_amt; + } + + /* update flash */ + g_video.g_flash_count++; + if(g_video.g_flash_count >= 30) { + g_video.g_flash_count = 0; + g_video.g_cur_a2_stat ^= ALL_STAT_FLASH_STATE; + change_display_mode(g_sim65816.g_cur_dcycs); + } + + + check_a2vid_palette(); + + + if(did_video) { + g_video.g_new_a2_stat_cur_line = 0; + g_video.g_a2_new_all_stat[0] = g_video.g_cur_a2_stat; + g_video.g_vid_update_last_line = 0; + video_update_through_line(0); + } + +// refresh_video(0); + + +} + + +int +video_all_stat_to_line_stat(int line, int new_all_stat) +{ + int page, color, dbl; + int st80, hires, annunc3, mix_t_gr; + int altchar, text_color, bg_color, flash_state; + int mode; + + st80 = new_all_stat & ALL_STAT_ST80; + hires = new_all_stat & ALL_STAT_HIRES; + annunc3 = new_all_stat & ALL_STAT_ANNUNC3; + mix_t_gr = new_all_stat & ALL_STAT_MIX_T_GR; + + page = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_PAGE2, 1) && !st80; + color = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_COLOR_C021, 1); + dbl = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_VID80, 1); + + altchar = 0; text_color = 0; bg_color = 0; flash_state = 0; + + if(new_all_stat & ALL_STAT_SUPER_HIRES) { + mode = MODE_SUPER_HIRES; + page = 0; dbl = 0; color = 0; + } else { + if(line >= 192) { + mode = MODE_BORDER; + page = 0; dbl = 0; color = 0; + } else if((new_all_stat & ALL_STAT_TEXT) || + (line >= 160 && mix_t_gr)) { + mode = MODE_TEXT; + color = 0; + altchar = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_ALTCHARSET, 1); + text_color = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_TEXT_COLOR, 4); + bg_color = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_BG_COLOR, 4); + flash_state = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_FLASH_STATE, 1); + if(altchar) { + /* don't bother flashing if altchar on */ + flash_state = 0; + } + } else { + /* obey the graphics mode */ + dbl = dbl && !annunc3; + if(hires) { + color = color | EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_DIS_COLOR_DHIRES, 1); + mode = MODE_HGR; + } else { + mode = MODE_GR; + } + } + } + + return((text_color << 12) + (bg_color << 8) + (altchar << 7) + + (mode << 4) + (flash_state << 3) + (page << 2) + + (color << 1) + dbl); +} + +int * +video_update_kimage_ptr(int line, int new_stat) +{ + Kimage *kimage_ptr; + int *mode_ptr; + int page; + int mode; + + page = (new_stat >> 2) & 1; + mode = (new_stat >> 4) & 7; + + switch(mode) { + case MODE_TEXT: + case MODE_GR: + kimage_ptr = &(s_video.g_kimage_text[page]); + mode_ptr = &(g_video.g_mode_text[page][0]); + break; + case MODE_HGR: + kimage_ptr = &(s_video.g_kimage_hires[page]); + mode_ptr = &(g_video.g_mode_hires[page][0]); + /* arrange to force superhires reparse since we use the */ + /* same memory */ + g_video.g_mode_superhires[line] = -1; + break; + case MODE_SUPER_HIRES: + kimage_ptr = &s_video.g_kimage_superhires; + mode_ptr = &(g_video.g_mode_superhires[0]); + /* arrange to force hires reparse since we use the */ + /* same memory */ + g_video.g_mode_hires[0][line] = -1; + g_video.g_mode_hires[1][line] = -1; + break; + case MODE_BORDER: + /* Hack: reuse text page last line as the special border */ + kimage_ptr = &s_video.g_kimage_border_special2; + mode_ptr = &(g_video.g_mode_border[0]); + break; + default: + halt_printf("update_a2_ptrs: mode: %d unknown!\n", mode); + return &(g_video.g_mode_superhires[0]); + } + + vid_printf("video_update_kimage_ptr %d=%p\n",line,kimage_ptr); + + g_video.g_a2_line_kimage[line] = kimage_ptr; + return mode_ptr; +} + +void +change_a2vid_palette(int new_palette) +{ + int i; + + for(i = 0; i < 200; i++) { + g_video.g_mode_text[0][i] = -1; + g_video.g_mode_text[1][i] = -1; + g_video.g_mode_hires[0][i] = -1; + g_video.g_mode_hires[1][i] = -1; + g_video.g_mode_superhires[i] = -1; + g_video.g_mode_border[i] = -1; + } + + printf("Changed a2vid_palette to %x\n", new_palette); + + g_video.g_a2vid_palette = new_palette; + g_video.g_cur_a2_stat = (g_video.g_cur_a2_stat & (~ALL_STAT_A2VID_PALETTE)) + + (new_palette << BIT_ALL_STAT_A2VID_PALETTE); + change_display_mode(g_sim65816.g_cur_dcycs); + + g_video.g_border_sides_refresh_needed = 1; + g_video.g_border_special_refresh_needed = 1; + g_video.g_status_refresh_needed = 1; + g_video.g_palette_change_cnt[new_palette]++; + g_video.g_border_last_vbl_changes = 1; + for(i = 0; i < 262; i++) { + g_video.g_cur_border_colors[i] = -1; + } +} + +void +check_a2vid_palette() +{ + int sum; + int min; + int val; + int min_pos; + int count_cur; + int i; + + /* determine if g_video.g_a2vid_palette should change */ + /* This is the palette of least use on superhires so that the */ + /* borders don't change when all 256 superhires colors are used */ + + g_video.g_num_a2vid_palette_checks--; + if(g_video.g_num_a2vid_palette_checks || s_video.g_installed_full_superhires_colormap){ + return; + } + + g_video.g_num_a2vid_palette_checks = 60; + + sum = 0; + min = 0x100000; + min_pos = -1; + count_cur = g_video.g_shr_palette_used[g_video.g_a2vid_palette]; + + for(i = 0; i < 16; i++) { + val = g_video.g_shr_palette_used[i]; + g_video.g_shr_palette_used[i] = 0; + if(val < min) { + min = val; + min_pos = i; + } + sum += val; + } + + if(g_video.g_a2vid_palette != min_pos && (count_cur > min)) { + change_a2vid_palette(min_pos); + } +} + +void +change_display_mode(double dcycs) +{ + int line, tmp_line; + + line = ((get_lines_since_vbl(dcycs) + 0xff) >> 8); + if(line < 0) { + line = 0; + halt_printf("Line < 0!\n"); + } + tmp_line = MIN(199, line); + + video_update_all_stat_through_line(tmp_line); + + if(line < 200) { + g_video.g_a2_new_all_stat[line] = g_video.g_cur_a2_stat; + } + /* otherwise, g_video.g_cur_a2_stat is covered at the end of vbl */ +} + +void +video_update_all_stat_through_line(int line) +{ + int start_line; + int prev_stat; + int max_line; + int i; + + start_line = g_video.g_new_a2_stat_cur_line; + prev_stat = g_video.g_a2_new_all_stat[start_line]; + + max_line = MIN(199, line); + + for(i = start_line + 1; i <= max_line; i++) { + g_video.g_a2_new_all_stat[i] = prev_stat; + } + g_video.g_new_a2_stat_cur_line = max_line; +} + + + + +void +change_border_color(double dcycs, int val) +{ + int pos; + + g_video.g_border_color = val; // OG Expose border color + + pos = g_video.g_num_border_changes; + g_video.g_border_changes[pos].fcycs = (float)(dcycs - g_sim65816.g_last_vbl_dcycs); + g_video.g_border_changes[pos].val = val; + // OG + /* + static int max=100; + if (max) + { + max--; + double dline = g_video.g_border_changes[pos].fcycs / 65.0; + int new_line = (int)dline; + + printf("changing border color (%d) @vbl:%d,line:%d %f(%f)\n",val,g_sim65816.g_vbl_count,new_line,g_sim65816.g_last_vbl_dcycs,g_sim65816.g_cur_dcycs); + } + */ + pos++; + g_video.g_num_border_changes = pos; + + if(pos >= MAX_BORDER_CHANGES) { + halt_printf("num border changes: %d\n", pos); + g_video.g_num_border_changes = 0; + } +} + +//extern int first; + +void +update_border_info() +{ + double dlines_per_dcyc; + double dcycs, dline, dcyc_line_start; + int offset; + int new_line_offset, last_line_offset; + int new_line; + int new_val; + int limit; + int color_now; + int i; + + + /* to get this routine to redraw the border, change */ + /* g_video.g_vbl_border_color, set g_video.g_border_last_vbl_changes = 1 */ + /* and change the cur_border_colors[] array */ + + color_now = g_video.g_vbl_border_color; + + dlines_per_dcyc = (double)(1.0 / 65.0); + limit = g_video.g_num_border_changes; + if(g_video.g_border_last_vbl_changes || limit) { + /* add a dummy entry */ + g_video.g_border_changes[limit].fcycs = DCYCS_IN_16MS + 21.0; + g_video.g_border_changes[limit].val = (g_moremem.g_c034_val & 0xf); + limit++; + } + last_line_offset = (-1 << 8) + 44; + for(i = 0; i < limit; i++) { + dcycs = g_video.g_border_changes[i].fcycs; + dline = dcycs * dlines_per_dcyc; + new_line = (int)dline; + dcyc_line_start = (double)new_line * 65.0; + offset = ((int)(dcycs - dcyc_line_start)) & 0xff; + + /* here comes the tricky part */ + /* offset is from 0 to 65, where 0-3 is the right border of */ + /* the previous line, 4-20 is horiz blanking, 21-24 is the */ + /* left border and 25-64 is the main window */ + /* Convert this to a new notation which is 0-3 is the left */ + /* border, 4-43 is the main window, and 44-47 is the right */ + /* basically, add -21 to offset, and wrap < 0 to previous ln */ + /* note this makes line -1 offset 44-47 the left hand border */ + /* for true line 261 on the screen */ + offset -= 21; + if(offset < 0) { + new_line--; + offset += 64; + } + new_val = g_video.g_border_changes[i].val; + new_line_offset = (new_line << 8) + offset; + + if(new_line_offset < -256 || new_line_offset >(262*256 + 0x80)){ + printf("new_line_offset: %05x\n", new_line_offset); + new_line_offset = last_line_offset; + } + while(last_line_offset < new_line_offset) { + /* see if this will finish it */ + if((last_line_offset & -256)==(new_line_offset & -256)){ + update_border_line(last_line_offset, + new_line_offset, color_now); + last_line_offset = new_line_offset; + } else { + update_border_line(last_line_offset, + (last_line_offset & -256) + 65, + color_now); + last_line_offset =(last_line_offset & -256)+256; + } + } + + color_now = new_val; + } + +#if 0 + if(g_video.g_num_border_changes) { + printf("Border changes: %d\n", g_video.g_num_border_changes); + } +#endif + + if(limit > 1) { + g_video.g_border_last_vbl_changes = 1; + } else { + g_video.g_border_last_vbl_changes = 0; + } + + g_video.g_num_border_changes = 0; + g_video.g_vbl_border_color = (g_moremem.g_c034_val & 0xf); +} + +void +update_border_line(int st_line_offset, int end_line_offset, int color) +{ + + word32 val; + int st_offset, end_offset; + int left, right; + int line; + + line = st_line_offset >> 8; + if(line != (end_line_offset >> 8)) { + halt_printf("ubl, %04x %04x %02x!\n", st_line_offset, + end_line_offset, color); + } + if(line < -1 || line >= 262) { + halt_printf("ubl-b, mod line is %d\n", line); + line = 0; + } + if(line < 0 || line >= 262) { + line = 0; + } + + st_offset = st_line_offset & 0xff; + end_offset = end_line_offset & 0xff; + + if((st_offset == 0) && (end_offset >= 0x41)) { + /* might be the same as last time, save some work */ + if(g_video.g_cur_border_colors[line] == color) { + return; + } + g_video.g_cur_border_colors[line] = color; + } else { + g_video.g_cur_border_colors[line] = -1; + } + + val = (color + (g_video.g_a2vid_palette << 4)); + val = (val << 24) + (val << 16) + (val << 8) + val; + + /* 0-3: left border, 4-43: main window, 44-47: right border */ + /* 48-65: horiz blanking */ + /* first, do the sides from line 0 to line 199 */ + if((line < 200) || (line >= 262)) { + if(line >= 262) { + line = 0; + } + if(st_offset < 4) { + /* left side */ + left = st_offset; + right = MIN(4, end_offset); + video_border_pixel_write(&s_video.g_kimage_border_sides, + VIDEO_VFACTOR*line, VIDEO_VFACTOR, val, (left * BORDER_WIDTH)/4, + (right * BORDER_WIDTH) / 4); + g_video.g_border_sides_refresh_needed = 1; + } + if((st_offset < 48) && (end_offset >= 44)) { + /* right side */ + left = MAX(0, st_offset - 44); + right = MIN(4, end_offset - 44); + + video_border_pixel_write(&s_video.g_kimage_border_sides, + VIDEO_VFACTOR*line, VIDEO_VFACTOR, val, + BORDER_WIDTH + (left * EFF_BORDER_WIDTH/4), + BORDER_WIDTH + (right * EFF_BORDER_WIDTH/4)); + g_video.g_border_sides_refresh_needed = 1; + } + } + + if((line >= 192) && (line < 200)) { + if(st_offset < 44 && end_offset > 4) { + left = MAX(0, st_offset - 4); + right = MIN(40, end_offset - 4); + + video_border_pixel_write(&s_video.g_kimage_border_special2, + VIDEO_VFACTOR*line, VIDEO_VFACTOR, val, left * 320*VIDEO_HFACTOR / 40, + right * 320*VIDEO_HFACTOR / 40); + g_video.g_border_line24_refresh_needed = 1; + } + } + + /* now do the bottom, lines 200 to 215 */ + if((line >= 200) && (line < (200 + 15 /*BASE_MARGIN_BOTTOM/2*/)) ) // OG bottom border height is not linked to the real border size : it is 15px anyway + { + line -= 200; + left = st_offset; + right = MIN(48, end_offset); + video_border_pixel_write(&s_video.g_kimage_border_special, VIDEO_VFACTOR*line, VIDEO_VFACTOR, + val, (left * X_A2_WINDOW_WIDTH / 48), + (right * X_A2_WINDOW_WIDTH / 48)); + g_video.g_border_special_refresh_needed = 1; + } + + /* and top, lines 236 to 262 */ + if((line >= (262 - 16 /*BASE_MARGIN_TOP/2*/)) && (line < 262)) { // OG top border height is not linked to the real border size : it is 16px anyway + line -= (262 - 16 /*BASE_MARGIN_TOP/2*/); + left = st_offset; + right = MIN(48, end_offset); + video_border_pixel_write(&s_video.g_kimage_border_special, + BASE_MARGIN_BOTTOM + VIDEO_VFACTOR*line, VIDEO_VFACTOR, val, + (left * X_A2_WINDOW_WIDTH / 48), + (right * X_A2_WINDOW_WIDTH / 48)); + g_video.g_border_special_refresh_needed = 1; + } +} + +void +video_border_pixel_write(Kimage *kimage_ptr, int starty, int num_lines, + word32 val, int st_off, int end_off) +{ + + int width; + int width_act; + int mdepth; + int num_words, num_bytes; + int bytes_per_pix; + int i, j; + + if(end_off <= st_off) { + return; + } + + width = end_off - st_off; + width_act = kimage_ptr->width_act; + mdepth = kimage_ptr->mdepth; + bytes_per_pix = mdepth >> 3; + num_bytes = width * bytes_per_pix; + num_words = num_bytes >> 2; + + if(width > width_act) { + halt_printf("border write but width %d > act %d\n", width, + width_act); + } + + if(mdepth == 16) { + val = g_a2palette_8to1624[val & 0xff]; + val = (val << 16) + val; + } else if(mdepth == 32) { + /* 32-bit pixels */ + val = g_a2palette_8to1624[val & 0xff]; + } + + + for(i = 0; i < num_lines; i++) + { + + if (mdepth==8) + { + byte* ptr = (byte *)&(kimage_ptr->data_ptr[(starty + i)*width_act*bytes_per_pix]); + ptr += st_off; + memset(ptr,val,width); + } + else + { + word32* ptr = (word32 *)&(kimage_ptr->data_ptr[(starty + i)*width_act*bytes_per_pix]); + ptr += ((st_off * bytes_per_pix) / 4); + // HACK: the above isn't really right when bytes_per_pix is less than four... + for(j = 0; j < num_words; j++) + *ptr++ = val; + } + } +} + + +#define CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, do_clear) \ + ch_ptr = &(s_video.slow_mem_changed[mem_ptr >> CHANGE_SHIFT]); \ + ch_bitpos = 0; \ + bits_per_line = 40 >> SHIFT_PER_CHANGE; \ + ch_shift_amount = (mem_ptr >> SHIFT_PER_CHANGE) & 0x1f; \ + mask_per_line = (-(1 << (32 - bits_per_line))); \ + mask_per_line = mask_per_line >> ch_shift_amount; \ + ch_mask = *ch_ptr & mask_per_line; \ + if(do_clear) { \ + *ch_ptr = *ch_ptr & (~ch_mask); \ + } \ + ch_mask = ch_mask << ch_shift_amount; \ + \ + if(reparse) { \ + ch_mask = - (1 << (32 - bits_per_line)); \ + } + +#define CH_LOOP_A2_VID(ch_mask, ch_tmp) \ + ch_tmp = ch_mask & 0x80000000; \ + ch_mask = ch_mask << 1; \ + \ + if(!ch_tmp) { \ + continue; \ + } + +void +redraw_changed_text_40(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, + int pixels_per_line) +{ + + register word32 start_time, end_time; + word32 *img_ptr; + word32 *save_img_ptr; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; + word32 *save_img_ptr2; +#endif + word32 *ch_ptr; + const word32 *font_ptr1; + const word32 *font_ptr2; + byte *slow_mem_ptr; + byte *b_ptr; + word32 ch_mask; + word32 ch_tmp; + word32 line_mask; + word32 mask_per_line; + word32 mem_ptr; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 palette_add; + word32 diff_val; + word32 and_val; + word32 add_val; + const word32 ff_val = 0x0f0f0f0f; + word32 val0, val1; + int flash_state; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line_mod8, st_line; + int i; + + /* always redraws to the next multiple of 8 lines due to redraw */ + /* issues: char changed on one screen redraw at line 0 with */ + /* num_lines=1. We need to have drawn lines 1-7 also since line 1 */ + /* will not see any changed bytes */ + st_line_mod8 = start_line & 7; + st_line = start_line; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << (y); + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + halt_printf("redraw_changed_text: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + /* avoid clearing changed bits unless we are line 0 (mod 8) */ + + if(ch_mask == 0) { + return; + } + + GET_ITIMER(start_time); + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + diff_val = (fg_val - bg_val) & 0xf; + and_val = diff_val + (diff_val << 8) + (diff_val << 16) +(diff_val<<24); + add_val = bg_val + (bg_val << 8) + (bg_val << 16) + (bg_val << 24); + + + flash_state = (g_video.g_cur_a2_stat & ALL_STAT_FLASH_STATE); + + for(x1 = 0; x1 < 40; x1 += shift_per) + { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + + b_ptr = &screen_data[(8*y + st_line_mod8)*VIDEO_VFACTOR*pixels_per_line + x1*7*VIDEO_HFACTOR]; + + vid_printf("b_ptr:%p screen_data:%p\n",b_ptr,screen_data); + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); +#endif + + +#ifndef VIDEO_DOUBLEHLINE + for(x2 = 0; x2 < shift_per; x2 += 4) + { + /* do 4 chars at once! */ + val0 = slow_mem_ptr[0]; + val1 = slow_mem_ptr[1]; + word32 val2 = slow_mem_ptr[2]; + word32 val3 = slow_mem_ptr[3]; + slow_mem_ptr += 4; + + if(!altcharset) { + if(val0 >= 0x40 && val0 < 0x80) { + if(flash_state) { + val0 += 0x40; + } else { + val0 -= 0x40; + } + } + if(val1 >= 0x40 && val1 < 0x80) { + if(flash_state) { + val1 += 0x40; + } else { + val1 -= 0x40; + } + } + if(val2 >= 0x40 && val2 < 0x80) { + if(flash_state) { + val2 += 0x40; + } else { + val2 -= 0x40; + } + } + if(val3 >= 0x40 && val3 < 0x80) { + if(flash_state) { + val3 += 0x40; + } else { + val3 -= 0x40; + } + } + } + save_img_ptr = img_ptr; +#ifdef VIDEO_DOUBLEVLINE + save_img_ptr2 = img_ptr2; +#endif + for(i = st_line_mod8; i < 8; i++) + { + const word32* font_ptr0 = &(g_font80_off0_bits[val0][i][0]); + tmp0 = (font_ptr0[0] & and_val) + add_val; + + const word32* font_ptr3 = &(g_font80_off3_bits[val1][i][0]); + tmp1 = ((font_ptr0[1]+font_ptr3[0]) & and_val)+ + add_val; + /* 3 bytes from ptr0, 1 from ptr3 */ + tmp2 = (font_ptr3[1] & and_val) + add_val; + + font_ptr2 = &(g_font80_off2_bits[val2][i][0]); + tmp3 = ((font_ptr3[2]+font_ptr2[0]) & and_val)+ + add_val; + /* 2 bytes from ptr3, 2 from ptr2*/ + tmp4 = (font_ptr2[1] & and_val) + add_val; + + font_ptr1 = &(g_font80_off1_bits[val3][i][0]); + tmp5 = ((font_ptr2[2]+font_ptr1[0]) & and_val)+ + add_val; + /* 1 byte from ptr2, 3 from ptr1 */ + tmp6 = (font_ptr1[1] & and_val) + add_val; + + tmp0 = (tmp0 & ff_val) + palette_add; + tmp1 = (tmp1 & ff_val) + palette_add; + tmp2 = (tmp2 & ff_val) + palette_add; + tmp3 = (tmp3 & ff_val) + palette_add; + tmp4 = (tmp4 & ff_val) + palette_add; + tmp5 = (tmp5 & ff_val) + palette_add; + tmp6 = (tmp6 & ff_val) + palette_add; + + img_ptr[0] = tmp0; + img_ptr[1] = tmp1; + img_ptr[2] = tmp2; + img_ptr[3] = tmp3; + img_ptr[4] = tmp4; + img_ptr[5] = tmp5; + img_ptr[6] = tmp6; + + img_ptr += (VIDEO_VFACTOR*pixels_per_line)/4; + } + img_ptr = save_img_ptr + 7; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = save_img_ptr2 + 7; +#endif + } + } +#else + for(x2 = 0; x2 < shift_per; x2 += 2) + { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + if(!altcharset) { + if(val0 >= 0x40 && val0 < 0x80) { + if(flash_state) { + val0 += 0x40; + } else { + val0 -= 0x40; + } + } + if(val1 >= 0x40 && val1 < 0x80) { + if(flash_state) { + val1 += 0x40; + } else { + val1 -= 0x40; + } + } + } + save_img_ptr = img_ptr; +#ifdef VIDEO_DOUBLEVLINE + save_img_ptr2 = img_ptr2; +#endif + for(i = st_line_mod8; i < 8; i++) { + font_ptr1 = &(g_font40_even_bits[val0][i][0]); + tmp0 = (font_ptr1[0] & and_val) + add_val; + tmp1 = (font_ptr1[1] & and_val) + add_val; + tmp2 = (font_ptr1[2] & and_val) + add_val; + + font_ptr2 = &(g_font40_odd_bits[val1][i][0]); + tmp3 = ((font_ptr1[3]+font_ptr2[0]) & and_val)+ + add_val; + + tmp4 = (font_ptr2[1] & and_val) + add_val; + tmp5 = (font_ptr2[2] & and_val) + add_val; + tmp6 = (font_ptr2[3] & and_val) + add_val; + + tmp0 = (tmp0 & ff_val) + palette_add; + tmp1 = (tmp1 & ff_val) + palette_add; + tmp2 = (tmp2 & ff_val) + palette_add; + tmp3 = (tmp3 & ff_val) + palette_add; + tmp4 = (tmp4 & ff_val) + palette_add; + tmp5 = (tmp5 & ff_val) + palette_add; + tmp6 = (tmp6 & ff_val) + palette_add; + + img_ptr[0] = tmp0; + img_ptr[1] = tmp1; + img_ptr[2] = tmp2; + img_ptr[3] = tmp3; + img_ptr[4] = tmp4; + img_ptr[5] = tmp5; + img_ptr[6] = tmp6; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2[0] = tmp0; + img_ptr2[1] = tmp1; + img_ptr2[2] = tmp2; + img_ptr2[3] = tmp3; + img_ptr2[4] = tmp4; + img_ptr2[5] = tmp5; + img_ptr2[6] = tmp6; + + img_ptr += (2*pixels_per_line)/4; + img_ptr2 += (2*pixels_per_line)/4; +#else + img_ptr += (1*pixels_per_line)/4; +#endif + } + + img_ptr = save_img_ptr + 7; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = save_img_ptr2 + 7; +#endif + } + } +#endif // VIDEO_DOUBLEHLINE + + GET_ITIMER(end_time); + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*7*VIDEO_HFACTOR); + g_video.g_a2_line_right_edge[st_line + i] = (right*7*VIDEO_HFACTOR); + } + + if(left >= right || left < 0 || right < 0) { + printf("line %d, 40: left >= right: %d >= %d\n", + start_line, left, right); + } + + g_video.g_cycs_in_40col += (end_time - start_time); + + g_video.g_need_redraw = 0; +} + +void +redraw_changed_text_80(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, + int pixels_per_line) +{ + const word32 *font_ptr0, *font_ptr1, *font_ptr2, *font_ptr3; + word32 *ch_ptr; + word32 *img_ptr; + word32 *save_img_ptr; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; + word32 *save_img_ptr2; +#endif + byte *b_ptr; + byte *slow_mem_ptr; + word32 ch_mask; + word32 ch_tmp; + word32 mask_per_line; + word32 mem_ptr; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 diff_val; + word32 add_val, and_val, ff_val; + word32 palette_add; + word32 line_mask; + word32 val0, val1, val2, val3; + int st_line_mod8, st_line; + int flash_state; + int y; + int x1, x2; + int i; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + +#ifndef VIDEO_DOUBLEHLINE + return ; +#endif + + st_line_mod8 = start_line & 7; + st_line = start_line; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << (y); + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + halt_printf("redraw_changed_text: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + + if(ch_mask == 0) { + return; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + diff_val = (fg_val - bg_val) & 0xf; + add_val = bg_val + (bg_val << 8) + (bg_val << 16) + (bg_val << 24); + and_val = diff_val + (diff_val << 8) + (diff_val << 16) +(diff_val<<24); + ff_val = 0x0f0f0f0f; + + flash_state = (g_video.g_cur_a2_stat & ALL_STAT_FLASH_STATE); + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*8 + st_line_mod8)*VIDEO_VFACTOR*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); +#endif + + for(x2 = 0; x2 < shift_per; x2 += 2) { + /* do 4 chars at once! */ + + val1 = slow_mem_ptr[0]; + val3 = slow_mem_ptr[1]; + val0 = slow_mem_ptr[0x10000]; + val2 = slow_mem_ptr[0x10001]; + slow_mem_ptr += 2; + + if(!altcharset) { + if(val0 >= 0x40 && val0 < 0x80) { + if(flash_state) { + val0 += 0x40; + } else { + val0 -= 0x40; + } + } + if(val1 >= 0x40 && val1 < 0x80) { + if(flash_state) { + val1 += 0x40; + } else { + val1 -= 0x40; + } + } + if(val2 >= 0x40 && val2 < 0x80) { + if(flash_state) { + val2 += 0x40; + } else { + val2 -= 0x40; + } + } + if(val3 >= 0x40 && val3 < 0x80) { + if(flash_state) { + val3 += 0x40; + } else { + val3 -= 0x40; + } + } + } + save_img_ptr = img_ptr; +#ifdef VIDEO_DOUBLEVLINE + save_img_ptr2 = img_ptr2; +#endif + for(i = st_line_mod8; i < 8; i++) { + font_ptr0 = &(g_font80_off0_bits[val0][i][0]); + tmp0 = (font_ptr0[0] & and_val) + add_val; + + font_ptr3 = &(g_font80_off3_bits[val1][i][0]); + tmp1 = ((font_ptr0[1]+font_ptr3[0]) & and_val)+ + add_val; + /* 3 bytes from ptr0, 1 from ptr3 */ + tmp2 = (font_ptr3[1] & and_val) + add_val; + + font_ptr2 = &(g_font80_off2_bits[val2][i][0]); + tmp3 = ((font_ptr3[2]+font_ptr2[0]) & and_val)+ + add_val; + /* 2 bytes from ptr3, 2 from ptr2*/ + tmp4 = (font_ptr2[1] & and_val) + add_val; + + font_ptr1 = &(g_font80_off1_bits[val3][i][0]); + tmp5 = ((font_ptr2[2]+font_ptr1[0]) & and_val)+ + add_val; + /* 1 byte from ptr2, 3 from ptr1 */ + tmp6 = (font_ptr1[1] & and_val) + add_val; + + tmp0 = (tmp0 & ff_val) + palette_add; + tmp1 = (tmp1 & ff_val) + palette_add; + tmp2 = (tmp2 & ff_val) + palette_add; + tmp3 = (tmp3 & ff_val) + palette_add; + tmp4 = (tmp4 & ff_val) + palette_add; + tmp5 = (tmp5 & ff_val) + palette_add; + tmp6 = (tmp6 & ff_val) + palette_add; + + img_ptr[0] = tmp0; + img_ptr[1] = tmp1; + img_ptr[2] = tmp2; + img_ptr[3] = tmp3; + img_ptr[4] = tmp4; + img_ptr[5] = tmp5; + img_ptr[6] = tmp6; + + img_ptr += (VIDEO_VFACTOR*pixels_per_line)/4; + +#ifdef VIDEO_DOUBLEVLINE + img_ptr2[0] = tmp0; + img_ptr2[1] = tmp1; + img_ptr2[2] = tmp2; + img_ptr2[3] = tmp3; + img_ptr2[4] = tmp4; + img_ptr2[5] = tmp5; + img_ptr2[6] = tmp6; + + img_ptr2 += (2*pixels_per_line)/4; +#endif + } + + img_ptr = save_img_ptr + 7; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = save_img_ptr2 + 7; +#endif + } + } + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*14); + g_video.g_a2_line_right_edge[st_line + i] = (right*14); + } + + if(left >= right || left < 0 || right < 0) { + printf("line %d, 80: left >= right: %d >= %d\n", + start_line, left, right); + } + + g_video.g_need_redraw = 0; + +} + +void +redraw_changed_gr(int start_offset, int start_line, int num_lines, int reparse, + byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; + word32 *save_img_ptr; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 line_mask; + word32 val0, val1; + word32 val0_wd, val1_wd; + word32 palette_add; + int half; + int x1, x2; + int y; + int y2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line_mod8, st_line, eff_line, end_line; + int i; + + st_line_mod8 = start_line & 7; + st_line = start_line; + end_line = 8; // st_line_mod8 + num_lines; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << y; + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + printf("redraw_changed_gr: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + + if(ch_mask == 0) { + return; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*8 + st_line_mod8)*VIDEO_VFACTOR*pixels_per_line + + x1*7*VIDEO_HFACTOR]; + img_ptr = (word32 *)b_ptr; + +#ifndef VIDEO_DOUBLEHLINE + for(x2 = 0; x2 < shift_per; x2 += 4) { + byte val_even_main = slow_mem_ptr[0]; + byte val_odd_main = slow_mem_ptr[1]; + byte val_even_aux = slow_mem_ptr[2]; + byte val_odd_aux = slow_mem_ptr[3]; + slow_mem_ptr += 4; + + save_img_ptr = img_ptr; + + for(half = 0; half < 2; half++) { + val0 = val_even_aux & 0xf; + val1 = val_even_main & 0xf; + word32 val2 = val_odd_aux & 0xf; + word32 val3 = val_odd_main & 0xf; + + /* Handle funny pattern of dbl gr aux mem */ + val0 = ((val0 << 1) & 0xf) + (val0 >> 3); + val2 = ((val2 << 1) & 0xf) + (val2 >> 3); + + val0_wd = (val0 << 24) + (val0 << 16) + + (val0 << 8) + val0; + val1_wd = (val1 << 24) + (val1 << 16) + + (val1 << 8) + val1; + word32 val2_wd = (val2 << 24) + (val2 << 16) + + (val2 << 8) + val2; + word32 val3_wd = (val3 << 24) + (val3 << 16) + + (val3 << 8) + val3; +#ifdef KEGS_LITTLE_ENDIAN + word32 val01_wd = (val1_wd << 24) + (val0_wd&0xffffff); + word32 val12_wd = (val2_wd << 16) + (val1_wd & 0xffff); + word32 val23_wd = (val3_wd << 8) + (val2_wd & 0xff); +#else + word32 val01_wd = (val0_wd << 8) + (val1_wd & 0xff); + word32 val12_wd = (val1_wd << 16) + (val2_wd & 0xffff); + word32 val23_wd = (val2_wd << 24) + (val3_wd&0xffffff); +#endif + + for(y2 = 0; y2 < 8; y2++) { + eff_line = half*4 + (y2 >> 1); + if((eff_line < st_line_mod8) || + (eff_line > end_line)) { + continue; + } + img_ptr[0] = val0_wd + palette_add; + img_ptr[1] = val01_wd + palette_add; + img_ptr[2] = val1_wd + palette_add; + img_ptr[3] = val12_wd + palette_add; + img_ptr[4] = val2_wd + palette_add; + img_ptr[5] = val23_wd + palette_add; + img_ptr[6] = val3_wd + palette_add; + img_ptr += (pixels_per_line)/4; +#ifndef VIDEO_DOUBLEVLINE + y2++; // skip line +#endif + } + + val_even_aux = val_even_aux >> 4; + val_even_main = val_even_main >> 4; + val_odd_aux = val_odd_aux >> 4; + val_odd_main = val_odd_main >> 4; + } + + img_ptr = save_img_ptr + 7; + } + } +#else // VIDEO_DOUBLEHLINE + + for(x2 = 0; x2 < shift_per; x2 += 2) { + byte val_even = *slow_mem_ptr++; + byte val_odd = *slow_mem_ptr++; + + save_img_ptr = img_ptr; + + for(half = 0; half < 2; half++) { + val0 = val_even & 0xf; + val1 = val_odd & 0xf; + val0_wd = (val0 << 24) + (val0 << 16) + + (val0 << 8) + val0; + val1_wd = (val1 << 24) + (val1 << 16) + + (val1 << 8) + val1; +#ifdef KEGS_LITTLE_ENDIAN + word32 val01_wd = (val1_wd << 16) + (val0_wd & 0xffff); +#else + word32 val01_wd = (val0_wd << 16) + (val1_wd & 0xffff); +#endif + + for(y2 = 0; y2 < 8; y2++) { + + eff_line = half*4 + (y2 >> 1); + if((eff_line < st_line_mod8) || + (eff_line > end_line)) { + continue; + } + + img_ptr[0] = val0_wd + palette_add; + img_ptr[1] = val0_wd + palette_add; + img_ptr[2] = val0_wd + palette_add; + img_ptr[3] = val01_wd + palette_add; + img_ptr[4] = val1_wd + palette_add; + img_ptr[5] = val1_wd + palette_add; + img_ptr[6] = val1_wd + palette_add; + img_ptr += (pixels_per_line)/4; + +#ifndef VIDEO_DOUBLEVLINE + y2++; // skip line +#endif + } + + val_even = val_even >> 4; + val_odd = val_odd >> 4; + } + + img_ptr = save_img_ptr + 7; + } + } +#endif // !VIDEO_DOUBLEHLINE + for(i = 0; i < (8 - st_line_mod8); i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*7*VIDEO_HFACTOR); + g_video.g_a2_line_right_edge[st_line + i] = (right*7*VIDEO_HFACTOR); + } + + g_video.g_need_redraw = 0; +} + +void +redraw_changed_dbl_gr(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; + word32 *save_img_ptr; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 line_mask; + word32 val0, val1, val2, val3; + word32 val0_wd, val1_wd, val2_wd, val3_wd; + word32 val01_wd, val12_wd, val23_wd; + word32 val_even_main, val_odd_main; + word32 val_even_aux, val_odd_aux; + word32 palette_add; + int half; + int x1, x2; + int y; + int y2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line_mod8, st_line, eff_line, end_line; + int i; + +#ifndef VIDEO_DOUBLEHLINE + return ; +#endif + + + st_line_mod8 = start_line & 7; + end_line = 8; // st_line_mod8 + num_lines + st_line = start_line; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << y; + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + printf("redraw_changed_dbl_gr: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + + if(ch_mask == 0) { + return; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*8 + st_line_mod8)*VIDEO_VFACTOR*pixels_per_line + + x1*14]; + img_ptr = (word32 *)b_ptr; + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val_even_main = slow_mem_ptr[0]; + val_odd_main = slow_mem_ptr[1]; + val_even_aux = slow_mem_ptr[0x10000]; + val_odd_aux = slow_mem_ptr[0x10001]; + slow_mem_ptr += 2; + + save_img_ptr = img_ptr; + + for(half = 0; half < 2; half++) { + val0 = val_even_aux & 0xf; + val1 = val_even_main & 0xf; + val2 = val_odd_aux & 0xf; + val3 = val_odd_main & 0xf; + + /* Handle funny pattern of dbl gr aux mem */ + val0 = ((val0 << 1) & 0xf) + (val0 >> 3); + val2 = ((val2 << 1) & 0xf) + (val2 >> 3); + + val0_wd = (val0 << 24) + (val0 << 16) + + (val0 << 8) + val0; + val1_wd = (val1 << 24) + (val1 << 16) + + (val1 << 8) + val1; + val2_wd = (val2 << 24) + (val2 << 16) + + (val2 << 8) + val2; + val3_wd = (val3 << 24) + (val3 << 16) + + (val3 << 8) + val3; +#ifdef KEGS_LITTLE_ENDIAN + val01_wd = (val1_wd << 24) + (val0_wd&0xffffff); + val12_wd = (val2_wd << 16) + (val1_wd & 0xffff); + val23_wd = (val3_wd << 8) + (val2_wd & 0xff); +#else + val01_wd = (val0_wd << 8) + (val1_wd & 0xff); + val12_wd = (val1_wd << 16) + (val2_wd & 0xffff); + val23_wd = (val2_wd << 24) + (val3_wd&0xffffff); +#endif + + for(y2 = 0; y2 < 8; y2++) { + eff_line = half*4 + (y2 >> 1); + if((eff_line < st_line_mod8) || + (eff_line > end_line)) { + continue; + } + img_ptr[0] = val0_wd + palette_add; + img_ptr[1] = val01_wd + palette_add; + img_ptr[2] = val1_wd + palette_add; + img_ptr[3] = val12_wd + palette_add; + img_ptr[4] = val2_wd + palette_add; + img_ptr[5] = val23_wd + palette_add; + img_ptr[6] = val3_wd + palette_add; + img_ptr += (pixels_per_line)/4; +#ifndef VIDEO_DOUBLEVLINE + y2++; // skip line +#endif + } + + val_even_aux = val_even_aux >> 4; + val_even_main = val_even_main >> 4; + val_odd_aux = val_odd_aux >> 4; + val_odd_main = val_odd_main >> 4; + } + + img_ptr = save_img_ptr + 7; + } + } + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*14); + g_video.g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_video.g_need_redraw = 0; +} + +void +redraw_changed_hires(int start_offset, int start_line, int num_lines, + int color, int reparse, byte *screen_data, int pixels_per_line) +{ + if(!color) + { + redraw_changed_hires_color(start_offset, start_line, num_lines, + reparse, screen_data, pixels_per_line); + } else { + redraw_changed_hires_bw(start_offset, start_line, num_lines, + reparse, screen_data, pixels_per_line); + } +} + +void +redraw_changed_hires_bw(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; +#endif + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; +#ifndef ACTIVEGSKARATEKA + word32 ch_tmp; +#endif + + word32 mem_ptr; + word32 val0, val1; + word32 val_whole; + word32 line_mask; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i; + + + st_line = start_line; + start_line = start_line >> 3; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + + g_screen_index[y >> 3]) + start_offset; + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + +#ifndef ACTIVEGSKARATEKA + if(ch_mask == 0) { + continue; + } +#else +#pragma message( "TODO Find why BW scrolling is broken") +#endif + + + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) + { +#ifndef ACTIVEGSKARATEKA + CH_LOOP_A2_VID(ch_mask, ch_tmp); +#endif + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*VIDEO_VFACTOR)*pixels_per_line + x1*7*VIDEO_HFACTOR]; + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); +#endif + + +#ifndef VIDEO_DOUBLEHLINE + for(x2 = 0; x2 < shift_per; x2 += 2) + { + + // word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + + val0 = slow_mem_ptr[0]; + val1 = slow_mem_ptr[1]; + word32 val2 = slow_mem_ptr[2]; + word32 val3 = slow_mem_ptr[3]; + slow_mem_ptr += 4; + + val_whole = ((val3 & 0x7f) << 21) + + ((val2 & 0x7f) << 14) + + ((val1 & 0x7f) << 7) + + (val0 & 0x7f); + + word32 tmp0 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp1 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp2 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp3 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp4 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp5 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp6 = g_bw_dhires_convert[val_whole & 0xf]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + img_ptr += 7; + } +#else // !VIDEO_DOUBLEHLINE + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + val_whole = ((val1 & 0x7f) << 7) +(val0 & 0x7f); + + word32 tmp0 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + word32 tmp1 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + word32 tmp2 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + word32 tmp3 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + word32 tmp4 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + word32 tmp5 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + word32 tmp6 = g_bw_hires_convert[val_whole & 3]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + img_ptr += 7; + +#ifdef VIDEO_DOUBLEVLINE + img_ptr2[0] = tmp0 + palette_add; + img_ptr2[1] = tmp1 + palette_add; + img_ptr2[2] = tmp2 + palette_add; + img_ptr2[3] = tmp3 + palette_add; + img_ptr2[4] = tmp4 + palette_add; + img_ptr2[5] = tmp5 + palette_add; + img_ptr2[6] = tmp6 + palette_add; + img_ptr2 += 7; +#endif + } +#endif // VIDEO_DOUBLEHLINE + } + + } + + for(i = 0; i < num_lines; i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*7*VIDEO_HFACTOR); + g_video.g_a2_line_right_edge[st_line + i] = (right*7*VIDEO_HFACTOR); + } + + g_video.g_need_redraw = 0; +} + +void +redraw_changed_hires_color(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; +#endif + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 val0, val1; + word32 val_whole; + word32 pix_val; + word32 line_mask; + word32 prev_pixel; + word32 prev_hi; + word32 loc_hi; + word32 val_hi; + word32 tmp_val; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i, j; + + st_line = start_line; +// int st_line2 = start_line; + + start_line = start_line >> 3; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + + g_screen_index[y >> 3]) + start_offset; + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + /* Hires depends on adjacent bits, so also reparse adjacent */ + /* regions so that if bits on the edge change, redrawing is */ + /* correct */ + ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1); + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*VIDEO_VFACTOR)*pixels_per_line + x1*7*VIDEO_HFACTOR]; + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); +#endif + prev_pixel = 0; + prev_hi = 0; + + if(x1 > 0) { + tmp_val = slow_mem_ptr[-1]; + prev_pixel = (tmp_val >> 6) & 1; + prev_hi = (tmp_val >> 7) & 0x1; + } + +#ifndef VIDEO_DOUBLEHLINE + +#if 0 + // mode B&w + for(x2 = 0; x2 < shift_per; x2 += 2) { + + val0 = slow_mem_ptr[0]; + val1 = slow_mem_ptr[1]; + word32 val2 = slow_mem_ptr[2]; + word32 val3 = slow_mem_ptr[3]; + slow_mem_ptr += 4; + + val_whole = ((val3 & 0x7f) << 21) + + ((val2 & 0x7f) << 14) + + ((val1 & 0x7f) << 7) + + (val0 & 0x7f); + + word32 tmp0 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp1 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp2 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp3 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp4 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp5 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + word32 tmp6 = g_bw_dhires_convert[val_whole & 0xf]; + + /* + word32 tmp0 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + word32 tmp1 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + word32 tmp2 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + word32 tmp3 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + word32 tmp4 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + word32 tmp5 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + if((x1 + x2 + 2) < 40) { + val_whole += (slow_mem_ptr[0]<<8); + } + word32 tmp6 = g_dhires_convert[val_whole & 0xfff]; + */ + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + img_ptr += 7; + } + } +#endif + word16* img_ptrw = (word16*)b_ptr; + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + val_whole = ((val1 & 0x7f) << 8) + + ((val0 & 0x7f) << 1) + + prev_pixel; + + loc_hi = prev_hi; + if(((val1 >> 7) & 1) != 0) { + loc_hi += 0x7f00; + } + if(((val0 >> 7) & 1) != 0) { + loc_hi += 0xfe; + } + + prev_pixel = (val1 >> 6) & 1; + prev_hi = (val1 >> 7) & 1; + if((x1 + x2 + 2) < 40) { + tmp_val = slow_mem_ptr[0]; + if(tmp_val & 1) { + val_whole |= 0x8000; + } + if(tmp_val & 0x80) { + loc_hi |= 0x8000; + } + } + + loc_hi = loc_hi >> 1; + + for(j = 0; j < 7; j+=1) { + tmp_val = val_whole & 0xf; + val_hi = loc_hi & 0x3; + + pix_val = g_hires_convert[(val_hi<<4) + tmp_val]; + + // OG To optimize + word16 pix_16 = (pix_val >> 8 ) & 0xFFFF; + *img_ptrw++ = pix_16; + +/* +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = pix_val + palette_add; +#endif + */ + val_whole = val_whole >> 2; + loc_hi = loc_hi >> 2; + } + } + } + +#else //!VIDEO_DOUBLEHLINE + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + val_whole = ((val1 & 0x7f) << 8) + + ((val0 & 0x7f) << 1) + + prev_pixel; + + loc_hi = prev_hi; + if(((val1 >> 7) & 1) != 0) { + loc_hi += 0x7f00; + } + if(((val0 >> 7) & 1) != 0) { + loc_hi += 0xfe; + } + + prev_pixel = (val1 >> 6) & 1; + prev_hi = (val1 >> 7) & 1; + if((x1 + x2 + 2) < 40) { + tmp_val = slow_mem_ptr[0]; + if(tmp_val & 1) { + val_whole |= 0x8000; + } + if(tmp_val & 0x80) { + loc_hi |= 0x8000; + } + } + + loc_hi = loc_hi >> 1; + + for(j = 0; j < 7; j+=2/VIDEO_HFACTOR) { + tmp_val = val_whole & 0xf; + val_hi = loc_hi & 0x3; + + pix_val = g_hires_convert[(val_hi<<4) + tmp_val]; + *img_ptr++ = pix_val + palette_add; +#ifdef VIDEO_DOUBLEVLINE + *img_ptr2++ = pix_val + palette_add; +#endif + val_whole = val_whole >> 2; + loc_hi = loc_hi >> 2; + } + } + } +#endif // VIDEO_DOUBLEHLINE + } + + for(i = 0; i < num_lines; i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*7*VIDEO_HFACTOR); + g_video.g_a2_line_right_edge[st_line + i] = (right*7*VIDEO_HFACTOR); + /* //OG + for(int j=0;j<32;j++) + { + screen_data[(i+st_line2)*VIDEO_VFACTOR*pixels_per_line+j] = start_offset?0x00:0xFF ; + screen_data[((i+st_line2)*VIDEO_VFACTOR+1)*pixels_per_line+j] = start_offset?0x00:0xFF ; + } + */ + } + + g_video.g_need_redraw = 0; +} + + +void +redraw_changed_dbl_hires(int start_offset, int start_line, int num_lines, + int color, int reparse, byte *screen_data, int pixels_per_line) +{ + if(!color) { + redraw_changed_dbl_hires_color(start_offset, start_line, + num_lines, reparse, screen_data, pixels_per_line); + } else { + redraw_changed_dbl_hires_bw(start_offset, start_line, + num_lines, reparse, screen_data, pixels_per_line); + } +} + + +void +redraw_changed_dbl_hires_bw(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; +#endif + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 val0, val1, val2, val3; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 val_whole; + word32 line_mask; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + g_screen_index[y >> 3] + + start_offset); + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + /* Hires depends on adjacent bits, so also reparse adjacent */ + /* regions so that if bits on the edge change, redrawing is */ + /* correct */ + ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1); + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*VIDEO_VFACTOR)*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); +#endif + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = slow_mem_ptr[0x10000]; + val1 = slow_mem_ptr[0]; + val2 = slow_mem_ptr[0x10001]; + val3 = slow_mem_ptr[1]; + slow_mem_ptr += 2; + + val_whole = ((val3 & 0x7f) << 21) + + ((val2 & 0x7f) << 14) + + ((val1 & 0x7f) << 7) + + (val0 & 0x7f); + + tmp0 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp1 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp2 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp3 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp4 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp5 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp6 = g_bw_dhires_convert[val_whole & 0xf]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + img_ptr += 7; + +#ifdef VIDEO_DOUBLEVLINE + img_ptr2[0] = tmp0 + palette_add; + img_ptr2[1] = tmp1 + palette_add; + img_ptr2[2] = tmp2 + palette_add; + img_ptr2[3] = tmp3 + palette_add; + img_ptr2[4] = tmp4 + palette_add; + img_ptr2[5] = tmp5 + palette_add; + img_ptr2[6] = tmp6 + palette_add; + img_ptr2 += 7; +#endif + + } + } + } + + for(i = 0; i < num_lines; i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*14); + g_video.g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_video.g_need_redraw = 0; +} + +void +redraw_changed_dbl_hires_color(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *ch_ptr; + word32 *img_ptr; +#ifdef VIDEO_DOUBLEVLINE + word32 *img_ptr2; +#endif + byte *slow_mem_ptr; + byte *b_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 val0, val1, val2, val3; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 val_whole; + word32 prev_val; + word32 line_mask; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + palette_add = (g_video.g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + g_screen_index[y >> 3] + + start_offset); + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + /* dbl-hires also depends on adjacent bits, so reparse */ + /* adjacent regions so that if bits on the edge change, */ + /* redrawing is correct */ + ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1); + ch_mask = -1; + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_video.g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*VIDEO_VFACTOR)*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; +#ifdef VIDEO_DOUBLEVLINE + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); +#endif + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = slow_mem_ptr[0x10000]; + val1 = slow_mem_ptr[0]; + val2 = slow_mem_ptr[0x10001]; + val3 = slow_mem_ptr[1]; + + prev_val = 0; + if((x1 + x2) > 0) { + prev_val = (slow_mem_ptr[-1] >> 3) &0xf; + } + val_whole = ((val3 & 0x7f) << 25) + + ((val2 & 0x7f) << 18) + + ((val1 & 0x7f) << 11) + + ((val0 & 0x7f) << 4) + prev_val; + + tmp0 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp1 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp2 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp3 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp4 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp5 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + if((x1 + x2 + 2) < 40) { + val_whole += (slow_mem_ptr[0x10002]<<8); + } + tmp6 = g_dhires_convert[val_whole & 0xfff]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + img_ptr += 7; + +#ifdef VIDEO_DOUBLEVLINE + img_ptr2[0] = tmp0 + palette_add; + img_ptr2[1] = tmp1 + palette_add; + img_ptr2[2] = tmp2 + palette_add; + img_ptr2[3] = tmp3 + palette_add; + img_ptr2[4] = tmp4 + palette_add; + img_ptr2[5] = tmp5 + palette_add; + img_ptr2[6] = tmp6 + palette_add; + img_ptr2 += 7; +#endif + slow_mem_ptr += 2; + + } + } + } + + for(i = 0; i < num_lines; i++) { + g_video.g_a2_line_left_edge[st_line + i] = (left*14); + g_video.g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_video.g_need_redraw = 0; +} + +int +video_rebuild_super_hires_palette(word32 scan_info, int line, int reparse) +{ + word32 *word_ptr; + word32 *ch_ptr; + byte *byte_ptr; + word32 ch_mask, mask_per_line; + word32 tmp; + word32 scan, old_scan; + int palette_changed; + int diff0, diff1, diff2; + int val0, val1, val2; + int diffs; + int low_delta, low_color; + int delta; + int full; + int ch_bit_offset, ch_word_offset; + int bits_per_line; + int palette; + int j, k; + + palette_changed = 0; + palette = scan_info & 0xf; + + ch_ptr = &(s_video.slow_mem_changed[0x9e00 >> CHANGE_SHIFT]); + ch_bit_offset = (palette << 5) >> SHIFT_PER_CHANGE; + ch_word_offset = ch_bit_offset >> 5; + ch_bit_offset = ch_bit_offset & 0x1f; + bits_per_line = (0x20 >> SHIFT_PER_CHANGE); + mask_per_line = -(1 << (32 - bits_per_line)); + mask_per_line = mask_per_line >> ch_bit_offset; + + ch_mask = ch_ptr[ch_word_offset] & mask_per_line; + ch_ptr[ch_word_offset] &= ~mask_per_line; /* clear the bits */ + + old_scan = g_video.g_superhires_scan_save[line]; + scan = (scan_info & 0xfaf) + (g_video.g_palette_change_cnt[palette] << 12); + g_video.g_superhires_scan_save[line] = scan; + +#if 0 + if(line == 1) { + word_ptr = (word32 *)&(g_slow_memory_ptr[0x19e00+palette*0x20]); + printf("y1vrshp, ch:%08x, s:%08x,os:%08x %d = %08x %08x %08x %08x %08x %08x %08x %08x\n", + ch_mask, scan, old_scan, reparse, + word_ptr[0], word_ptr[1], word_ptr[2], word_ptr[3], + word_ptr[4], word_ptr[5], word_ptr[6], word_ptr[7]); + } +#endif + + diffs = reparse | ((scan ^ old_scan) & 0xf0f); + /* we must do full reparse if palette changed for this line */ + + if(!diffs && (ch_mask == 0) && (((scan ^ old_scan) & (~0xf0)) == 0)) { + /* nothing changed, get out fast */ + return 0; + } + + if(ch_mask) { + /* indicates the palette has changed, and other scan lines */ + /* using this palette need to do a full 32-byte compare to */ + /* decide if they need to update or not */ + g_video.g_palette_change_cnt[palette]++; + } + + word_ptr = (word32 *)&(g_slow_memory_ptr[0x19e00 + palette*0x20]); + for(j = 0; j < 8; j++) { + if(word_ptr[j] != s_video.g_saved_line_palettes[line][j]) { + diffs = 1; + break; + } + } + + if(diffs == 0) { + return 0; + } + + /* first, save this word_ptr into saved_line_palettes */ + byte_ptr = (byte *)word_ptr; + for(j = 0; j < 8; j++) { + s_video.g_saved_line_palettes[line][j] = word_ptr[j]; + } + + full = s_video.g_installed_full_superhires_colormap; + + if(!full && palette == g_video.g_a2vid_palette) { + /* construct new color approximations from lores */ + for(j = 0; j < 16; j++) { + tmp = *byte_ptr++; + val2 = (*byte_ptr++) & 0xf; + val0 = tmp & 0xf; + val1 = (tmp >> 4) & 0xf; + low_delta = 0x1000; + low_color = 0x0; + for(k = 0; k < 16; k++) { + diff0 = g_expanded_col_0[k] - val0; + diff1 = g_expanded_col_1[k] - val1; + diff2 = g_expanded_col_2[k] - val2; + if(diff0 < 0) { + diff0 = -diff0; + } + if(diff1 < 0) { + diff1 = -diff1; + } + if(diff2 < 0) { + diff2 = -diff2; + } + delta = diff0 + diff1 + diff2; + if(delta < low_delta) { + low_delta = delta; + low_color = k; + } + } + + g_video.g_a2vid_palette_remap[j] = low_color; + } + } + // OG + //extern double last_vid_update_dcys; + //printf("palette %d (%x) changed @line:%d (vidupd:%f) last_vbl:%d (%f) dcycs :%f\n",palette,*byte_ptr,line,last_vid_update_dcys,g_sim65816.g_vbl_count,g_sim65816.g_last_vbl_dcycs,g_sim65816.g_cur_dcycs); + byte_ptr = (byte *)word_ptr; + /* this palette has changed */ + for(j = 0; j < 16; j++) { + val0 = *byte_ptr++; + val1 = *byte_ptr++; + video_update_color_array(palette*16 + j, (val1<<8) + val0); + } + + g_video.g_palette_change_summary = 1; + + return 1; +} + +#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_8 +#define SUPER_FILL 0 +#define SUPER_PIXEL_SIZE 8 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_16 +#define SUPER_FILL 0 +#define SUPER_PIXEL_SIZE 16 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_32 +#define SUPER_FILL 0 +#define SUPER_PIXEL_SIZE 32 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_8 +#define SUPER_FILL 1 +#define SUPER_PIXEL_SIZE 8 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_16 +#define SUPER_FILL 1 +#define SUPER_PIXEL_SIZE 16 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_32 +#define SUPER_FILL 1 +#define SUPER_PIXEL_SIZE 32 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + + + +void +redraw_changed_super_hires(int start_offset, int start_line, int num_lines, + int in_reparse, byte *screen_data) +{ + word32 *ch_ptr; + word32 mask_per_line; + word32 all_checks; + word32 check0, check1, mask0, mask1; + word32 this_check; + word32 tmp; + word32 line_mask; + word32 pal; + word32 scan, old_scan; + word32 kd_tmp_debug; + int y; + int bits_per_line; + int a2vid_palette; + int type; + int left, right; + int st_line; + int check_bit_pos, check_word_off; + int pixel_size, pixel_size_type; + int use_a2vid_palette, mode_640; + int pixels_per_line; + int ret; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + pixel_size = s_video.g_kimage_superhires.mdepth; + pixels_per_line = s_video.g_kimage_superhires.width_act; + + pixel_size_type = (pixel_size >> 3) - 1; + /* pixel_size_type is now: 0=8bit, 1=16bit, 3=32bit */ + if(pixel_size_type >= 3) { + pixel_size_type = 2; + } + + kd_tmp_debug = g_video.g_a2_screen_buffer_changed; + + line_mask = 1 << (start_line); + + ch_ptr = &(s_video.slow_mem_changed[(0x2000) >> CHANGE_SHIFT]); + bits_per_line = 160 >> SHIFT_PER_CHANGE; + mask_per_line = -(1 << (32 - bits_per_line)); + + if(SHIFT_PER_CHANGE != 3) { + halt_printf("SHIFT_PER_CHANGE must be 3!\n"); + return; + } + + a2vid_palette = g_video.g_a2vid_palette; + if(s_video.g_installed_full_superhires_colormap) { + a2vid_palette = -1; + } else { + /* handle palette counting for finding least-used palette */ + if(pixel_size == 8) { + for(y = 8*start_line; y < 8*(start_line + 1); y++) { + scan = g_slow_memory_ptr[0x19d00 + y]; + pal = scan & 0xf; + g_video.g_shr_palette_used[pal]++; + } + } + } + + all_checks = 0; + check0 = 0; + check1 = 0; + for(y = st_line; y < (st_line + num_lines); y++) { + scan = g_slow_memory_ptr[0x19d00 + y]; + check_bit_pos = bits_per_line * y; + check_word_off = check_bit_pos >> 5; /* 32 bits per word */ + check_bit_pos = check_bit_pos & 0x1f; /* 5-bit bit_pos */ + check0 = ch_ptr[check_word_off]; + check1 = ch_ptr[check_word_off+1]; + mask0 = mask_per_line >> check_bit_pos; + mask1 = 0; + this_check = check0 << check_bit_pos; + /* move indicated bit to MSbit position */ + if((check_bit_pos + bits_per_line) > 32) { + this_check |= (check1 >> (32 - check_bit_pos)); + mask1 = mask_per_line << (32 - check_bit_pos); + } + + ch_ptr[check_word_off] = check0 & ~mask0; + ch_ptr[check_word_off+1] = check1 & ~mask1; + + this_check = this_check & mask_per_line; + old_scan = g_video.g_superhires_scan_save[y]; + use_a2vid_palette = ((scan & 0xf) == (word32)a2vid_palette); + scan = (scan + (a2vid_palette << 8)) & 0xfff; + + ret = video_rebuild_super_hires_palette(scan, y, in_reparse); +#if 0 + if(y == 1) { + printf("y1, ch:%08x, ret:%d, scan:%03x, os:%03x\n", + this_check, ret, scan, old_scan); + } +#endif + if(ret || in_reparse || ((scan ^ old_scan) & 0xa0)) { + /* 0x80 == mode640, 0x20 = fill */ + this_check = -1; + } + + if(this_check == 0) { + continue; + } + + mode_640 = (scan & 0x80); + if(mode_640) { + g_video.g_num_lines_superhires640++; + } + + type = ((scan >> 5) & 1) + (pixel_size_type << 1); + if(type & 1) { + /* fill mode--redraw whole line */ + this_check = -1; + } + + all_checks |= this_check; + + g_video.g_a2_screen_buffer_changed |= line_mask; + + + switch(type) { + case 0: /* nofill, 8 bit pixels */ + redraw_changed_super_hires_oneline_nofill_8( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 1: /* fill, 8 bit pixels */ + redraw_changed_super_hires_oneline_fill_8( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 2: /* nofill, 16 bit pixels */ + redraw_changed_super_hires_oneline_nofill_16( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 3: /* fill, 16 bit pixels */ + redraw_changed_super_hires_oneline_fill_16( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 4: /* nofill, 32 bit pixels */ + redraw_changed_super_hires_oneline_nofill_32( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 5: /* fill, 32 byte pixels */ + redraw_changed_super_hires_oneline_fill_32( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + default: + halt_printf("type: %d bad!\n", type); + break; + } + } + + left = 4*40; + right = 0; + + tmp = all_checks; + if(all_checks) { + for(i = 0; i < 160; i += 8) { + if(tmp & 0x80000000) { + left = MIN(i, left); + right = MAX(i + 8, right); + } + tmp = tmp << 1; + } + } + + for(i = 0; i < num_lines; i++) { + g_video.g_a2_line_left_edge[st_line + i] = 2*VIDEO_HFACTOR*left; + g_video.g_a2_line_right_edge[st_line + i] = 2*VIDEO_HFACTOR*right; + } + +#if 0 + if((g_video.g_a2_screen_buffer_changed & (1 << start_line)) != 0) { + if(((g_video.g_full_refresh_needed & (1 << start_line)) == 0) && + left >= right) { + halt_printf("shr: line: %d, left: %d, right:%d\n", + start_line, left, right); + printf("mask_per_line: %08x, all_checks: %08x\n", + mask_per_line, all_checks); + printf("check0,1 = %08x,%08x\n", check0, check1); + printf("a2_screen_chang: %08x\n", kd_tmp_debug); +#ifdef HPUX + U_STACK_TRACE(); +#endif + } + } +#endif + + g_video.g_need_redraw = 0; +} + +void +display_screen() +{ + + + video_update_through_line(262); +} +//double last_vid_update_dcys; // OG + +void +video_update_event_line(int line) +{ + int new_line; + + video_update_through_line(line); + + new_line = line + g_sim65816.g_line_ref_amt; + if(new_line < 200) { + if(!g_config_control_panel) { + add_event_vid_upd(new_line); + } + } else if(line >= 262) { + video_update_through_line(0); + if(!g_config_control_panel) { + add_event_vid_upd(1); /* add event for new screen */ + } + } + + if(g_video.g_video_extra_check_inputs) { + if(g_video.g_video_dcycs_check_input < g_sim65816.g_cur_dcycs) + { + video_check_input_events(); + } + } +} + +void +video_check_input_events() +{ + word32 start_time, end_time; + + g_video.g_video_dcycs_check_input = g_sim65816.g_cur_dcycs + 4000.0; + + GET_ITIMER(start_time); + extern void should_decrement_fifo(); + should_decrement_fifo(); + check_input_events(); + GET_ITIMER(end_time); + + g_video.g_cycs_in_check_input += (end_time - start_time); +} + +void +video_update_through_line(int line) +{ + register word32 start_time; + register word32 end_time; + int *mode_ptr; + word32 mask; + int last_line, num_lines; + int must_reparse; + int new_all_stat, prev_all_stat; + int new_stat, prev_stat; + int i; + +#if 0 + vid_printf("\nvideo_upd for line %d, lines: %06x\n", line, + get_lines_since_vbl(g_cur_dcycs)); +#endif + + GET_ITIMER(start_time); + + video_update_all_stat_through_line(line); + + i = g_video.g_vid_update_last_line; + + last_line = MIN(200, line+1); /* go through line, but not past 200 */ + + prev_stat = -2; + prev_all_stat = -2; + num_lines = 0; + must_reparse = 0; + for(i = g_video.g_vid_update_last_line; i < last_line; i++) { + new_all_stat = g_video.g_a2_new_all_stat[i]; + if(new_all_stat != g_video.g_a2_cur_all_stat[i]) { + /* regen line_stat for this line */ + g_video.g_a2_cur_all_stat[i] = new_all_stat; + if(new_all_stat == prev_all_stat) { + /* save a lookup */ + new_stat = prev_stat; + } else { + new_stat = video_all_stat_to_line_stat(i, + new_all_stat); + } + if(new_stat != g_video.g_a2_line_stat[i]) { + /* status changed */ + g_video.g_a2_line_stat[i] = new_stat; + mode_ptr = video_update_kimage_ptr(i, new_stat); + if(mode_ptr[i] != new_stat) { + must_reparse = 1; + mode_ptr[i] = new_stat; + } + mask = 1 << (line >> 3); + g_video.g_full_refresh_needed |= mask; + g_video.g_a2_screen_buffer_changed |= mask; + } + } + + new_stat = g_video.g_a2_line_stat[i]; + + if( ((new_stat == prev_stat) && ((i & 7) != 0)) || + (num_lines == 0) ) { + /* merge prev and this together */ + prev_stat = new_stat; + num_lines++; + continue; + } + + /* else, we must call refresh */ + video_refresh_lines(i - num_lines, num_lines, must_reparse); + num_lines = 1; + prev_all_stat = -1; + prev_stat = new_stat; + must_reparse = 0; + } + + if(num_lines > 0) { + + video_refresh_lines(i - num_lines, num_lines, must_reparse); + } + + g_video.g_vid_update_last_line = last_line; + + /* deal with border */ + if(line >= 262) { + if(g_video.g_num_lines_prev_superhires != g_video.g_num_lines_superhires) { + /* switched in/out from superhires--refresh borders */ + g_video.g_border_sides_refresh_needed = 1; + } + refresh_border(); + + if(g_video.g_status_refresh_needed) { + g_video.g_status_refresh_needed = 0; + x_redraw_status_lines(); + } + } + GET_ITIMER(end_time); + + g_video.g_cycs_in_refresh_line += (end_time - start_time); + + if(line >= 262) { + GET_ITIMER(start_time); + if(g_video.g_palette_change_summary) { + g_video.g_palette_change_summary = 0; + video_update_colormap(); + } + + video_push_kimages(); + GET_ITIMER(end_time); + g_video.g_cycs_in_refresh_ximage += (end_time - start_time); + + g_video.g_num_lines_prev_superhires = g_video.g_num_lines_superhires; + g_video.g_num_lines_prev_superhires640 = g_video.g_num_lines_superhires640; + g_video.g_num_lines_superhires = 0; + g_video.g_num_lines_superhires640 = 0; + } +} + +void +video_refresh_lines(int st_line, int num_lines, int must_reparse) +{ + byte *ptr; + int line; + int stat; + int mode; + int dbl, page, color; + int altchar, bg_color, text_color; + int pixels_per_line; + int i; + + vid_printf("video_refresh_lines %d %d\n",st_line,num_lines); + + line = st_line; + + /* do some basic checking, num_lines should be 1-8, and */ + /* st_line+num_lines-1 cannot roll over 8 */ + if((num_lines < 1) || (num_lines > 8) || + (((st_line & 7) + num_lines) > 8) ) { + halt_printf("video_refresh_lines called with %d, %d\n", + st_line, num_lines); + return; + } + + stat = g_video.g_a2_line_stat[line]; + ptr = g_video.g_a2_line_kimage[line]->data_ptr; + pixels_per_line = g_video.g_a2_line_kimage[line]->width_act; + + /* do not zero g_a2_line_left/right_edge here since text/gr routs */ + /* need to leave stale values around for drawing to work correctly */ + /* all routs force in new left/right when there are screen changes */ + + dbl = stat & 1; + color = (stat >> 1) & 1; + page = (stat >> 2) & 1; + mode = (stat >> 4) & 7; + +#if 0 + printf("refresh line: %d, stat: %04x\n", line, stat); +#endif + + switch(mode) { + case MODE_TEXT: + vid_printf("refresh line: %d, stat: %04x\n", line, stat); + altchar = (stat >> 7) & 1; + bg_color = (stat >> 8) & 0xf; + text_color = (stat >> 12) & 0xf; + if(dbl) { + redraw_changed_text_80(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, altchar, bg_color, + text_color, pixels_per_line); + } else { + redraw_changed_text_40(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, altchar, bg_color, + text_color, pixels_per_line); + } + break; + case MODE_GR: + if(dbl) { + redraw_changed_dbl_gr(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, pixels_per_line); + } else { + redraw_changed_gr(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, pixels_per_line); + } + break; + case MODE_HGR: + if(dbl) { + redraw_changed_dbl_hires(0x000 + page*0x2000, st_line, + num_lines, color, must_reparse, ptr, + pixels_per_line); + } else { + redraw_changed_hires(0x000 + page*0x2000, st_line, + num_lines, color, must_reparse, ptr, + pixels_per_line); + } + break; + case MODE_SUPER_HIRES: + g_video.g_num_lines_superhires++; + redraw_changed_super_hires(0, st_line, num_lines, + must_reparse, ptr); + break; + case MODE_BORDER: + if(line < 192) { + halt_printf("Border line not 192: %d\n", line); + } + for(i = 0; i < num_lines; i++) { + g_video.g_a2_line_left_edge[line + i] = 0; + g_video.g_a2_line_right_edge[line + i] = 320*VIDEO_HFACTOR; + } + if(g_video.g_border_line24_refresh_needed) { + g_video.g_border_line24_refresh_needed = 0; + g_video.g_a2_screen_buffer_changed |= (1 << 24); + } + break; + default: + halt_printf("refresh screen: mode: 0x%02x unknown!\n", mode); + x_exit(7); + break; + } +} + +void +refresh_border() +{ + /**ZZZZ***/ +} + +// OG Added video_release_kimages proto +void video_release_kimages(); + +void +end_screen() +{ + printf("In end_screen\n"); + + // OG Free up allocated images + video_release_kimages(); + x_video_shut(); +} + +byte g_font_array[256][8] = { +#include "kegsfont.h" +}; + +void +read_a2_font() +{ + byte *f40_e_ptr; + byte *f40_o_ptr; + byte *f80_0_ptr, *f80_1_ptr, *f80_2_ptr, *f80_3_ptr; + int char_num; + int j, k; + int val0; + int mask; + int pix; + + for(char_num = 0; char_num < 0x100; char_num++) { + for(j = 0; j < 8; j++) { + val0 = g_font_array[char_num][j]; + + mask = 0x80; + + for(k = 0; k < 3; k++) { + g_font80_off0_bits[char_num][j][k] = 0; + g_font80_off1_bits[char_num][j][k] = 0; + g_font80_off2_bits[char_num][j][k] = 0; + g_font80_off3_bits[char_num][j][k] = 0; + g_font40_even_bits[char_num][j][k] = 0; + g_font40_odd_bits[char_num][j][k] = 0; + } + g_font40_even_bits[char_num][j][3] = 0; + g_font40_odd_bits[char_num][j][3] = 0; + + f40_e_ptr = (byte *)&g_font40_even_bits[char_num][j][0]; + f40_o_ptr = (byte *)&g_font40_odd_bits[char_num][j][0]; + + f80_0_ptr = (byte *)&g_font80_off0_bits[char_num][j][0]; + f80_1_ptr = (byte *)&g_font80_off1_bits[char_num][j][0]; + f80_2_ptr = (byte *)&g_font80_off2_bits[char_num][j][0]; + f80_3_ptr = (byte *)&g_font80_off3_bits[char_num][j][0]; + + for(k = 0; k < 7; k++) { + pix = 0; + if(val0 & mask) { + pix = 0xf; + } + + f40_e_ptr[2*k] = pix; + f40_e_ptr[2*k+1] = pix; + + f40_o_ptr[2*k+2] = pix; + f40_o_ptr[2*k+3] = pix; + + f80_0_ptr[k] = pix; + f80_1_ptr[k+1] = pix; + f80_2_ptr[k+2] = pix; + f80_3_ptr[k+3] = pix; + + mask = mask >> 1; + } + } + } +} + + +/* Helper routine for the *driver.c files */ + +void init_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth) +{ + int width = A2_WINDOW_WIDTH; + int height = A2_WINDOW_HEIGHT; + if(extend_info & 1) { + /* Border at top and bottom of screen */ + width = X_A2_WINDOW_WIDTH; + height = X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8; + } + if(extend_info & 2) { + /* Border at sides of screen */ + width = BORDER_WIDTH + EFF_BORDER_WIDTH; + height = A2_WINDOW_HEIGHT; + } + + memset(kimage_ptr,0,sizeof(Kimage)); + + kimage_ptr->width_req = width; + kimage_ptr->width_act = width; + kimage_ptr->height = height; + kimage_ptr->depth = depth; + kimage_ptr->mdepth = mdepth; + +} + +void video_get_kimage(Kimage *kimage_ptr, int extend_info, int _depth, int _mdepth) +{ + init_kimage(kimage_ptr,extend_info,_depth,_mdepth); + + byte *ptr; + + int width = kimage_ptr->width_req; + int height = kimage_ptr->height; + //int depth = kimage_ptr->depth; + int mdepth = kimage_ptr->mdepth; + + kimage_ptr->data_size = (width*height*mdepth) >> 3; + ptr = (byte *)malloc(kimage_ptr->data_size); + + if(ptr == 0) { + printf("malloc for data failed, mdepth: %d\n", mdepth); + x_exit(2); + } + + kimage_ptr->data_ptr = ptr; + kimage_ptr->dev_handle = (void *)-1; +} + + +void +video_get_kimages() +{ + video_get_kimage(&s_video.g_kimage_border_special2, 0, 8, 8); + video_get_kimage(&s_video.g_kimage_text[0], 0, 8, 8); + video_get_kimage(&s_video.g_kimage_text[1], 0, 8, 8); + video_get_kimage(&s_video.g_kimage_hires[0], 0, 8, 8); + video_get_kimage(&s_video.g_kimage_hires[1], 0, 8, 8); + video_get_kimage(&s_video.g_kimage_superhires, 0, s_video.g_screen_depth, + s_video.g_screen_mdepth); + video_get_kimage(&s_video.g_kimage_border_special, 1, s_video.g_screen_depth, + s_video.g_screen_mdepth); + video_get_kimage(&s_video.g_kimage_border_sides, 2, s_video.g_screen_depth, + s_video.g_screen_mdepth); +} + +// OG Added video_release_kimages (to match video_get_kimages) +void video_release_kimages() +{ + extern void x_release_kimage(Kimage *kimage_ptr); + + x_release_kimage(&s_video.g_kimage_border_special2); + x_release_kimage(&s_video.g_kimage_text[0]); + x_release_kimage(&s_video.g_kimage_text[1]); + x_release_kimage(&s_video.g_kimage_hires[0]); + x_release_kimage(&s_video.g_kimage_hires[1]); + x_release_kimage(&s_video.g_kimage_superhires); + x_release_kimage(&s_video.g_kimage_border_special); + x_release_kimage(&s_video.g_kimage_border_sides); +} + + +void +video_convert_kimage_depth(Kimage *kim_in, Kimage *kim_out, int startx, + int starty, int width, int height) +{ + byte *indata, *inptr; + word32 *outdata32, *outptr32; + word16 *outdata16, *outptr16; + word32 *palptr; + int out_width, in_width; + int x, y; + + indata = (byte *)kim_in->data_ptr; + outdata32 = (word32 *)kim_out->data_ptr; + outdata16 = (word16 *)kim_out->data_ptr; + + // OG added safe check (to investigate further) + if (!outdata32) + { + printf("video_convert_kimage_depth: kim_out* not yet initialized\n"); + return ; + } + + if(kim_in == &s_video.g_kimage_superhires) { + palptr = &(g_palette_8to1624[0]); + } else { + palptr = &(g_a2palette_8to1624[0]); + } + if(kim_in->depth != 8) { + printf("x_convert_kimage_depth from non-8 bit depth: %p\n", + kim_in); + x_exit(1); + } + + out_width = kim_out->width_act; + in_width = kim_in->width_act; + indata += (starty * in_width + startx); + outdata32 += (starty * out_width + startx); + outdata16 += (starty * out_width + startx); + if(kim_out->mdepth == 16) { + for(y = 0; y < height; y++) { + outptr16 = outdata16; + inptr = indata; + for(x = 0; x < width; x++) { + *outptr16++ = palptr[*inptr++]; + } + outdata16 += out_width; + indata += in_width; + } + } else { + /* 32-bit depth */ + for(y = 0; y < height; y++) { + outptr32 = outdata32; + inptr = indata; + for(x = 0; x < width; x++) { + *outptr32++ = palptr[*inptr++]; + } + outdata32 += out_width; + indata += in_width; + } + } +} + +void +video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix, + int right_pix) +{ + int mdepth_mismatch; + int srcy; + int center = 0; // OG added variable to center screen + + //OG add null pointer check when emulator is restarted + if (!kimage_ptr) + { + printf("warning : video_push_lines(kimage_ptr=null)\n"); + return ; + } + + if(left_pix >= right_pix || left_pix < 0 || right_pix <= 0) { + halt_printf("video_push_lines: lines %d to %d, pix %d to %d\n", + start_line, end_line, left_pix, right_pix); + printf("a2_screen_buf_ch:%08x, g_full_refr:%08x\n", + g_video.g_a2_screen_buffer_changed, g_video.g_full_refresh_needed); + } + + srcy = VIDEO_VFACTOR*start_line; + + mdepth_mismatch = (kimage_ptr->mdepth != s_video.g_screen_mdepth); + if(mdepth_mismatch) { + /* translate from 8-bit pseudo to correct visual */ + video_convert_kimage_depth(kimage_ptr, &s_video.g_mainwin_kimage, + left_pix, srcy, (right_pix - left_pix), + VIDEO_VFACTOR*(end_line - start_line)); + kimage_ptr = &s_video.g_mainwin_kimage; + } + g_refresh_bytes_xfer += VIDEO_VFACTOR*(end_line - start_line) *(right_pix - left_pix); + + // OG Calculating new center + if (g_video.g_cur_a2_stat & ALL_STAT_SUPER_HIRES) + center=0; + else + center=EFF_BORDER_WIDTH - BORDER_WIDTH; + + // OG shifting image to the center + x_push_kimage(kimage_ptr, g_video_act_margin_left + left_pix + center, + g_video_act_margin_top + srcy, left_pix, srcy, + (right_pix - left_pix), VIDEO_VFACTOR*(end_line - start_line)); +} + +void +video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line, + int end_line) +{ + + Kimage *kimage_ptr; + int srcy; + + if(start_line < 0 || width < 0) { + return; + } + +#if 0 + printf("push_border_sides lines:%d-%d from %d to %d\n", + start_line, end_line, end_x - width, end_x); +#endif + kimage_ptr = &s_video.g_kimage_border_sides; + g_refresh_bytes_xfer += VIDEO_VFACTOR * (end_line - start_line) * width; + + srcy = VIDEO_VFACTOR * start_line; + + // Adjust dext_x to accound for changed margins + dest_x = dest_x + g_video_act_margin_left - BASE_MARGIN_LEFT; + if(dest_x < BASE_MARGIN_LEFT) { + src_x = src_x + g_video_act_margin_left - BASE_MARGIN_LEFT; + // Don't adjust src_x if doing right border + } + if(dest_x < 0) { + width = width + dest_x; + src_x = src_x - dest_x; + dest_x = 0; + } + if(src_x < 0) { + width = width + src_x; + dest_x = dest_x - src_x; + src_x = 0; + } + if(dest_x + width > g_video_act_width) { + width = g_video_act_width - dest_x; + } + if(width > 0) { + x_push_kimage(kimage_ptr, dest_x, g_video_act_margin_top + srcy, + src_x, srcy, width, VIDEO_VFACTOR*(end_line - start_line)); + } +} + +void +video_push_border_sides() +{ + int old_width; + int prev_line; + int width; + int mode; + int i; + +#if 0 + printf("refresh border sides!\n"); +#endif + + /* redraw left sides */ + // OG Left side can alos be "jagged" as a2 screen is now being centered + + //video_push_border_sides_lines(0, 0, BORDER_WIDTH, 0, 200); + + prev_line = -1; + old_width = -1; + for(i = 0; i < 200; i++) { + mode = (g_video.g_a2_line_stat[i] >> 4) & 7; + width = EFF_BORDER_WIDTH; + if(mode == MODE_SUPER_HIRES) { + width = BORDER_WIDTH; + } + if(width != old_width) { + video_push_border_sides_lines(BORDER_WIDTH, + 0, old_width, + prev_line, i); + prev_line = i; + old_width = width; + } + } + video_push_border_sides_lines(0/*BORDER_WIDTH*/, + 0, old_width, prev_line, 200); + + + /* right side--can be "jagged" */ + prev_line = -1; + old_width = -1; + for(i = 0; i < 200; i++) { + mode = (g_video.g_a2_line_stat[i] >> 4) & 7; + width = EFF_BORDER_WIDTH; + if(mode == MODE_SUPER_HIRES) { + width = BORDER_WIDTH; + } + if(width != old_width) { + video_push_border_sides_lines(BORDER_WIDTH, + X_A2_WINDOW_WIDTH - old_width, old_width, + prev_line, i); + prev_line = i; + old_width = width; + } + } + + + video_push_border_sides_lines(0/*BORDER_WIDTH*/, + X_A2_WINDOW_WIDTH - old_width, old_width, prev_line, 200); +} + +void +video_push_border_special() +{ + + Kimage *kimage_ptr; + int width, height; + int src_x, src_y; + int dest_x, dest_y; + + kimage_ptr = &s_video.g_kimage_border_special; + width = g_video_act_width; + g_refresh_bytes_xfer += width * (BASE_MARGIN_TOP + BASE_MARGIN_BOTTOM); + + // First do bottom border: dest_x from 0 to 640+MARGIN_LEFT+MARGIN_RIGHT + // and dest_y of BASE_MARGIN_BOTTOM starting at TOP+A2_HEIGHT + // src_x is dest_x, and src_y is 0. + dest_y = g_video_act_margin_top + A2_WINDOW_HEIGHT; + height = g_video_act_margin_bottom; + src_y = BASE_MARGIN_BOTTOM - height; + + dest_x = 0; + src_x = BASE_MARGIN_LEFT - g_video_act_margin_left; + + if(width > 0 && height > 0) { + x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y, + width, height); + } + + // Then fix top border: dest_x from 0 to 640+LEFT+RIGHT and + // dest_y from 0 to TOP. src_x is dest_x, but src_y is + // BOTTOM to BOTTOM+TOP + // Just use src_x and dest_x from earlier. + height = g_video_act_margin_top; + dest_y = 0; + src_y = BASE_MARGIN_BOTTOM; + if(width > 0 && height > 0) { + x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y, + width, height); + } +} + +// OG Added window ratio support +extern int x_calc_ratio(float&,float&); + +void +video_push_kimages() +{ + register word32 start_time; + register word32 end_time; + Kimage *last_kim, *cur_kim; + word32 mask; + int start; + int line; + int left_pix, right_pix; + int left, right; + int line_div8; + + if(g_video.g_border_sides_refresh_needed) { + g_video.g_border_sides_refresh_needed = 0; + video_push_border_sides(); + } + if(g_video.g_border_special_refresh_needed) { + g_video.g_border_special_refresh_needed = 0; + video_push_border_special(); + } + + if(g_video.g_a2_screen_buffer_changed == 0) { + return; + } + + GET_ITIMER(start_time); + + float ratiox,ratioy; + + if (x_calc_ratio(ratiox,ratioy)) + { + line = 0; + while (1) + { + start = line; + cur_kim = g_video.g_a2_line_kimage[line]; + while(line < 200 && g_video.g_a2_line_kimage[line] == cur_kim) line++; + if (cur_kim == &s_video.g_kimage_superhires ||cur_kim == &s_video.g_kimage_border_special2 ) + right = cur_kim->width_act/2*VIDEO_HFACTOR; + else + right = 560/2*VIDEO_HFACTOR; + + video_push_lines(cur_kim, start, line,0,right); + if (line==200) break; + } + + } + else + { + start = -1; + last_kim = (Kimage *)-1; + cur_kim = (Kimage *)0; + + left_pix = 640/2*VIDEO_HFACTOR; + right_pix = 0; + + for(line = 0; line < 200; line++) { + line_div8 = line >> 3; + mask = 1 << (line_div8); + cur_kim = g_video.g_a2_line_kimage[line]; + if((g_video.g_full_refresh_needed & mask) != 0) + { + left = 0; + + if (cur_kim == &s_video.g_kimage_superhires ||cur_kim == &s_video.g_kimage_border_special2 ) + right = cur_kim->width_act/2*VIDEO_HFACTOR; + else + right = 560/2*VIDEO_HFACTOR; + } + else + { + left = g_video.g_a2_line_left_edge[line]; + right = g_video.g_a2_line_right_edge[line]; + } + + if(!(g_video.g_a2_screen_buffer_changed & mask) || (left > right)) { + /* No need to update this line */ + /* Refresh previous chunks of lines, if any */ + if(start >= 0) { + video_push_lines(last_kim, start, line, + left_pix, right_pix); + start = -1; + left_pix = 640/2*VIDEO_HFACTOR; + right_pix = 0; + } + } else { + /* Need to update this line */ + if(start < 0) { + start = line; + last_kim = cur_kim; + } + if(cur_kim != last_kim) { + /* do the refresh */ + video_push_lines(last_kim, start, line, + left_pix, right_pix); + last_kim = cur_kim; + start = line; + left_pix = left; + right_pix = right; + } + left_pix = MIN(left, left_pix); + right_pix = MAX(right, right_pix); + } + } + + if(start >= 0) { + video_push_lines(last_kim, start, 200, left_pix, right_pix); + } + } + + g_video.g_a2_screen_buffer_changed = 0; + g_video.g_full_refresh_needed = 0; + +// refresh_video(0); + // x_push_done(); + + GET_ITIMER(end_time); + + g_video.g_cycs_in_xredraw += (end_time - start_time); +} + +void video_update_palette_color() +{ + for(int i = 0; i < 256; i++) + { + int lores_col = g_lores_colors[i & 0xf]; + video_update_color_raw(i, lores_col); + g_a2palette_8to1624[i] = g_palette_8to1624[i]; + } +} + +void +video_update_color_raw(int col_num, int a2_color) +{ + word32 tmp; + int red, green, blue; + int newred, newgreen, newblue; + + red = (a2_color >> 8) & 0xf; + green = (a2_color >> 4) & 0xf; + blue = (a2_color) & 0xf; + red = ((red << 4) + red); + green = ((green << 4) + green); + blue = ((blue << 4) + blue); + + float gray = (float)red*0.3f + (float)green*0.59f+ (float)blue*0.11f ; + + int cm = r_sim65816.get_color_mode(); + + switch(cm) + { + case COLORMODE_BW: + case COLORMODE_MONO: + green = (int)gray ; + red = (int)gray ; + blue = (int)gray; + break; + case COLORMODE_AMBER: + // It is a color that is 75% yellow (R+G) and 25% red. = 1R + green = (int) ( gray ); + blue = 0; + red = (int) ( gray ); + break; + case COLORMODE_GREEN: + green = (int)gray; + blue = 0; + red = 0; + break; + default: + break; + } + + newred = red >> s_video.g_red_right_shift; + newgreen = green >> s_video.g_green_right_shift; + newblue = blue >> s_video.g_blue_right_shift; + + tmp = ((newred & s_video.g_red_mask) << s_video.g_red_left_shift) + + ((newgreen & s_video.g_green_mask) << s_video.g_green_left_shift) + + ((newblue & s_video.g_blue_mask) << s_video.g_blue_left_shift); + + + + g_palette_8to1624[col_num] = tmp; + + x_update_color(col_num, red, green, blue, tmp); +} + +void +video_update_color_array(int col_num, int a2_color) +{ + int palette; + int full; + + if(col_num >= 256 || col_num < 0) { + halt_printf("video_update_color_array: col: %03x\n", col_num); + return; + } + + full = s_video.g_installed_full_superhires_colormap; + + palette = col_num >> 4; + if(!full && palette == g_video.g_a2vid_palette) { + return; + } + +#if 0 + if(s_video.g_screen_depth != 8) { + /* redraw whole superhires for now */ + g_video.g_full_refresh_needed = -1; + } +#endif + + video_update_color_raw(col_num, a2_color); +} + +void +video_update_colormap() +{ + int palette; + int full; + int i; + + full = s_video.g_installed_full_superhires_colormap; + + if(!full) { + palette = g_video.g_a2vid_palette << 4; + for(i = 0; i < 16; i++) { + video_update_color_raw(palette + i, g_lores_colors[i]); + } + x_update_physical_colormap(); + } +} + +void +video_update_status_line(int line, const char *string) +{ + char *buf; + const char *ptr; + int i; + + if(line >= MAX_STATUS_LINES || line < 0) { + printf("update_status_line: line: %d!\n", line); + x_exit(1); + } + + ptr = string; + buf = &(g_status_buf[line][0]); + g_status_ptrs[line] = buf; + for(i = 0; i < STATUS_LINE_LENGTH; i++) { + if(*ptr) { + buf[i] = *ptr++; + } else { + buf[i] = ' '; + } + } + + buf[STATUS_LINE_LENGTH] = 0; +} + +void +video_show_debug_info() +{ + word32 tmp1; + + printf("g_cur_dcycs: %f, last_vbl: %f\n", g_sim65816.g_cur_dcycs, + g_sim65816.g_last_vbl_dcycs); + tmp1 = get_lines_since_vbl(g_sim65816.g_cur_dcycs); + printf("lines since vbl: %06x\n", tmp1); + printf("Last line updated: %d\n", g_video.g_vid_update_last_line); +} + +word32 +float_bus(double dcycs) +{ + word32 val; + int lines_since_vbl; + int line, eff_line, line24; + int all_stat; + int byte_offset; + int hires, page2; + int addr; + + lines_since_vbl = get_lines_since_vbl(dcycs); + +/* For floating bus, model hires style: Visible lines 0-191 are simply the */ +/* data being displayed at that time. Lines 192-255 are lines 0 - 63 again */ +/* and lines 256-261 are lines 58-63 again */ +/* For each line, figure out starting byte at -25 mod 128 bytes from this */ +/* line's start */ +/* This emulates an Apple II style floating bus. A reall IIgs does not */ +/* drive anything meaningful during the 25 horizontal blanking lines, */ +/* nor during veritical blanking. The data seems to be 0 or related to */ +/* the instruction fetches on a real IIgs during blankings */ + + line = lines_since_vbl >> 8; + byte_offset = lines_since_vbl & 0xff; + /* byte offset is from 0 to 65, where the visible screen is drawn */ + /* from 25 to 65 */ + + eff_line = line; + if(line >= 192) { + eff_line = line - 192; + if(line >= 256) { + eff_line = line - 262 + 64; + } + } + all_stat = g_video.g_cur_a2_stat; + hires = all_stat & ALL_STAT_HIRES; + if((all_stat & ALL_STAT_MIX_T_GR) && (line >= 160)) { + hires = 0; + } + page2 = EXTRU(all_stat, 31 - BIT_ALL_STAT_PAGE2, 1); + if(all_stat & ALL_STAT_ST80) { + page2 = 0; + } + + line24 = (eff_line >> 3) & 0x1f; + addr = g_screen_index[line24] & 0x3ff; + addr = (addr & 0x380) + (((addr & 0x7f) - 25 + byte_offset) & 0x7f); + if(hires) { + addr = 0x2000 + addr + ((eff_line & 7) << 10) + (page2 << 13); + } else { + addr = 0x400 + addr + (page2 << 10); + } + + val = g_slow_memory_ptr[addr]; + if(byte_offset < 10) { + /* Bob Bishop's sample program seems to get confused by */ + /* these bytes--so mask some off to prevent seeing some */ + val = 0; + } +#if 0 + printf("For %04x (%d) addr=%04x, val=%02x, dcycs:%9.2f\n", + lines_since_vbl, eff_line, addr, val, dcycs - g_last_vbl_dcycs); +#endif + return val; +} + +void refresh_video(int _force) +{ + + if (!r_sim65816.is_emulator_offscreen_available() || r_sim65816.should_emulator_terminate()) + { + printf("refresh_video cancelled : offscreen not available\n"); + return ; + } + + addFrameRate(3); + + + if (_force || g_video_offscreen_has_been_modified ) + { + + addFrameRate(1); + + // pour avoir une synchro vbl + g_video_offscreen_has_been_modified = 1; + +#ifdef ENABLE_GRAPH + static double lastvbl=0.0; + double d = get_dtime(); + double delay = 1/(d - lastvbl); + lastvbl = d; + g_graph.add_graph(0,(float)delay,g_sim65816.g_vbl_count); + +#endif + + x_refresh_video(); + } + +} + +void SET_LINES() +{ + for(int i=0;i<200;i++) + { + Kimage* p = g_video.g_a2_line_kimage[i]; + if (p==(Kimage*)1) + p =&s_video.g_kimage_text[0]; + else + if (p==(Kimage*)2) + p =&s_video.g_kimage_text[1]; + else + if (p==(Kimage*)3) + p =&s_video.g_kimage_hires[0]; + else + if (p==(Kimage*)4 ) + p =&s_video.g_kimage_hires[1]; + else + if (p==(Kimage*)5) + p =&s_video.g_kimage_superhires; + else + if (p==(Kimage*)6) + p =&s_video.g_kimage_border_special; + else + if (p==(Kimage*)7) + p =&s_video.g_kimage_border_special2; + else + if (p==(Kimage*)8) + p =&s_video.g_kimage_border_sides; + else + if (p==(Kimage*)9) + p =&s_video.g_mainwin_kimage; + else + { + // to fix + p =&s_video.g_kimage_superhires; + } + g_video.g_a2_line_kimage[i]=p; + } +} +void RESET_LINES() +{ + for(int i=0;i<200;i++) + { + Kimage* p = g_video.g_a2_line_kimage[i]; + if (p==&s_video.g_kimage_text[0]) + p =(Kimage*)1; + else + if (p==&s_video.g_kimage_text[1]) + p =(Kimage*)2; + else + if (p==&s_video.g_kimage_hires[0]) + p =(Kimage*)3; + else + if (p==&s_video.g_kimage_hires[1]) + p =(Kimage*)4; + else + if (p==&s_video.g_kimage_superhires) + p =(Kimage*)5; + else + if (p==&s_video.g_kimage_border_special) + p =(Kimage*)6; + else + if (p==&s_video.g_kimage_border_special2) + p =(Kimage*)7; + else + if (p==&s_video.g_kimage_border_sides) + p =(Kimage*)8; + else + if (p==&s_video.g_mainwin_kimage) + p =(Kimage*)9; + else + { + // to fix + p=(Kimage*)5; + } + g_video.g_a2_line_kimage[i]=p; + } +} + + +#define NBSECSAMPLING 2.0f +int fpsNbFrames[NBFPSTIMER]; +double fpsLastSecond[NBFPSTIMER]; +int fpsValues[NBFPSTIMER]; + +void addFrameRate(int _id) +{ + + double timer = get_dtime(); + double delay = timer - fpsLastSecond[_id]; + if (delay>NBSECSAMPLING) + { + fpsValues[_id] = (int)((float)(fpsNbFrames[_id]*10.0)/NBSECSAMPLING); + fpsNbFrames[_id]=0; + fpsLastSecond[_id]=timer; + } + fpsNbFrames[_id]++; +// printf("%d-",_id); +} + +int getFrameRate(int _id) +{ + return fpsValues[_id]; +} diff --git a/kegs/Src/video.h b/kegs/Src/video.h new file mode 100644 index 0000000..79c119c --- /dev/null +++ b/kegs/Src/video.h @@ -0,0 +1,295 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +extern void RESET_LINES(); +extern void SET_LINES(); + +#define MAX_BORDER_CHANGES 16384 + +#ifdef _WIN32 +#pragma pack(push,PRAGMA_PACK_SIZE) +#endif + +STRUCT(Border_changes) +{ + float fcycs; + int val; +} XCODE_PRAGMA_PACK;; + + +class sd_video : public serialized +{ +public: + int g_a2_line_stat[200]; + int g_a2_line_left_edge[200]; + int g_a2_line_right_edge[200]; + Kimage *g_a2_line_kimage[200]; + + int g_mode_text[2][200]; + int g_mode_hires[2][200]; + int g_mode_superhires[200]; + int g_mode_border[200]; + + byte g_cur_border_colors[270]; + byte g_new_special_border[64][64]; + byte g_cur_special_border[64][64]; + + word32 g_a2_screen_buffer_changed ; + word32 g_full_refresh_needed; + + word32 g_cycs_in_40col; + word32 g_cycs_in_xredraw ; + + + + + word32 g_superhires_scan_save[256]; + + double g_video_dcycs_check_input ; + int g_video_extra_check_inputs ; + + /* + int g_video_act_margin_left; + int g_video_act_margin_right; + int g_video_act_margin_top; + int g_video_act_margin_bottom ; + int g_video_act_width; + int g_video_act_height ; + */ + int g_need_redraw ; + int g_palette_change_summary ; + word32 g_palette_change_cnt[16]; + int g_border_sides_refresh_needed ; + int g_border_special_refresh_needed ; + int g_border_line24_refresh_needed ; + int g_status_refresh_needed ; + + int g_vbl_border_color ; + int g_border_last_vbl_changes ; + + int g_use_dhr140; + + int g_a2_new_all_stat[200]; + int g_a2_cur_all_stat[200]; + int g_new_a2_stat_cur_line ; + int g_vid_update_last_line ; + + + + int g_cur_a2_stat ; + + int g_a2vid_palette ; + + int Max_color_size ; + + + + int g_saved_a2vid_palette ; + word32 g_a2vid_palette_remap[16]; + + word32 g_cycs_in_refresh_line ; + word32 g_cycs_in_refresh_ximage ; + + int g_num_lines_superhires ; + int g_num_lines_superhires640; + int g_num_lines_prev_superhires ; + int g_num_lines_prev_superhires640 ; + + int g_flash_count ; + + int g_screen_redraw_skip_count ; + int g_screen_redraw_skip_amt ; + + word32 g_cycs_in_check_input ; + + int g_needfullrefreshfornextframe ; + + int g_num_a2vid_palette_checks ; + int g_shr_palette_used[16]; + + int g_border_color; + + Border_changes g_border_changes[MAX_BORDER_CHANGES]; + int g_num_border_changes; + + +#define RESET_KIMAGE(X,N) byte* old_##N = X.data_ptr; X.data_ptr=NULL; +#define SET_KIMAGE(X,N) X.data_ptr = old_##N ; + + +#define RESET_KIMAGES \ + RESET_KIMAGE(g_kimage_text[0],g_kimage_text0); \ + RESET_KIMAGE(g_kimage_text[1],g_kimage_text1); \ + RESET_KIMAGE(g_kimage_hires[0],g_kimage_hires0); \ + RESET_KIMAGE(g_kimage_hires[1],g_kimage_hires1); \ + RESET_KIMAGE(g_kimage_superhires,g_kimage_superhires); \ + RESET_KIMAGE(g_kimage_border_special,g_kimage_border_special); \ + RESET_KIMAGE(g_kimage_border_special2,g_kimage_border_special2); \ + RESET_KIMAGE(g_kimage_border_sides,g_kimage_border_sides); \ + RESET_KIMAGE(g_mainwin_kimage,g_mainwin_kimage); + + + +#define SET_KIMAGES \ + SET_KIMAGE(g_kimage_text[0],g_kimage_text0); \ + SET_KIMAGE(g_kimage_text[1],g_kimage_text1); \ + SET_KIMAGE(g_kimage_hires[0],g_kimage_hires0); \ + SET_KIMAGE(g_kimage_hires[1],g_kimage_hires1); \ + SET_KIMAGE(g_kimage_superhires,g_kimage_superhires); \ + SET_KIMAGE(g_kimage_border_special,g_kimage_border_special); \ + SET_KIMAGE(g_kimage_border_special2,g_kimage_border_special2); \ + SET_KIMAGE(g_kimage_border_sides,g_kimage_border_sides); \ + SET_KIMAGE(g_mainwin_kimage,g_mainwin_kimage); + + + + sd_video() + { + INIT_SERIALIZED(); + + g_video_extra_check_inputs=1; + + g_a2_screen_buffer_changed = (word32)-1; + g_full_refresh_needed = (word32)-1; +/* + g_video_act_margin_left = BASE_MARGIN_LEFT; + g_video_act_margin_right = BASE_MARGIN_RIGHT; + g_video_act_margin_top = BASE_MARGIN_TOP; + g_video_act_margin_bottom = BASE_MARGIN_BOTTOM; + g_video_act_width = X_A2_WINDOW_WIDTH; + g_video_act_height = X_A2_WINDOW_HEIGHT; +*/ + g_need_redraw = 1; + + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; + g_border_line24_refresh_needed = 1; + g_status_refresh_needed = 1; + + g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 | (0xf << BIT_ALL_STAT_TEXT_COLOR); + g_a2vid_palette = 0xe; + Max_color_size = 256; + g_saved_a2vid_palette = -1; + + g_screen_redraw_skip_amt = -1; + g_needfullrefreshfornextframe = 1 ; + g_num_a2vid_palette_checks = 1; + } + + void in(serialize* _s) + { + + RESET_LINES(); + + byte* ptr = (byte*)_s->data; + + int ssize = *(int*)ptr; + if (ssize!=sizeof(*this)) + x_fatal_exit("alignment mismatch"); + ptr+=sizeof(ssize); + memcpy(this,ptr,sizeof(*this)); + + SET_LINES(); + g_needfullrefreshfornextframe = 1 ; + + } + + int out(serialize* _s, int _fastalloc) + { + int ssize= sizeof(*this); + int size = ssize + sizeof(ssize); + _s->size = size; + _s->fastalloc = _fastalloc; + _s->data = (void*)x_malloc(size,_fastalloc); + + RESET_LINES(); + byte* ptr = (byte*)_s->data; + + memcpy(ptr,&ssize,sizeof(ssize)); + ptr+=sizeof(ssize); + memcpy(ptr,this,sizeof(*this)); + SET_LINES(); + + + return size; + } +} XCODE_PRAGMA_PACK; + + +#ifdef _WIN32 +#pragma pack(pop) +#endif + + +extern sd_video g_video; + +extern int g_video_act_margin_left ; +extern int g_video_act_margin_right; +extern int g_video_act_margin_top ; +extern int g_video_act_margin_bottom ; +extern int g_video_act_width ; +extern int g_video_act_height ; + + +class ss_video +{ +public: + int g_screen_mdepth; + int g_screen_depth; + word32 g_red_mask; + word32 g_green_mask ; + word32 g_blue_mask ; + int g_red_left_shift; + int g_green_left_shift ; + int g_blue_left_shift; + int g_red_right_shift ; + int g_green_right_shift ; + int g_blue_right_shift ; + int g_installed_full_superhires_colormap ; + word32 g_saved_line_palettes[200][8]; + word32 slow_mem_changed[SLOW_MEM_CH_SIZE]; + + + Kimage g_kimage_text[2]; + Kimage g_kimage_hires[2]; + Kimage g_kimage_superhires; + Kimage g_kimage_border_special; + Kimage g_kimage_border_special2; + Kimage g_kimage_border_sides; + + Kimage g_mainwin_kimage; + + + ss_video() + { + memset(this,0,sizeof(*this)); + g_screen_depth = 8; + g_red_mask = 0xff; + g_green_mask = 0xff; + g_blue_mask = 0xff; + g_red_left_shift = 16; + g_green_left_shift = 8; + g_blue_left_shift = 0; + g_red_right_shift = 0; + g_green_right_shift = 0; + g_blue_right_shift = 0; + } +} ; + +extern ss_video s_video; + +extern Kimage g_kimage_offscreen; +extern int g_video_offscreen_has_been_modified ; + +void refresh_video(int _forcerefresh); + +void init_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth); + +#define NBFPSTIMER 5 +extern void addFrameRate(int ); +extern int getFrameRate(int ); diff --git a/kegs/iOS/emulatorView.h b/kegs/iOS/emulatorView.h new file mode 100644 index 0000000..cbc5dd1 --- /dev/null +++ b/kegs/iOS/emulatorView.h @@ -0,0 +1,32 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#pragma once + +#import +#include + +extern void x_async_refresh(CGContextRef myContext,CGRect r); +extern void add_event_key(int,int); +extern void add_event_mouse(int _x,int _y, int _state, int _button); +extern void add_event_modifier(unsigned int state) ; + +extern int g_warp_pointer; +extern int g_pause; + + +@interface emulatorView : UIView +{ + CADisplayLink* displayLink; + +} + + +-(void)activateEmulatorRefresh:(int)_frameRate; +-(void)deactivateEmulatorRefresh; + + +@end diff --git a/kegs/iOS/emulatorView.mm b/kegs/iOS/emulatorView.mm new file mode 100644 index 0000000..9e2a62d --- /dev/null +++ b/kegs/iOS/emulatorView.mm @@ -0,0 +1,98 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Src/defc.h" +#include "../Src/video.h" +#include "../Src/sim65816.h" +#import "emulatorView.h" + + +int x_frame_rate = -1; + +@implementation emulatorView + + +-(void)activateEmulatorRefresh:(int)_frameRate +{ + if (displayLink) + [self deactivateEmulatorRefresh]; + + displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(directDraw:)] retain]; + + x_frame_rate = _frameRate; + switch(_frameRate) + { + case 30: + [displayLink setFrameInterval:2]; + g_video.g_screen_redraw_skip_amt = 1; + break; + case 60: + [displayLink setFrameInterval:1]; + g_video.g_screen_redraw_skip_amt = -1; + break; + case 15: + [displayLink setFrameInterval:4]; + g_video.g_screen_redraw_skip_amt = 3; + break; + case 20: + default: // 20FPS + [displayLink setFrameInterval:3]; + g_video.g_screen_redraw_skip_amt = 2; + break; + } + // OG utiliser NSRunLoopCommonModes pour que le rendu ne s'arrete pas durant un uiscrollview + [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; +} + +-(void)deactivateEmulatorRefresh +{ + displayLink=nil; + +} + +int x_video_need_to_be_refreshed = 0; +extern int x_vbl_count ; + +void x_invalidrect() +{ + x_video_need_to_be_refreshed = 1; +} + +- (void)directDraw:(CADisplayLink *)sender +{ + + x_vbl_count++; + addFrameRate(4); + + if (x_video_need_to_be_refreshed) + { + x_video_need_to_be_refreshed = 0; + addFrameRate(3); + [self setNeedsDisplay]; + + } + /* +#ifdef ACTIVEGS + extern void x_update_framerate(); + x_update_framerate(); +#endif + */ +} + +-(void) drawRect:(CGRect) rect +{ + + CGContextRef g = UIGraphicsGetCurrentContext(); + x_async_refresh(g,rect); + +} + + + +@end + + + diff --git a/kegs/iOS/joystick_iphone.cpp b/kegs/iOS/joystick_iphone.cpp new file mode 100644 index 0000000..c6d506a --- /dev/null +++ b/kegs/iOS/joystick_iphone.cpp @@ -0,0 +1,57 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../src/defc.h" +#include "../src/paddles.h" +#include "../src/moremem.h" + + +void +joystick_init() +{ + g_joystick_native_type1 = 0; + g_joystick_native_type2 = -1; + g_joystick_native_type = JOYSTICK_TYPE_NATIVE_1; +} + +extern float joyX,joyY; +extern int oaButton,caButton; +extern void x_notify_paddle(int _on); + +void +joystick_update(double dcycs) +{ + x_notify_paddle(1); + + // non linear joy + float x = joyX*1.0; + float y = joyY*1.0; + x = (x > 1.0?1.0:x); x = (x < -1.0?-1.0:x); + y = (y > 1.0?1.0:y); y = (y < -1.0?-1.0:y); + + + + g_paddles.g_paddle_val[0] = 32767*x; + g_paddles.g_paddle_val[1] = 32767*y; + g_paddles.g_paddle_val[2] = 32767; + g_paddles.g_paddle_val[3] = 32767; + + +// g_moremem.g_paddle_buttons = (oaButton & 1) + (caButton & 1)*2 ; + paddle_update_trigger_dcycs(dcycs); +} + +void +joystick_update_buttons() +{ +// g_moremem.g_paddle_buttons = (oaButton & 1) + (caButton & 1)*2 ; +} + +// OG +void joystick_shut() +{ +} + diff --git a/kegs/iOS/zoomEmulatorView.h b/kegs/iOS/zoomEmulatorView.h new file mode 100644 index 0000000..e999f7c --- /dev/null +++ b/kegs/iOS/zoomEmulatorView.h @@ -0,0 +1,73 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#import +#import "emulatorView.h" + +#if defined(VIDEO_DOUBLEVLINE) +# define HEIGHT_MULTIPLY 1 +#else +# define HEIGHT_MULTIPLY 2 +#endif + +#if defined(VIDEO_DOUBLEHLINE) +# define WIDTH_MULTIPLY 1 +#else +# define WIDTH_MULTIPLY 2 +#endif + + struct orientationVar +{ + float scale; + CGPoint p; +} ; + +typedef struct orientationVar orientationVar; + +@interface zoomEmulatorView : UIScrollView +{ + + float dpiRatio; + CGSize viewSize; + + + + int mouseDown; + int zoomDisabled; + orientationVar orientationVars[4]; + + float kbdScale; + + UIPanGestureRecognizer* panGR; + UIPinchGestureRecognizer* pinchGR; + CGPoint lastMousePos; + BOOL allowInput; + BOOL startNewPhase; +@public + UIImageView* _crt ; + emulatorView * _ew ; + UITouch* _useTouch; + UITouch* _secondTouch; + int curOrientation; +} +@property (retain,nonatomic) emulatorView* ew ; +@property (retain,nonatomic) UIImageView* crt ; +@property (retain,nonatomic) UITouch* useTouch ; +@property (retain,nonatomic) UITouch* secondTouch ; + +-(void)updateFrame:(CGRect)frame kbdRect:(CGRect)kbdRect; +-(void)updateScreen:(CGRect)frame ratio:(float)ratio; +- (void)switchOrientation:(int)orientation; +-(void)disableZoom; +-(void)enableZoom; +-(void)enableInput; +-(void)disableInput; +-(void)mouseUp; +-(void)mouseDown; +-(void)setRatioToOne; +-(CGPoint)rotateTouch:(UITouch*) _touch; +- (id)initWithFrame:(CGRect)frame ratio:(float)ratio; +@end diff --git a/kegs/iOS/zoomEmulatorView.mm b/kegs/iOS/zoomEmulatorView.mm new file mode 100644 index 0000000..64ff098 --- /dev/null +++ b/kegs/iOS/zoomEmulatorView.mm @@ -0,0 +1,808 @@ +/* + ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS + Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net + This code is covered by the GNU GPL licence +*/ + +#include "../Src/defc.h" +#include "../Src/sim65816.h" +#include "../Src/adb.h" +#import "zoomEmulatorView.h" +#ifdef ACTIVEGSKARATEKA +#import "../../ActiveGS_Karateka/KaratekaAppDelegate.h" +#elif defined(ACTIVEGS) +#import "../../common.iphone/activegsAppDelegate.h" + +#endif + + + + + + +#undef debug_printf +#define debug_printf(...) +//#define debug_printf printf +//#define SHOW_COLOR + +@implementation zoomEmulatorView +@synthesize ew = _ew; +@synthesize crt = _crt; +@synthesize useTouch = _useTouch; +@synthesize secondTouch = _secondTouch; + +- (id)initWithFrame:(CGRect)frame ratio:(float)ratio +{ + + if (self = [super initWithFrame:frame]) + { + + self->dpiRatio = ratio; + self->viewSize = frame.size; + + debug_printf("ratio:%f width:%f height:%f",self->dpiRatio,self->viewSize.width,self->viewSize.height); + + CGRect r = CGRectMake(0.0,0.0,X_A2_WINDOW_WIDTH/self->dpiRatio ,X_A2_WINDOW_HEIGHT/self->dpiRatio ); + + self.contentSize = CGSizeMake(r.size.width,r.size.height); + + self.ew = [[[emulatorView alloc] initWithFrame:r] autorelease]; + [self.ew setUserInteractionEnabled:TRUE]; + + CGColorSpaceRef innerColorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef icontext = CGBitmapContextCreate(nil, X_A2_WINDOW_WIDTH,X_A2_WINDOW_HEIGHT*2, 8, X_A2_WINDOW_WIDTH*4,innerColorSpace,kCGImageAlphaPremultipliedLast); + + CGContextSetRGBFillColor(icontext,0,0,0,0.0); // transparent + CGContextFillRect(icontext,CGRectMake(0,0,X_A2_WINDOW_WIDTH,X_A2_WINDOW_HEIGHT*2)); + for(int h=0;hviewSize = frame.size; + self->dpiRatio = ratio; + + CGRect r = CGRectMake(0.0,0.0,X_A2_WINDOW_WIDTH/self->dpiRatio ,X_A2_WINDOW_HEIGHT/self->dpiRatio ); + + self.contentSize = CGSizeMake(r.size.width,r.size.height); + [self.ew setFrame:r]; + + [self.crt setFrame:CGRectMake(0,0,r.size.width,r.size.height)]; + [self.crt setBounds:CGRectMake(0,0,r.size.width,r.size.height*2)]; + + [self setRatioToOne]; +} + +-(void)updateFrame:(CGRect)frame kbdRect:(CGRect)kbdRect +{ + + // adapte la vue pour que le clavier ne cache pas l'écran + CGRect scrollSize = self.bounds ; + + + float ref = kbdRect.size.height; + + if ( (-scrollSize.origin.y) < ref) + { + // centre par rapport à la hauteur restante + float hremaining = frame.size.height - ref; + frame.origin.y = - kbdRect.size.height- ( hremaining - scrollSize.size.height*HEIGHT_MULTIPLY ) /2 ; + // TODO : ajuster le zoom! + } + + // NSLog(@"Frame %f,%f %f,%f",frame.origin.x,frame.origin.y,frame.size.width,frame.size.height); + + [self setFrame:frame]; +} + + + + +-(void)setRatioToOne +{ + + int w = (int)viewSize.width; + int h = (int)viewSize.height; + + debug_printf("apprect %d x %d\n",w,h); + +#define ZOOM_CLAMP 0.25 // calcul un zoom par multiple *.25 + + + for(int i=0;i<4;i++) + { + if (!(i&1)) + { + + + + // prend le plus petit des zooms possible + + float r = w*dpiRatio / (A2_WINDOW_WIDTH*WIDTH_MULTIPLY); + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + int ir = (int)r; + float zoomw = (float)ir*ZOOM_CLAMP; + + r = h*dpiRatio / (A2_WINDOW_HEIGHT*HEIGHT_MULTIPLY); + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + ir = (int)r; + float zoomh = (float)ir*ZOOM_CLAMP; + + float zoom = zoomh < zoomw ? zoomh : zoomw ; + + orientationVars[i].scale = zoom; + + + float realew =(X_A2_WINDOW_WIDTH - A2_WINDOW_WIDTH)*WIDTH_MULTIPLY*zoom; + float realw = w*dpiRatio; + float posw = realw - A2_WINDOW_WIDTH*zoom; + float x = (posw - realew)/2; // pour centrer + + + float realeh =(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT)*HEIGHT_MULTIPLY*zoom; + float realh = h*dpiRatio; + float posh = realh - A2_WINDOW_HEIGHT*HEIGHT_MULTIPLY*zoom; + float y = (posh - realeh)/2; // pour centrer + + orientationVars[i].p = CGPointMake(-x/dpiRatio/WIDTH_MULTIPLY,-y/dpiRatio/HEIGHT_MULTIPLY); + + + } + else + { + + + float r = h*dpiRatio / A2_WINDOW_WIDTH; + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + int ir = (int)r; + float zoomw = (float)ir*ZOOM_CLAMP; + + r = w*dpiRatio / ( A2_WINDOW_HEIGHT * HEIGHT_MULTIPLY ); + r = r/ZOOM_CLAMP; + if (r<1.0) + r = 1.0; + ir = (int)r; + float zoomh = (float)ir*ZOOM_CLAMP; + + float zoom = zoomh < zoomw ? zoomh : zoomw ; + + float realew =(X_A2_WINDOW_WIDTH - A2_WINDOW_WIDTH)*zoom; + float realw = h*dpiRatio; + float posw = realw - A2_WINDOW_WIDTH*zoom; + float x = (posw - realew)/2; + + + float realeh =(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT)*HEIGHT_MULTIPLY*zoom; + float realh = w*dpiRatio; + float posh = realh - A2_WINDOW_HEIGHT*HEIGHT_MULTIPLY*zoom; + float y = (posh - realeh)/2; // pour centrer + + orientationVars[i].scale = zoom; + orientationVars[i].p = CGPointMake(-x/dpiRatio,-y/dpiRatio/2); + + + } + + debug_printf("orientation:%d = %f , p = %f,%f\n",i, orientationVars[i].scale,orientationVars[i].p.x,orientationVars[i].p.y); + + } + + mouseDown = 0; + allowInput = TRUE; + zoomDisabled = FALSE; + refScalePortrait = orientationVars[0].scale; + refScaleLandscape = orientationVars[1].scale; + + +} + + +- (void)switchOrientation:(int)orientation +{ + + curOrientation = -1; + float s = orientationVars[orientation].scale; + CGPoint p = orientationVars[orientation].p; + debug_printf("**** about to switchOrientation: (%d) scale:%f offset %f,%f\n",orientation,s,p.x,p.y); + + self.zoomScale = s ; + [self setContentOffset:p]; + curOrientation = orientation; + + s = orientationVars[orientation].scale; + p = orientationVars[orientation].p; + debug_printf("**** done switching (%d) scale:%f offset %f,%f\n",orientation,s,p.x,p.y); + + inCran = false; + + if (orientation & 1) + refScale = refScaleLandscape; + else + refScale = refScalePortrait; + +} + +-(void)setContentOffset:(CGPoint)p /*animated:(BOOL)animated*/ +{ + if (p.x == 0.0f || p.y == 0.0) + { + debug_printf("ignoring %f,%f\n",p.x,p.y); + return ; + } + // appelé par [super initWithFrame:frame] alors que ew n'est pas encore initialisé + if(self.ew != nil ) + { + + CGSize vs = self.ew.frame.size; + CGSize scrollSize = self.bounds.size; + + static float realScale=0.0f; + + + if (!inCran) + { + if ( fabs(self.zoomScale - refScale) < 0.05 ) + { + inCran = true; + realScale = self.zoomScale; + self.zoomScale = refScale; + } + } + else + { + realScale += self.zoomScale - refScale; + if (fabs(realScale - refScale) > 0.10 ) + { + // à faire avant le sef.zoomScale= sinon on tombe dans une boucle infinie! + inCran = false; + self.zoomScale = realScale; + } + else + self.zoomScale = refScale; + } + + + // recentre la fenetre si elle tient totalement en hauteur ou en largeur + + + if (scrollSize.width >= vs.width || inCran ) + p.x = - (scrollSize.width - abs(vs.width)) / 2.0; + if (scrollSize.height >= vs.height || inCran ) + p.y = - (scrollSize.height - abs(vs.height)) / 2.0; + + + if (curOrientation!=-1) + { + debug_printf("saving scale (%d) %f %f,%f\n",curOrientation,self.zoomScale,p.x,p.y); + orientationVars[curOrientation].scale = self.zoomScale ; // / kbdScale; + orientationVars[curOrientation].p = p; + } + + + } + debug_printf("********** offset : %f %f\n",p.x,p.y); + [super setContentOffset:p]; +} + + + +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView +{ + return self.ew; + } + +- (void)drawRect:(CGRect)rect { + + // Drawing code + CGContextRef g = UIGraphicsGetCurrentContext(); + +#ifdef SHOW_COLOR + CGContextSetFillColorWithColor(g, [UIColor blueColor].CGColor); +#else + CGContextSetFillColorWithColor(g, [UIColor blackColor].CGColor); +#endif + + CGContextFillRect(g, rect); + + +} + + +-(CGPoint)rotateTouch:(UITouch*) _touch +{ + CGPoint pt; + float scale = self->dpiRatio/self.zoomScale; + + if (g_adb.g_warp_pointer==WARP_TOUCHSCREEN) + { + pt = [_touch locationInView:self.ew]; + pt.x *= self->dpiRatio; + pt.y *= self->dpiRatio; + pt.y = (X_A2_WINDOW_HEIGHT - pt.y); + pt.y *=2; + pt.x -= BASE_MARGIN_LEFT; + pt.y -= BASE_MARGIN_TOP*2; + + return pt; + } + + + pt = [_touch locationInView:self]; + int height = self.contentSize.height; + + if (r_sim65816.is_emulator_in_640mode()) + { + // current scale for 640 mode + } + else + { + // otherwise reduce the speed of the mouse + scale /= 2; + } + + pt.y = (height - pt.y)*scale; + pt.x *= scale; + + return pt; + +} + + +-(BOOL)touchesShouldCancelInContentView:(UIView *)view +{ + debug_printf("touchesShouldCancelInContentView\n"); + return !zoomDisabled; +} + +-(void)enableInput +{ + allowInput = TRUE; +} + +-(void)disableInput +{ + allowInput = FALSE; + if (self.useTouch) + self.useTouch = nil; + + if (self.secondTouch) + { + self.secondTouch = nil; + printf("*** secondtouch set in disableinput --- should never appear"); + } +} + + +-(void)disableZoom +{ + + debug_printf("disableZoom\n"); + + // BUG!!!! + // Sometimes, offset is being reset when gestures are disabled! + // Workaround = save the former offset and restore it afterwards + CGPoint offset = self.contentOffset; + + pinchGR.enabled = FALSE; + panGR.enabled = FALSE; + self.scrollEnabled = FALSE; + zoomDisabled= TRUE; + + // REstoring the offset + self.contentOffset = offset; + +} + +-(void)enableZoom +{ + + debug_printf("enableZoom\n"); + + pinchGR.enabled = TRUE; + panGR.enabled = TRUE; + + self.scrollEnabled = TRUE; + + zoomDisabled = FALSE; +} + + +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view +{ + debug_printf("scrollViewWillBeginZooming\n"); +#ifdef ACTIVEGS + // le zoom a démarré : anule les timers pour que le zoom ne soit pas interrompu + [[pManager getEmulatorView].contentView disableGestures:(MODE_ALL + MODE_EMULATOR & ~MODE_ZOOM)]; + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_ZOOM color:[UIColor grayColor]]; +#endif +} + + +- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale +{ + debug_printf("scrollViewDidEndZooming\n"); +#ifdef ACTIVEGS + // zoom terminé => on peut réactiver les gestures immédiatement + [[pManager getEmulatorView].contentView reenableAllGestures]; +#endif +} + + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + // NSLog(@" Offset = %@ ",NSStringFromCGPoint(scrollView.contentOffset)); +} + + +- (void)scrollViewDidZoom:(UIScrollView *)scrollView +{ +// printf("scrollViewDidZoom"); +// [ew directDraw:nil]; +} + +- (void) mouseDown +{ + if (!mouseDown) + { + + debug_printf("mouseDown %f %f\n",lastMousePos.x,lastMousePos.y); + mouseDown = 1; + add_event_mouse(lastMousePos.x,lastMousePos.y,1,1); +#ifdef ACTIVEGS + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_MOUSEBUTTON color:[UIColor redColor]]; +#endif + } +} + +- (void) mouseUp +{ + if (mouseDown) + { + add_event_mouse(lastMousePos.x,lastMousePos.y,0,1); + mouseDown = 0; +#ifdef ACTIVEGS + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_MOUSEBUTTON color:[UIColor greenColor]]; +#endif + } +} + +- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ +#ifdef ACTIVEGS + if ([[pManager getEmulatorView].kbdc myTouchesBegan:touches]) + { + debug_printf("pad activated"); + + [[pManager getEmulatorView].kbdc setGestureIndicatorVisibility:MODE_PAD color:[UIColor grayColor]]; + [[pManager getEmulatorView].contentView disableGestures:(MODE_ALL+MODE_EMULATOR & ~MODE_PAD)]; + return ; + } +#endif + + // prend la première touche + UITouch *touch = [[touches allObjects] objectAtIndex:0]; + + + + + + if (!allowInput) + { + debug_printf("input disabled"); + return ; + } + + if ([touches count] > 1) + { + debug_printf("multiple - disabling input"); +#ifdef ACTIVEGS + [[pManager getEmulatorView].contentView disableGestures:MODE_EMULATOR]; +#endif + return ; + } + + + if (self.useTouch) + { + if (!self.secondTouch && zoomDisabled) + { + if (!mouseDown) + { + debug_printf("second touch mouse Down\n"); + [self mouseDown]; + } + else + { + debug_printf("second touch\n"); + + } + + self.secondTouch = touch; + } + else + { + if (zoomDisabled) + { + debug_printf("third or more touch ignore"); + } + else + { + debug_printf("ignoring second touch - too soon, must be a gestures"); +#ifdef ACTIVEGS + [[pManager getEmulatorView].contentView disableGestures:MODE_EMULATOR]; +#endif + } + } + return ; + + } + + + + self.useTouch = touch; + + lastMousePos = [self rotateTouch:touch]; + + add_event_mouse(lastMousePos.x,lastMousePos.y,0,-1); + + if (self.secondTouch) + { + // mouseDown déjà enclenchée -> on a fini + return ; + } + + int nbtap = [touch tapCount]; + if (nbtap==1) + { + // prépare la désactivation des gestures + //[[pManager getEmulatorView].contentView scheduleDisableAllGestures]; + startNewPhase=TRUE; + + } + + + if (nbtap==2) + { + extern void simulate_space_event(); + simulate_space_event(); + } + + if (nbtap>=2 || g_adb.g_warp_pointer==WARP_TOUCHSCREEN) + { + + debug_printf("*** multi-tap\n"); + + [self mouseUp]; + + [self mouseDown]; + + // Désactive immédiatement les gestures +#ifdef ACTIVEGS + if (g_adb.g_warp_pointer!=WARP_TOUCHSCREEN) + [[pManager getEmulatorView].contentView disableGestures:MODE_ALL]; +#endif + } +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + + debug_printf("touchesEnded : %d",[touches count]); + +#ifdef ACTIVEGS + if (! [[pManager getEmulatorView].kbdc myTouchesEnded:touches]) + { + // le pad n'est plus actif - reactive les input si elles étaient disabled + if (!allowInput) + [[pManager getEmulatorView].contentView reenableAllGestures]; + } +#endif + + + if (!allowInput) + return ; + + if ( [touches containsObject:self.useTouch] + && [touches containsObject:self.secondTouch]) + { + debug_printf("both keys ended at the sametime"); + + [self mouseUp]; + + self.useTouch = nil; + self.secondTouch = nil; + + #ifdef ACTIVEGS + // vérifie les gestures + customView* cv = [pManager getEmulatorView].contentView; + [cv processGesturesOnTouchesEnded]; +#endif + return ; + } + + if ([touches containsObject:self.useTouch]) + { + debug_printf("contains useTouch"); + + if (self.secondTouch) + { + // libère useTouch mais ne fait rien d'autre - maintien la touche enclenchée + + debug_printf("maintaining mouseDown - secondTouch "); + self.useTouch = nil; + return; + } + else + { + debug_printf("touchesEnded\n"); + + [self mouseUp]; + self.useTouch = nil; +#ifdef ACTIVEGS + // vérifie les gestures + customView* cv = [pManager getEmulatorView].contentView; + [cv processGesturesOnTouchesEnded]; +#endif + } + } + + if ([touches containsObject:self.secondTouch]) + { + // correspond à un mouseUp + [self mouseUp]; + self.secondTouch = nil; + debug_printf("secondTouch ended"); + + if (!self.useTouch) + { +#ifdef ACTIVEGS + // aucune touche n'est plus appuyée : réactive les gestures + [[pManager getEmulatorView].contentView scheduleEnableAllGestures]; +#endif + } + } + +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + + // on est ici car lez zoom a démarré => théoriquement, il ne doit y avoir aucun useTouch, secondTouch, ou mouseDown + + if ([touches containsObject:self.useTouch]) + { + debug_printf("touchesCancelled useTouch\n"); + self.useTouch = nil; + } + if ([touches containsObject:self.secondTouch]) + { + debug_printf("touchesCancelled secondTouch\n"); + self.secondTouch = nil; + } + + // DEBUG INFO + if (mouseDown) + { + printf("mouseDown in touchesCancelled***"); + [self mouseUp]; + } + + //[[pManager getEmulatorView].contentView reenableAllGestures]; +} + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + +#ifdef ACTIVEGS + if ([[pManager getEmulatorView].kbdc myTouchesMoved:touches]) + return ; +#endif + if (!allowInput) + return ; + + if (startNewPhase) + { + debug_printf("first finger moved"); + startNewPhase = FALSE; +#ifdef ACTIVEGS + [[pManager getEmulatorView].contentView disableGestures:MODE_ZOOM]; // à faire avant le schedule + [[pManager getEmulatorView].contentView scheduleDisableAllGestures]; +#endif + } + + if (!self.useTouch) return ; + if ([touches containsObject:self.useTouch]) + { + + lastMousePos = [self rotateTouch:self.useTouch]; + add_event_mouse(lastMousePos.x,lastMousePos.y,mouseDown,1); + } +} + + +- (void)dealloc { + + self.delegate = nil; + [super dealloc]; +} + + +@end diff --git a/xcodebuild.h b/xcodebuild.h new file mode 100644 index 0000000..14634a7 --- /dev/null +++ b/xcodebuild.h @@ -0,0 +1 @@ +const char* xcodebuild="304";