diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index 6b6078824..80436626d 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -787,12 +787,14 @@ template class ConcreteMachine: std::unique_ptr get_options() final { auto options = std::make_unique(Configurable::OptionsType::UserFriendly); options->output = get_video_signal_configurable(); + options->use_square_pixels = video_.get_use_square_pixels(); return options; } void set_options(const std::unique_ptr &str) { const auto options = dynamic_cast(str.get()); set_video_signal_configurable(options->output); + video_.set_use_square_pixels(options->use_square_pixels); } // MARK: MediaTarget diff --git a/Machines/Apple/AppleII/AppleII.hpp b/Machines/Apple/AppleII/AppleII.hpp index e373da4b8..97d348578 100644 --- a/Machines/Apple/AppleII/AppleII.hpp +++ b/Machines/Apple/AppleII/AppleII.hpp @@ -30,8 +30,11 @@ class Machine { class Options: public Reflection::StructImpl, public Configurable::DisplayOption { friend Configurable::DisplayOption; public: - Options(Configurable::OptionsType) : Configurable::DisplayOption(Configurable::Display::CompositeColour) { + bool use_square_pixels = false; + + Options(Configurable::OptionsType) : Configurable::DisplayOption(Configurable::Display::CompositeColour) { if(needs_declare()) { + DeclareField(use_square_pixels); declare_display_option(); limit_enum(&output, Configurable::Display::CompositeMonochrome, Configurable::Display::CompositeColour, -1); } diff --git a/Machines/Apple/AppleII/Video.cpp b/Machines/Apple/AppleII/Video.cpp index 7b0df2baa..ae358c0ab 100644 --- a/Machines/Apple/AppleII/Video.cpp +++ b/Machines/Apple/AppleII/Video.cpp @@ -15,9 +15,8 @@ VideoBase::VideoBase(bool is_iie, std::function &&target) : crt_(910, 1, Outputs::Display::Type::NTSC60, Outputs::Display::InputDataType::Luminance1), is_iie_(is_iie) { - // Show only the centre 75% of the TV frame. crt_.set_display_type(Outputs::Display::DisplayType::CompositeColour); - crt_.set_visible_area(Outputs::Display::Rect(0.118f, 0.122f, 0.77f, 0.77f)); + set_use_square_pixels(use_square_pixels_); // TODO: there seems to be some sort of bug whereby switching modes can cause // a signal discontinuity that knocks phase out of whack. So it isn't safe to @@ -26,6 +25,41 @@ VideoBase::VideoBase(bool is_iie, std::function &&target) : // crt_.set_immediate_default_phase(0.5f); } +void VideoBase::set_use_square_pixels(bool use_square_pixels) { + use_square_pixels_ = use_square_pixels; + + // HYPER-UGLY HACK. See correlated hack in the Macintosh. +#ifdef __APPLE__ + crt_.set_visible_area(Outputs::Display::Rect(0.128f, 0.122f, 0.75f, 0.77f)); +#else + if(use_square_pixels) { + crt_.set_visible_area(Outputs::Display::Rect(0.128f, 0.112f, 0.75f, 0.73f)); + } else { + crt_.set_visible_area(Outputs::Display::Rect(0.128f, 0.12f, 0.75f, 0.77f)); + } +#endif + + if(use_square_pixels) { + // From what I can make out, many contemporary Apple II monitors were + // calibrated slightly to stretch the Apple II's display slightly wider + // than it should be per the NTSC standards, for approximately square + // pixels. This reproduces that. + + // 243 lines and 52µs are visible. + // i.e. to be square, 1 pixel should be: (1/243 * 52) * (3/4) = 156/972 = 39/243 µs + // On an Apple II each pixel is actually 1/7µs. + // Therefore the adjusted aspect ratio should be (4/3) * (39/243)/(1/7) = (4/3) * 273/243 = 1092/729 = 343/243 ~= 1.412 + crt_.set_aspect_ratio(343.0f / 243.0f); + } else { + // Standard NTSC aspect ratio. + crt_.set_aspect_ratio(4.0f / 3.0f); + } +} +bool VideoBase::get_use_square_pixels() { + return use_square_pixels_; +} + + void VideoBase::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } diff --git a/Machines/Apple/AppleII/Video.hpp b/Machines/Apple/AppleII/Video.hpp index afd332efc..ba414c83e 100644 --- a/Machines/Apple/AppleII/Video.hpp +++ b/Machines/Apple/AppleII/Video.hpp @@ -51,8 +51,14 @@ class VideoBase: public VideoSwitches { /// Gets the type of output. Outputs::Display::DisplayType get_display_type() const; + /// Sets whether the current CRT should be recalibrated away from normative NTSC + /// to produce square pixels in 40-column text mode. + void set_use_square_pixels(bool); + bool get_use_square_pixels(); + protected: Outputs::CRT::CRT crt_; + bool use_square_pixels_ = false; // State affecting output video stream generation. uint8_t *pixel_pointer_ = nullptr; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index bda241923..60a7ae8c2 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ 4B051C912669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C5826670A9300CA44E8 /* ROMCatalogue.cpp */; }; 4B051C922669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C5826670A9300CA44E8 /* ROMCatalogue.cpp */; }; 4B051C93266D9D6900CA44E8 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; }; + 4B051C95266EF50200CA44E8 /* AppleIIOptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C94266EF50200CA44E8 /* AppleIIOptionsPanel.swift */; }; + 4B051C97266EF5F600CA44E8 /* CSAppleII.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C96266EF5F600CA44E8 /* CSAppleII.mm */; }; 4B05401E219D1618001BF69C /* ScanTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B05401D219D1618001BF69C /* ScanTarget.cpp */; }; 4B05401F219D1618001BF69C /* ScanTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B05401D219D1618001BF69C /* ScanTarget.cpp */; }; 4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B055A771FAE78210060FFFF /* SDL2.framework */; }; @@ -1023,6 +1025,9 @@ 4B04B65622A58CB40006AB58 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = ""; }; 4B051C5826670A9300CA44E8 /* ROMCatalogue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ROMCatalogue.cpp; sourceTree = ""; }; 4B051C5926670A9300CA44E8 /* ROMCatalogue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMCatalogue.hpp; sourceTree = ""; }; + 4B051C94266EF50200CA44E8 /* AppleIIOptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppleIIOptionsPanel.swift; sourceTree = ""; }; + 4B051C96266EF5F600CA44E8 /* CSAppleII.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CSAppleII.mm; sourceTree = ""; }; + 4B051C98266EF60500CA44E8 /* CSAppleII.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSAppleII.h; sourceTree = ""; }; 4B05401D219D1618001BF69C /* ScanTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScanTarget.cpp; sourceTree = ""; }; 4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Clock Signal Kiosk"; sourceTree = BUILT_PRODUCTS_DIR; }; 4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = SOURCE_ROOT; }; @@ -2405,8 +2410,10 @@ 4B2A53981D117D36003C6002 /* Wrappers */ = { isa = PBXGroup; children = ( + 4B051C98266EF60500CA44E8 /* CSAppleII.h */, 4B2A53991D117D36003C6002 /* CSAtari2600.h */, 4B14978D1EE4B4D200CE2596 /* CSZX8081.h */, + 4B051C96266EF5F600CA44E8 /* CSAppleII.mm */, 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */, 4B14978E1EE4B4D200CE2596 /* CSZX8081.mm */, ); @@ -2777,6 +2784,7 @@ 4B55CE551C3B7D360093A61B /* Documents */ = { isa = PBXGroup; children = ( + 4B051C94266EF50200CA44E8 /* AppleIIOptionsPanel.swift */, 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */, 4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */, 4B8FE2211DA19FB20090D3CE /* MachinePanel.swift */, @@ -5402,11 +5410,13 @@ 4B4518861F75E91A00926311 /* MFMDiskController.cpp in Sources */, 4B0ACC2C23775819008902D0 /* IntelligentKeyboard.cpp in Sources */, 4B92E26A234AE35100CD6D1B /* MFP68901.cpp in Sources */, + 4B051C97266EF5F600CA44E8 /* CSAppleII.mm in Sources */, 4B0ACC2A23775819008902D0 /* Video.cpp in Sources */, 4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */, 4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */, 4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */, 4BEDA3BF25B25563000C2DBD /* Decoder.cpp in Sources */, + 4B051C95266EF50200CA44E8 /* AppleIIOptionsPanel.swift in Sources */, 4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */, 4BE8EB6625C750B50040BC40 /* DAT.cpp in Sources */, 4BBFFEE61F7B27F1005F3FEB /* TrackSerialiser.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme index 131430afb..263537208 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme @@ -56,13 +56,17 @@ argument = "/Users/thomasharte/Downloads/test-dsk-for-rw-and-50-60-hz/TEST-RW-60Hz.DSK" isEnabled = "NO"> + + + isEnabled = "NO"> + isEnabled = "YES"> + isEnabled = "YES"> + + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/AppleIIOptions.xib b/OSBindings/Mac/Clock Signal/Base.lproj/AppleIIOptions.xib index 8c80a36f1..25cbc0a49 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/AppleIIOptions.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/AppleIIOptions.xib @@ -1,8 +1,8 @@ - + - + @@ -13,17 +13,27 @@ - + - - + + - + + - + @@ -40,16 +50,20 @@ - + + + - + + + - + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/Atari2600Options.xib b/OSBindings/Mac/Clock Signal/Base.lproj/Atari2600Options.xib index 2e6e00fb0..41c6e7572 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/Atari2600Options.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/Atari2600Options.xib @@ -1,8 +1,8 @@ - + - + @@ -13,17 +13,17 @@ - + - +