diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 410e50123..4a2b943fa 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -175,13 +175,25 @@ public: interrupt_timer_(interrupt_timer) { establish_palette_hits(); build_mode_table(); - crt_.set_dynamic_framing( - Outputs::Display::Rect(0.16842f, 0.19909f, 0.71579f, 0.67197f), - 0.0f, 0.1f); crt_.set_brightness(3.0f / 2.0f); // As only the values 0, 1 and 2 will be used in each channel, // whereas Red2Green2Blue2 defines a range of 0-3. } + void set_dynamic_framing(const bool enable) { + dynamic_framing_ = enable; + if(enable) { + crt_.set_dynamic_framing( + Outputs::Display::Rect(0.16842f, 0.19909f, 0.71579f, 0.67197f), + 0.0f, 0.1f); + } else { + crt_.set_fixed_framing(Outputs::Display::Rect(0.1072f, 0.1f, 0.842105263157895f, 0.842105263157895f)); + } + } + + bool dynamic_framing() const { + return dynamic_framing_; + } + /*! The CRTC entry function for the main part of each clock cycle; takes the current bus state and determines what output to produce based on the current palette and mode. @@ -543,6 +555,7 @@ private: int cycles_into_hsync_ = 0; Outputs::CRT::CRT crt_; + bool dynamic_framing_ = false; uint8_t *pixel_data_ = nullptr, *pixel_pointer_ = nullptr; const uint8_t *const ram_ = nullptr; @@ -1192,6 +1205,7 @@ public: auto options = std::make_unique(Configurable::OptionsType::UserFriendly); options->output = get_video_signal_configurable(); options->quick_load = allow_fast_tape_hack_; + options->dynamic_crop = crtc_bus_handler_.dynamic_framing(); return options; } @@ -1200,6 +1214,7 @@ public: set_video_signal_configurable(options->output); allow_fast_tape_hack_ = options->quick_load; set_use_fast_tape_hack(); + crtc_bus_handler_.set_dynamic_framing(options->dynamic_crop); } // MARK: - Joysticks diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 6b3a8fb07..2f96bc791 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -366,6 +366,7 @@ 4B47F6C5241C87A100ED06F7 /* Struct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B47F6C4241C87A100ED06F7 /* Struct.cpp */; }; 4B47F6C6241C87A100ED06F7 /* Struct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B47F6C4241C87A100ED06F7 /* Struct.cpp */; }; 4B49F0A923346F7A0045E6A6 /* MacintoshOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B49F0A723346F7A0045E6A6 /* MacintoshOptions.xib */; }; + 4B4A75BD2EB2C55100EA398F /* CompositeDynamicCropOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B4A75BB2EB2C55100EA398F /* CompositeDynamicCropOptions.xib */; }; 4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */; }; 4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; }; 4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; }; @@ -1608,6 +1609,7 @@ 4B47F3B52E7BAB94005D4DEC /* uPD7002.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = uPD7002.cpp; sourceTree = ""; }; 4B47F6C4241C87A100ED06F7 /* Struct.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Struct.cpp; sourceTree = ""; }; 4B49F0A823346F7A0045E6A6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/MacintoshOptions.xib"; sourceTree = SOURCE_ROOT; }; + 4B4A75BC2EB2C55100EA398F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/CompositeDynamicCropOptions.xib; sourceTree = ""; }; 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AY38910.cpp; sourceTree = ""; }; 4B4A762F1DB1A3FA007AAE2E /* AY38910.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AY38910.hpp; sourceTree = ""; }; 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KonamiSCC.cpp; sourceTree = ""; }; @@ -3452,12 +3454,13 @@ children = ( 4B051C94266EF50200CA44E8 /* AppleIIController.swift */, 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsController.swift */, - 4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */, 4B8FE2211DA19FB20090D3CE /* MachineController.swift */, + 4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */, 4B95FA9C1F11893B0008E395 /* ZX8081Controller.swift */, 4B08A56720D72BEF0016CE5A /* Activity.xib */, 4BC5FC2E20CDDDEE00410AA0 /* AppleIIOptions.xib */, 4B8FE2131DA19D5F0090D3CE /* Atari2600Options.xib */, + 4B4A75BB2EB2C55100EA398F /* CompositeDynamicCropOptions.xib */, 4BEEE6BB20DC72EA003723BF /* CompositeOptions.xib */, 4B8FE2151DA19D5F0090D3CE /* MachineDocument.xib */, 4B49F0A723346F7A0045E6A6 /* MacintoshOptions.xib */, @@ -5696,6 +5699,7 @@ buildActionMask = 2147483647; files = ( 4B2C45421E3C3896002A2389 /* cartridge.png in Resources */, + 4B4A75BD2EB2C55100EA398F /* CompositeDynamicCropOptions.xib in Resources */, 4BB73EA91B587A5100552FC2 /* Assets.xcassets in Resources */, 4B79E4451E3AF38600141F11 /* floppy35.png in Resources */, 4BEDA3BD25B25563000C2DBD /* README.md in Resources */, @@ -7003,6 +7007,14 @@ name = MacintoshOptions.xib; sourceTree = ""; }; + 4B4A75BB2EB2C55100EA398F /* CompositeDynamicCropOptions.xib */ = { + isa = PBXVariantGroup; + children = ( + 4B4A75BC2EB2C55100EA398F /* Base */, + ); + name = CompositeDynamicCropOptions.xib; + sourceTree = ""; + }; 4B55DD8120DF06680043F2E5 /* MachinePicker.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/CompositeDynamicCropOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/CompositeDynamicCropOptions.xib new file mode 100644 index 000000000..6e2c149cd --- /dev/null +++ b/OSBindings/Mac/Clock Signal/Base.lproj/CompositeDynamicCropOptions.xib @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/CompositeOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/CompositeOptions.xib index 6e2c149cd..049bdf340 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/CompositeOptions.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/CompositeOptions.xib @@ -1,8 +1,8 @@ - + - + @@ -21,7 +21,7 @@ - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/MachineDocument.xib b/OSBindings/Mac/Clock Signal/Base.lproj/MachineDocument.xib index 708b74ee0..8e15a28ec 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/MachineDocument.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/MachineDocument.xib @@ -1,8 +1,8 @@ - + - + @@ -21,7 +21,7 @@ - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/MacintoshOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/MacintoshOptions.xib index 62e12dae4..b45b72e47 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/MacintoshOptions.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/MacintoshOptions.xib @@ -1,8 +1,8 @@ - + - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/OricOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/OricOptions.xib index f2f29e25f..65f162461 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/OricOptions.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/OricOptions.xib @@ -1,8 +1,8 @@ - + - + @@ -31,7 +31,7 @@ - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadCompositeOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadCompositeOptions.xib index 6582d3b1c..eba2d61d5 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadCompositeOptions.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadCompositeOptions.xib @@ -1,8 +1,8 @@ - + - + @@ -31,7 +31,7 @@ - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadOptions.xib index 9fbc2efd5..f5c6f2eda 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadOptions.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/QuickLoadOptions.xib @@ -1,8 +1,8 @@ - + - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/ZX8081Options.xib b/OSBindings/Mac/Clock Signal/Base.lproj/ZX8081Options.xib index d69666c97..2704b7e71 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/ZX8081Options.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/ZX8081Options.xib @@ -1,8 +1,8 @@ - + - + diff --git a/OSBindings/Mac/Clock Signal/Documents/Base.lproj/CompositeDynamicCropOptions.xib b/OSBindings/Mac/Clock Signal/Documents/Base.lproj/CompositeDynamicCropOptions.xib new file mode 100644 index 000000000..15b835c09 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/Documents/Base.lproj/CompositeDynamicCropOptions.xib @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineController.swift b/OSBindings/Mac/Clock Signal/Documents/MachineController.swift index aac5ac5ae..bc2018df7 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineController.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineController.swift @@ -56,10 +56,21 @@ class MachineController: NSObject { @IBAction func setDisplayType(_ sender: NSPopUpButton!) { if let selectedItem = sender.selectedItem { machine.videoSignal = signalForTag(tag: selectedItem.tag) - UserDefaults.standard.set(selectedItem.tag, forKey: self.displayTypeUserDefaultsKey) + UserDefaults.standard.set(selectedItem.tag, forKey: displayTypeUserDefaultsKey) } } + // MARK: Dynamic Cropping + var dynamicCroppingUserDefaultsKey: String { + return prefixedUserDefaultsKey("dynamicCrop") + } + @IBOutlet var dynamicCropButton: NSButton? + @IBAction func setDynamicCrop(_ sender: NSButton!) { + let useDynamicCropping = sender.state == .on + machine.useDynamicCropping = useDynamicCropping + UserDefaults.standard.set(useDynamicCropping, forKey: dynamicCroppingUserDefaultsKey) + } + // MARK: Restoring user defaults func establishStoredOptions() { let standardUserDefaults = UserDefaults.standard @@ -70,17 +81,23 @@ class MachineController: NSObject { ]) if let fastLoadingButton = self.fastLoadingButton { - let useFastLoadingHack = standardUserDefaults.bool(forKey: self.fastLoadingUserDefaultsKey) + let useFastLoadingHack = standardUserDefaults.bool(forKey: fastLoadingUserDefaultsKey) machine.useFastLoadingHack = useFastLoadingHack fastLoadingButton.state = useFastLoadingHack ? .on : .off } if let fastBootingButton = self.fastBootingButton { - let bootQuickly = standardUserDefaults.bool(forKey: self.bootQuicklyUserDefaultsKey) + let bootQuickly = standardUserDefaults.bool(forKey: bootQuicklyUserDefaultsKey) machine.useQuickBootingHack = bootQuickly fastBootingButton.state = bootQuickly ? .on : .off } + if let dynamicCropButton = self.dynamicCropButton { + let useDynamicCropping = standardUserDefaults.bool(forKey: dynamicCroppingUserDefaultsKey) + machine.useDynamicCropping = useDynamicCropping + dynamicCropButton.state = useDynamicCropping ? .on : .off + } + if let displayTypeButton = self.displayTypeButton { // Enable or disable options as per machine support. var titlesToRemove: [String] = [] diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h index f78a33a83..fc6c7b86a 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h @@ -94,6 +94,7 @@ typedef NS_ENUM(NSInteger, CSMachineChangeEffect) { @property (nonatomic, assign) CSMachineVideoSignal videoSignal; @property (nonatomic, assign) BOOL useAutomaticTapeMotorControl; @property (nonatomic, assign) BOOL useQuickBootingHack; +@property (nonatomic, assign) BOOL useDynamicCropping; - (BOOL)supportsVideoSignal:(CSMachineVideoSignal)videoSignal; diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 3ee5a39f1..4ff16c4f2 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -669,6 +669,20 @@ struct ActivityObserver: public Activity::Observer { } } +- (void)setUseDynamicCropping:(BOOL)useDynamicCropping { + Configurable::Device *configurable_device = _machine->configurable_device(); + if(!configurable_device) return; + + @synchronized(self) { + _useDynamicCropping = useDynamicCropping; + + auto options = configurable_device->get_options(); + Reflection::set(*options, "dynamiccrop", useDynamicCropping ? true : false); + configurable_device->set_options(options); + } + +} + - (NSString *)userDefaultsPrefix { // Assumes that the first machine in the targets list is the source of user defaults. std::string name = Machine::ShortNameForTargetMachine(_analyser.targets.front()->machine); diff --git a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm index ab45edeed..e35e57280 100644 --- a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm +++ b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm @@ -403,7 +403,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K - (NSString *)optionsNibName { switch(_targets.front()->machine) { - case Analyser::Machine::AmstradCPC: return @"CompositeOptions"; + case Analyser::Machine::AmstradCPC: return @"CompositeDynamicCropOptions"; case Analyser::Machine::Archimedes: return @"QuickLoadOptions"; case Analyser::Machine::AppleII: return @"AppleIIOptions"; case Analyser::Machine::Atari2600: return @"Atari2600Options"; diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 943e509fa..594170bc4 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -505,6 +505,12 @@ void CRT::posit(Display::Rect rect) { Logger::info().append("First reading is (%0.5ff, %0.5ff, %0.5ff, %0.5ff)", posted_rect_.origin.x, posted_rect_.origin.y, posted_rect_.size.width, posted_rect_.size.height); + + auto frame = border_rect_; + frame.scale(0.90f, 0.90f); + Logger::info().append("90%% of whole frame was (%0.5ff, %0.5ff, %0.5ff, %0.5ff)", + frame.origin.x, frame.origin.y, + frame.size.width, frame.size.height); } return; }