Skip to content

Commit 8c24d53

Browse files
authored
Merge pull request #34 from morozov/video-settings
Fix Graphics Filter preferences bugs
2 parents fc74dec + dbd8721 commit 8c24d53

8 files changed

Lines changed: 285 additions & 12 deletions

File tree

fusepb/FuseX.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
B61F468B09121DF100C8096C /* PreferencesController.m in Sources */ = {isa = PBXBuildFile; fileRef = B650F73F07E7CD3F00E4F3AF /* PreferencesController.m */; };
120120
B61F468C09121DF100C8096C /* ScalerNameToIdTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = B67F3C1507ED1C9D0045339F /* ScalerNameToIdTransformer.m */; };
121121
B61F468D09121DF100C8096C /* MachineScalerIsEnabled.m in Sources */ = {isa = PBXBuildFile; fileRef = B67F3C5007ED34530045339F /* MachineScalerIsEnabled.m */; };
122+
B61F46A009121DF100C8096C /* ScalerSupportsScanlines.m in Sources */ = {isa = PBXBuildFile; fileRef = B67F3D0107ED1C9D0045339F /* ScalerSupportsScanlines.m */; };
122123
B61F468E09121DF100C8096C /* MachineNameToIdTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = B67F3CC407EE0A130045339F /* MachineNameToIdTransformer.m */; };
123124
B61F468F09121DF100C8096C /* CAMachines.m in Sources */ = {isa = PBXBuildFile; fileRef = B6CC83000800E408006EFFB9 /* CAMachines.m */; };
124125
B61F469009121DF100C8096C /* Joysticks.m in Sources */ = {isa = PBXBuildFile; fileRef = B6C740DA0810BB0500AB170C /* Joysticks.m */; };
@@ -562,6 +563,8 @@
562563
B67DC2180B63835100FA31B6 /* cocoastatusbar.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = cocoastatusbar.m; sourceTree = "<group>"; };
563564
B67F3C1407ED1C9D0045339F /* ScalerNameToIdTransformer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ScalerNameToIdTransformer.h; path = transformers/ScalerNameToIdTransformer.h; sourceTree = SOURCE_ROOT; };
564565
B67F3C1507ED1C9D0045339F /* ScalerNameToIdTransformer.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ScalerNameToIdTransformer.m; path = transformers/ScalerNameToIdTransformer.m; sourceTree = SOURCE_ROOT; };
566+
B67F3D0007ED1C9D0045339F /* ScalerSupportsScanlines.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ScalerSupportsScanlines.h; path = transformers/ScalerSupportsScanlines.h; sourceTree = SOURCE_ROOT; };
567+
B67F3D0107ED1C9D0045339F /* ScalerSupportsScanlines.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ScalerSupportsScanlines.m; path = transformers/ScalerSupportsScanlines.m; sourceTree = SOURCE_ROOT; };
565568
B67F3C4F07ED34530045339F /* MachineScalerIsEnabled.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MachineScalerIsEnabled.h; path = transformers/MachineScalerIsEnabled.h; sourceTree = SOURCE_ROOT; };
566569
B67F3C5007ED34530045339F /* MachineScalerIsEnabled.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MachineScalerIsEnabled.m; path = transformers/MachineScalerIsEnabled.m; sourceTree = SOURCE_ROOT; };
567570
B67F3CC307EE0A130045339F /* MachineNameToIdTransformer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MachineNameToIdTransformer.h; path = transformers/MachineNameToIdTransformer.h; sourceTree = SOURCE_ROOT; };
@@ -1260,6 +1263,8 @@
12601263
B67F3C5007ED34530045339F /* MachineScalerIsEnabled.m */,
12611264
B67F3C1407ED1C9D0045339F /* ScalerNameToIdTransformer.h */,
12621265
B67F3C1507ED1C9D0045339F /* ScalerNameToIdTransformer.m */,
1266+
B67F3D0007ED1C9D0045339F /* ScalerSupportsScanlines.h */,
1267+
B67F3D0107ED1C9D0045339F /* ScalerSupportsScanlines.m */,
12631268
B66D6C9608115FC200FAE6F3 /* VolumeSliderToPrefTransformer.h */,
12641269
B66D6C9708115FC200FAE6F3 /* VolumeSliderToPrefTransformer.m */,
12651270
);
@@ -2093,6 +2098,7 @@
20932098
B61F468B09121DF100C8096C /* PreferencesController.m in Sources */,
20942099
B61F468C09121DF100C8096C /* ScalerNameToIdTransformer.m in Sources */,
20952100
B61F468D09121DF100C8096C /* MachineScalerIsEnabled.m in Sources */,
2101+
B61F46A009121DF100C8096C /* ScalerSupportsScanlines.m in Sources */,
20962102
B61F468E09121DF100C8096C /* MachineNameToIdTransformer.m in Sources */,
20972103
B61F468F09121DF100C8096C /* CAMachines.m in Sources */,
20982104
B61F469009121DF100C8096C /* Joysticks.m in Sources */,

fusepb/controllers/PreferencesController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
IBOutlet NSView *machinePrefsView;
4949
IBOutlet NSView *filterPrefsView;
5050
IBOutlet NSView *debuggerPrefsView;
51+
IBOutlet NSButton *bilinearCheckbox;
5152

5253
JoystickConfigurationController *joystickConfigurationController;
5354

fusepb/controllers/PreferencesController.m

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#import "HIDJoysticks.h"
3939

4040
#import "ScalerNameToIdTransformer.h"
41+
#import "ScalerSupportsScanlines.h"
4142
#import "MachineScalerIsEnabled.h"
4243
#import "MachineNameToIdTransformer.h"
4344
#import "VolumeSliderToPrefTransformer.h"
@@ -62,6 +63,7 @@ @implementation PreferencesController
6263
+(void) initialize
6364
{
6465
ScalerNameToIdTransformer *sNToITransformer;
66+
ScalerSupportsScanlines *scalerSupportsScanlines;
6567
MachineScalerIsEnabled *machineScalerIsEnabled;
6668
MachineNameToIdTransformer *mToITransformer;
6769
VolumeSliderToPrefTransformer *vsToPTransformer;
@@ -71,6 +73,11 @@ +(void) initialize
7173
[NSValueTransformer setValueTransformer:sNToITransformer
7274
forName:@"ScalerNameToIdTransformer"];
7375

76+
scalerSupportsScanlines = [[[ScalerSupportsScanlines alloc] init] autorelease];
77+
78+
[NSValueTransformer setValueTransformer:scalerSupportsScanlines
79+
forName:@"ScalerSupportsScanlines"];
80+
7481
machineScalerIsEnabled = [MachineScalerIsEnabled
7582
machineScalerIsEnabledWithInt:1];
7683

@@ -92,6 +99,12 @@ +(void) initialize
9299

93100
[NSValueTransformer setValueTransformer:vsToPTransformer
94101
forName:@"VolumeSliderToPrefTransformer"];
102+
103+
/* Force the saved bilinear flag off so the disabled Bilinear checkbox
104+
shows as unchecked rather than checked-but-greyed for users upgrading
105+
from a build where they had enabled it. Drop this when the TODO in
106+
DisplayOpenGLView.m re-enables the setting. */
107+
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"bilinear"];
95108
}
96109

97110
- (void)windowDidLoad
@@ -138,6 +151,12 @@ - (void)awakeFromNib
138151
NSToolbarItem *item = [[toolbar items] objectAtIndex:[defaults integerForKey:@"preferencestab"]];
139152
[toolbar setSelectedItemIdentifier:[item itemIdentifier]];
140153
[self selectPrefPanel:item];
154+
155+
/* The xib's static enabled="NO" attribute is silently dropped by ibtool
156+
for buttons with a value binding (the compiled nib has NSEnabled=true),
157+
so disable it here instead. Drop this when the TODO in
158+
DisplayOpenGLView.m re-enables bilinear filtering. */
159+
[bilinearCheckbox setEnabled:NO];
141160
}
142161

143162
- (void)showWindow:(id)sender
@@ -218,8 +237,25 @@ - (void)handleWillClose:(NSNotification *)note
218237
// B&W TV status may have changed
219238
display_refresh_all();
220239

221-
if( ( ( current_scaler != scaler_get_type(settings_current.start_scaler_mode) )
222-
&& !scaler_select_id(settings_current.start_scaler_mode) ) ||
240+
scaler_type prev_scaler = current_scaler;
241+
242+
/* Skip silently for unknown ids (e.g. defaults written by an older build
243+
with a now-removed scaler) rather than show ui_error from
244+
scaler_select_id every time Preferences closes. */
245+
int new_scaler = scaler_get_type( settings_current.start_scaler_mode );
246+
if( new_scaler >= 0 ) {
247+
/* scaler_select_scaler is a no-op when the requested scaler is already
248+
current; if it isn't supported on the current machine it returns
249+
non-zero and current_scaler is left unchanged. When the scaler does
250+
change, the hotswap inside picks up the new bilinear setting via
251+
createTexture, so no separate hotswap call is needed for that path. */
252+
scaler_select_scaler( new_scaler );
253+
}
254+
255+
/* For bilinear-only changes, the hotswap inside scaler_select_scaler
256+
didn't fire; trigger one explicitly so createTexture picks up the new
257+
filter. */
258+
if( current_scaler == prev_scaler &&
223259
old_bilinear != settings_current.bilinear_filter ) {
224260
uidisplay_hotswap_gfx_mode();
225261
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* ScalerSupportsScanlines.h: Transformer that returns YES when the selected
2+
graphics filter supports the PAL TV scanlines
3+
option
4+
Copyright (c) 2026 The FuseX Authors
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation; either version 2 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program; if not, write to the Free Software
18+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19+
20+
*/
21+
22+
#import <Foundation/Foundation.h>
23+
24+
@interface ScalerSupportsScanlines : NSValueTransformer
25+
+ (Class)transformedValueClass;
26+
+ (BOOL)allowsReverseTransformation;
27+
- (id)transformedValue:(id)value;
28+
@end
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/* ScalerSupportsScanlines.m: Transformer that returns YES when the selected
2+
graphics filter supports the PAL TV scanlines
3+
option
4+
Copyright (c) 2026 The FuseX Authors
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation; either version 2 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program; if not, write to the Free Software
18+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19+
20+
*/
21+
22+
#import "ScalerSupportsScanlines.h"
23+
24+
#include "ui/scaler/scaler.h"
25+
26+
@implementation ScalerSupportsScanlines
27+
28+
+ (Class)transformedValueClass
29+
{
30+
return [NSNumber class];
31+
}
32+
33+
+ (BOOL)allowsReverseTransformation
34+
{
35+
return NO;
36+
}
37+
38+
- (id)transformedValue:(id)value
39+
{
40+
const char *id_string;
41+
42+
if( value == nil ) return @(NO);
43+
44+
if( [value respondsToSelector:@selector(UTF8String)] ) {
45+
/* handles NSString */
46+
id_string = [value UTF8String];
47+
} else if( [value respondsToSelector:@selector(stringValue)] ) {
48+
/* handles NSCell and NSNumber */
49+
id_string = [[value stringValue] UTF8String];
50+
} else {
51+
/* unexpected type (e.g. NSNull from a corrupt defaults entry); leave
52+
the checkbox disabled rather than raise from a binding evaluation */
53+
return @(NO);
54+
}
55+
56+
/* Only PAL TV 2x, 3x and 4x expose a scanlines option; the 1x variant
57+
has no alternate row to darken */
58+
int type = scaler_get_type( id_string );
59+
BOOL supports = type == SCALER_PALTV2X ||
60+
type == SCALER_PALTV3X ||
61+
type == SCALER_PALTV4X;
62+
return @(supports);
63+
}
64+
65+
@end

fusepb/views/DisplayOpenGLView.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,12 @@ -(void) createTexture:(Cocoa_Texture*)newScreen
688688
GL_STORAGE_CACHED_APPLE );
689689
glPixelStorei( GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE );
690690
#endif
691-
GLint filter = settings_current.bilinear_filter ? GL_LINEAR : GL_NEAREST;
691+
/* TODO: honour settings_current.bilinear_filter again and re-enable the
692+
Bilinear checkbox in PreferencesController -awakeFromNib once
693+
bilinear filtering is fully working. Hard-coded to nearest-neighbour
694+
for now so the broken path is not reached for users with the setting
695+
saved on. */
696+
GLint filter = GL_NEAREST;
692697
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, filter );
693698
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, filter );
694699
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );

fusepb/xibs/Preferences.xib

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<outlet property="rom1Filename" destination="1627" id="1783"/>
2323
<outlet property="rom2Filename" destination="1629" id="1784"/>
2424
<outlet property="rom3Filename" destination="1626" id="1785"/>
25+
<outlet property="bilinearCheckbox" destination="1717" id="1789"/>
2526
<outlet property="romPrefsView" destination="1582" id="1778"/>
2627
<outlet property="rzxPrefsView" destination="1488" id="1779"/>
2728
<outlet property="soundPrefsView" destination="1408" id="1780"/>
@@ -1901,6 +1902,11 @@
19011902
</buttonCell>
19021903
<connections>
19031904
<binding destination="270" name="value" keyPath="values.paltv2x" id="1743"/>
1905+
<binding destination="270" name="enabled" keyPath="values.graphicsfilter" id="1790">
1906+
<dictionary key="options">
1907+
<string key="NSValueTransformerName">ScalerSupportsScanlines</string>
1908+
</dictionary>
1909+
</binding>
19041910
</connections>
19051911
</button>
19061912
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1717">
@@ -2018,9 +2024,16 @@
20182024
</binding>
20192025
</connections>
20202026
</buttonCell>
2021-
<buttonCell type="radio" title="HQ 4x" imagePosition="left" alignment="left" tag="24" inset="2" id="tRv-o9-mGu">
2027+
<buttonCell type="radio" title="TV 4x" imagePosition="left" alignment="left" tag="13" inset="2" id="1721">
20222028
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
20232029
<font key="font" metaFont="system"/>
2030+
<connections>
2031+
<binding destination="270" name="enabled" keyPath="values.machine" id="1791">
2032+
<dictionary key="options">
2033+
<string key="NSValueTransformerName">MachineTimexIsDisabled</string>
2034+
</dictionary>
2035+
</binding>
2036+
</connections>
20242037
</buttonCell>
20252038
</column>
20262039
<column>
@@ -2061,6 +2074,17 @@
20612074
</binding>
20622075
</connections>
20632076
</buttonCell>
2077+
<buttonCell type="radio" title="PAL TV 4x" imagePosition="left" alignment="left" tag="21" inset="2" id="74h-R3-Dsl">
2078+
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
2079+
<font key="font" metaFont="system"/>
2080+
<connections>
2081+
<binding destination="270" name="enabled" keyPath="values.machine" id="1792">
2082+
<dictionary key="options">
2083+
<string key="NSValueTransformerName">MachineTimexIsDisabled</string>
2084+
</dictionary>
2085+
</binding>
2086+
</connections>
2087+
</buttonCell>
20642088
<buttonCell type="radio" title="HQ 2x" imagePosition="left" alignment="left" tag="22" inset="2" id="1729">
20652089
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
20662090
<font key="font" metaFont="system"/>
@@ -2083,24 +2107,27 @@
20832107
</binding>
20842108
</connections>
20852109
</buttonCell>
2086-
<buttonCell type="radio" title="Dot Matrix" imagePosition="left" alignment="left" tag="15" inset="2" id="1725">
2110+
<buttonCell type="radio" title="HQ 4x" imagePosition="left" alignment="left" tag="24" inset="2" id="tRv-o9-mGu">
20872111
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
20882112
<font key="font" metaFont="system"/>
20892113
<connections>
2090-
<binding destination="270" name="enabled" keyPath="values.machine" id="1770">
2114+
<binding destination="270" name="enabled" keyPath="values.machine" id="1793">
20912115
<dictionary key="options">
20922116
<string key="NSValueTransformerName">MachineTimexIsDisabled</string>
20932117
</dictionary>
20942118
</binding>
20952119
</connections>
20962120
</buttonCell>
2097-
<buttonCell type="radio" title="TV 4x" imagePosition="left" alignment="left" tag="13" inset="2" id="1721">
2098-
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
2099-
<font key="font" metaFont="system"/>
2100-
</buttonCell>
2101-
<buttonCell type="radio" title="PAL TV 4x" imagePosition="left" alignment="left" tag="21" inset="2" id="74h-R3-Dsl">
2121+
<buttonCell type="radio" title="Dot Matrix" imagePosition="left" alignment="left" tag="15" inset="2" id="1725">
21022122
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
21032123
<font key="font" metaFont="system"/>
2124+
<connections>
2125+
<binding destination="270" name="enabled" keyPath="values.machine" id="1770">
2126+
<dictionary key="options">
2127+
<string key="NSValueTransformerName">MachineTimexIsDisabled</string>
2128+
</dictionary>
2129+
</binding>
2130+
</connections>
21042131
</buttonCell>
21052132
</column>
21062133
</cells>

0 commit comments

Comments
 (0)