mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Factored out the stuff of pushing a fast-loading option onwards and storing it within the user defaults.
This commit is contained in:
parent
9134e4de1f
commit
6027cba95f
@ -30,6 +30,18 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
|
|||||||
{
|
{
|
||||||
set_reset_line(false);
|
set_reset_line(false);
|
||||||
|
|
||||||
|
// test for PC at F92F
|
||||||
|
if(_use_fast_tape_hack && address == 0xf92f && operation == CPU6502::BusOperation::ReadOpcode)
|
||||||
|
{
|
||||||
|
// advance time on the tape and the VIAs until an interrupt is signalled
|
||||||
|
while(!_userPortVIA.get_interrupt_line() && !_keyboardVIA.get_interrupt_line())
|
||||||
|
{
|
||||||
|
_userPortVIA.run_for_half_cycles(2);
|
||||||
|
_keyboardVIA.run_for_half_cycles(2);
|
||||||
|
_tape.run_for_cycles(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// run the phase-1 part of this cycle, in which the VIC accesses memory
|
// run the phase-1 part of this cycle, in which the VIC accesses memory
|
||||||
uint16_t video_address = _mos6560->get_address();
|
uint16_t video_address = _mos6560->get_address();
|
||||||
uint8_t video_value = 0xff; // TODO
|
uint8_t video_value = 0xff; // TODO
|
||||||
@ -92,7 +104,6 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
|
|||||||
|
|
||||||
void Machine::mos6522_did_change_interrupt_status(void *mos6522)
|
void Machine::mos6522_did_change_interrupt_status(void *mos6522)
|
||||||
{
|
{
|
||||||
// bool irq = _userPortVIA.get_interrupt_line() || _keyboardVIA.get_interrupt_line();
|
|
||||||
set_nmi_line(_userPortVIA.get_interrupt_line());
|
set_nmi_line(_userPortVIA.get_interrupt_line());
|
||||||
set_irq_line(_keyboardVIA.get_interrupt_line());
|
set_irq_line(_keyboardVIA.get_interrupt_line());
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,8 @@ class Machine:
|
|||||||
void set_key_state(Key key, bool isPressed) { _keyboardVIA.set_key_state(key, isPressed); }
|
void set_key_state(Key key, bool isPressed) { _keyboardVIA.set_key_state(key, isPressed); }
|
||||||
void clear_all_keys() { _keyboardVIA.clear_all_keys(); }
|
void clear_all_keys() { _keyboardVIA.clear_all_keys(); }
|
||||||
|
|
||||||
|
inline void set_use_fast_tape_hack(bool activate) { _use_fast_tape_hack = activate; }
|
||||||
|
|
||||||
// to satisfy CPU6502::Processor
|
// to satisfy CPU6502::Processor
|
||||||
unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
|
unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
|
||||||
void synchronise() { _mos6560->synchronise(); }
|
void synchronise() { _mos6560->synchronise(); }
|
||||||
@ -199,7 +201,10 @@ class Machine:
|
|||||||
std::unique_ptr<MOS::MOS6560> _mos6560;
|
std::unique_ptr<MOS::MOS6560> _mos6560;
|
||||||
UserPortVIA _userPortVIA;
|
UserPortVIA _userPortVIA;
|
||||||
KeyboardVIA _keyboardVIA;
|
KeyboardVIA _keyboardVIA;
|
||||||
|
|
||||||
|
// Tape
|
||||||
Tape _tape;
|
Tape _tape;
|
||||||
|
bool _use_fast_tape_hack;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -683,6 +683,7 @@
|
|||||||
4BB73ECF1B587A6700552FC2 /* Clock Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Clock Signal.entitlements"; sourceTree = "<group>"; };
|
4BB73ECF1B587A6700552FC2 /* Clock Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Clock Signal.entitlements"; sourceTree = "<group>"; };
|
||||||
4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntermediateShader.cpp; sourceTree = "<group>"; };
|
4BBB142F1CD2CECE00BDB55C /* IntermediateShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntermediateShader.cpp; sourceTree = "<group>"; };
|
||||||
4BBB14301CD2CECE00BDB55C /* IntermediateShader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IntermediateShader.hpp; sourceTree = "<group>"; };
|
4BBB14301CD2CECE00BDB55C /* IntermediateShader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IntermediateShader.hpp; sourceTree = "<group>"; };
|
||||||
|
4BBC34241D2208B100FFC9DF /* CSCommonOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCommonOptions.h; sourceTree = "<group>"; };
|
||||||
4BBF99081C8FBA6F0075DAFB /* CRTInputBufferBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRTInputBufferBuilder.cpp; sourceTree = "<group>"; };
|
4BBF99081C8FBA6F0075DAFB /* CRTInputBufferBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRTInputBufferBuilder.cpp; sourceTree = "<group>"; };
|
||||||
4BBF99091C8FBA6F0075DAFB /* CRTInputBufferBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTInputBufferBuilder.hpp; sourceTree = "<group>"; };
|
4BBF99091C8FBA6F0075DAFB /* CRTInputBufferBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTInputBufferBuilder.hpp; sourceTree = "<group>"; };
|
||||||
4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRTOpenGL.cpp; sourceTree = "<group>"; };
|
4BBF990A1C8FBA6F0075DAFB /* CRTOpenGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRTOpenGL.cpp; sourceTree = "<group>"; };
|
||||||
@ -803,6 +804,7 @@
|
|||||||
4B2A53921D117D36003C6002 /* Machine */ = {
|
4B2A53921D117D36003C6002 /* Machine */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4BBC34241D2208B100FFC9DF /* CSCommonOptions.h */,
|
||||||
4B2A53931D117D36003C6002 /* CSKeyboardMachine.h */,
|
4B2A53931D117D36003C6002 /* CSKeyboardMachine.h */,
|
||||||
4B2A53941D117D36003C6002 /* CSMachine+Subclassing.h */,
|
4B2A53941D117D36003C6002 /* CSMachine+Subclassing.h */,
|
||||||
4B2A53951D117D36003C6002 /* CSMachine.h */,
|
4B2A53951D117D36003C6002 /* CSMachine.h */,
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9532"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9532"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="Atari2600Document" customModule="Clock_Signal" customModuleProvider="target">
|
<customObject id="-2" userLabel="File's Owner" customClass="Vic20Document" customModule="Clock_Signal" customModuleProvider="target">
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="fastLoadingButton" destination="sBT-cU-h7s" id="gWf-9E-D7l"/>
|
||||||
<outlet property="openGLView" destination="DEG-fq-cjd" id="Gxs-2u-n7B"/>
|
<outlet property="openGLView" destination="DEG-fq-cjd" id="Gxs-2u-n7B"/>
|
||||||
<outlet property="optionsPanel" destination="ota-g7-hOL" id="zeO-di-9i3"/>
|
<outlet property="optionsPanel" destination="ota-g7-hOL" id="zeO-di-9i3"/>
|
||||||
<outlet property="window" destination="xOd-HO-29H" id="JIz-fz-R2o"/>
|
<outlet property="window" destination="xOd-HO-29H" id="JIz-fz-R2o"/>
|
||||||
@ -48,7 +49,7 @@
|
|||||||
<value key="maxSize" type="size" width="200" height="83"/>
|
<value key="maxSize" type="size" width="200" height="83"/>
|
||||||
<view key="contentView" id="7Pv-WL-2Rq">
|
<view key="contentView" id="7Pv-WL-2Rq">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="200" height="83"/>
|
<rect key="frame" x="0.0" y="0.0" width="200" height="83"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="sBT-cU-h7s">
|
<button translatesAutoresizingMaskIntoConstraints="NO" id="sBT-cU-h7s">
|
||||||
<rect key="frame" x="18" y="47" width="164" height="18"/>
|
<rect key="frame" x="18" y="47" width="164" height="18"/>
|
||||||
@ -56,10 +57,13 @@
|
|||||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="setFastLoading:" target="-2" id="ctR-h1-CYI"/>
|
||||||
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MlB-rE-TXV">
|
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MlB-rE-TXV">
|
||||||
<rect key="frame" x="18" y="17" width="165" height="26"/>
|
<rect key="frame" x="18" y="17" width="165" height="26"/>
|
||||||
<popUpButtonCell key="cell" type="push" title="Danish Machine" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="38Y-Wm-1uo" id="UIu-uz-pTu">
|
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="UIu-uz-pTu">
|
||||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="menu"/>
|
<font key="font" metaFont="menu"/>
|
||||||
<menu key="menu" id="ajo-u0-WGk">
|
<menu key="menu" id="ajo-u0-WGk">
|
||||||
@ -83,7 +87,7 @@
|
|||||||
<constraint firstAttribute="trailing" secondItem="MlB-rE-TXV" secondAttribute="trailing" constant="20" id="v18-62-uee"/>
|
<constraint firstAttribute="trailing" secondItem="MlB-rE-TXV" secondAttribute="trailing" constant="20" id="v18-62-uee"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<point key="canvasLocation" x="129" y="46.5"/>
|
<point key="canvasLocation" x="-2" y="6.5"/>
|
||||||
</window>
|
</window>
|
||||||
</objects>
|
</objects>
|
||||||
</document>
|
</document>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#import "CSMachine.h"
|
#import "CSMachine.h"
|
||||||
#import "CSKeyboardMachine.h"
|
#import "CSKeyboardMachine.h"
|
||||||
|
#import "CSCommonOptions.h"
|
||||||
|
|
||||||
#import "CSAtari2600.h"
|
#import "CSAtari2600.h"
|
||||||
#import "CSElectron.h"
|
#import "CSElectron.h"
|
||||||
|
@ -16,6 +16,11 @@ class Atari2600Document: MachineDocument {
|
|||||||
return atari2600
|
return atari2600
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
override var name: String! {
|
||||||
|
get {
|
||||||
|
return "atari2600"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: NSDocument overrides
|
// MARK: NSDocument overrides
|
||||||
override class func autosavesInPlace() -> Bool {
|
override class func autosavesInPlace() -> Bool {
|
||||||
|
@ -17,6 +17,11 @@ class ElectronDocument: MachineDocument {
|
|||||||
return electron
|
return electron
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
override var name: String! {
|
||||||
|
get {
|
||||||
|
return "electron"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func aspectRatio() -> NSSize {
|
override func aspectRatio() -> NSSize {
|
||||||
return NSSize(width: 11.0, height: 10.0)
|
return NSSize(width: 11.0, height: 10.0)
|
||||||
@ -33,8 +38,6 @@ class ElectronDocument: MachineDocument {
|
|||||||
self.electron.setOSROM(os)
|
self.electron.setOSROM(os)
|
||||||
self.electron.setBASICROM(basic)
|
self.electron.setBASICROM(basic)
|
||||||
}
|
}
|
||||||
|
|
||||||
establishStoredOptions()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override var windowNibName: String? {
|
override var windowNibName: String? {
|
||||||
@ -69,25 +72,14 @@ class ElectronDocument: MachineDocument {
|
|||||||
NSUserDefaults.standardUserDefaults().setInteger(sender.indexOfSelectedItem, forKey: self.displayTypeUserDefaultsKey)
|
NSUserDefaults.standardUserDefaults().setInteger(sender.indexOfSelectedItem, forKey: self.displayTypeUserDefaultsKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBOutlet var fastLoadingButton: NSButton!
|
|
||||||
@IBAction func setFastLoading(sender: NSButton!) {
|
|
||||||
electron.useFastLoadingHack = sender.state == NSOnState
|
|
||||||
NSUserDefaults.standardUserDefaults().setBool(electron.useFastLoadingHack, forKey: self.fastLoadingUserDefaultsKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
private let displayTypeUserDefaultsKey = "electron.displayType"
|
private let displayTypeUserDefaultsKey = "electron.displayType"
|
||||||
private let fastLoadingUserDefaultsKey = "electron.fastLoading"
|
override func establishStoredOptions() {
|
||||||
private func establishStoredOptions() {
|
super.establishStoredOptions()
|
||||||
let standardUserDefaults = NSUserDefaults.standardUserDefaults()
|
let standardUserDefaults = NSUserDefaults.standardUserDefaults()
|
||||||
standardUserDefaults.registerDefaults([
|
standardUserDefaults.registerDefaults([
|
||||||
displayTypeUserDefaultsKey: 0,
|
displayTypeUserDefaultsKey: 0,
|
||||||
fastLoadingUserDefaultsKey: true
|
|
||||||
])
|
])
|
||||||
|
|
||||||
let useFastLoadingHack = standardUserDefaults.boolForKey(self.fastLoadingUserDefaultsKey)
|
|
||||||
electron.useFastLoadingHack = useFastLoadingHack
|
|
||||||
self.fastLoadingButton.state = useFastLoadingHack ? NSOnState : NSOffState
|
|
||||||
|
|
||||||
let displayType = standardUserDefaults.integerForKey(self.displayTypeUserDefaultsKey)
|
let displayType = standardUserDefaults.integerForKey(self.displayTypeUserDefaultsKey)
|
||||||
electron.useTelevisionOutput = (displayType == 1)
|
electron.useTelevisionOutput = (displayType == 1)
|
||||||
self.displayTypeButton.selectItemAtIndex(displayType)
|
self.displayTypeButton.selectItemAtIndex(displayType)
|
||||||
|
@ -25,6 +25,11 @@ class MachineDocument:
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var name: String! {
|
||||||
|
get {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func aspectRatio() -> NSSize {
|
func aspectRatio() -> NSSize {
|
||||||
return NSSize(width: 4.0, height: 3.0)
|
return NSSize(width: 4.0, height: 3.0)
|
||||||
@ -61,6 +66,7 @@ class MachineDocument:
|
|||||||
|
|
||||||
setupClockRate()
|
setupClockRate()
|
||||||
self.machine.delegate = self
|
self.machine.delegate = self
|
||||||
|
establishStoredOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
func machineDidChangeClockRate(machine: CSMachine!) {
|
func machineDidChangeClockRate(machine: CSMachine!) {
|
||||||
@ -168,4 +174,33 @@ class MachineDocument:
|
|||||||
$0.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.AlternateKeyMask))
|
$0.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.AlternateKeyMask))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: IBActions
|
||||||
|
var fastLoadingUserDefaultsKey: String {
|
||||||
|
get {
|
||||||
|
return "\(self.name).fastLoading"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBOutlet var fastLoadingButton: NSButton!
|
||||||
|
@IBAction func setFastLoading(sender: NSButton!) {
|
||||||
|
if let commonOptionsMachine = machine as? CSCommonOptions {
|
||||||
|
let useFastLoadingHack = sender.state == NSOnState
|
||||||
|
commonOptionsMachine.useFastLoadingHack = useFastLoadingHack
|
||||||
|
NSUserDefaults.standardUserDefaults().setBool(useFastLoadingHack, forKey: fastLoadingUserDefaultsKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func establishStoredOptions() {
|
||||||
|
let standardUserDefaults = NSUserDefaults.standardUserDefaults()
|
||||||
|
standardUserDefaults.registerDefaults([
|
||||||
|
fastLoadingUserDefaultsKey: true
|
||||||
|
])
|
||||||
|
|
||||||
|
if let commonOptionsMachine = machine as? CSCommonOptions {
|
||||||
|
let useFastLoadingHack = standardUserDefaults.boolForKey(self.fastLoadingUserDefaultsKey)
|
||||||
|
commonOptionsMachine.useFastLoadingHack = useFastLoadingHack
|
||||||
|
self.fastLoadingButton.state = useFastLoadingHack ? NSOnState : NSOffState
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,11 @@ class Vic20Document: MachineDocument {
|
|||||||
return vic20
|
return vic20
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
override var name: String! {
|
||||||
|
get {
|
||||||
|
return "vic20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: NSDocument overrides
|
// MARK: NSDocument overrides
|
||||||
override init() {
|
override init() {
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
#import "CSMachine.h"
|
#import "CSMachine.h"
|
||||||
#import "CSKeyboardMachine.h"
|
#import "CSKeyboardMachine.h"
|
||||||
|
#import "CSCommonOptions.h"
|
||||||
|
|
||||||
@interface CSElectron : CSMachine <CSKeyboardMachine>
|
@interface CSElectron : CSMachine <CSKeyboardMachine, CSCommonOptions>
|
||||||
|
|
||||||
- (void)setOSROM:(nonnull NSData *)rom;
|
- (void)setOSROM:(nonnull NSData *)rom;
|
||||||
- (void)setBASICROM:(nonnull NSData *)rom;
|
- (void)setBASICROM:(nonnull NSData *)rom;
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
#import "CSMachine.h"
|
#import "CSMachine.h"
|
||||||
#import "CSKeyboardMachine.h"
|
#import "CSKeyboardMachine.h"
|
||||||
|
#import "CSCommonOptions.h"
|
||||||
|
|
||||||
@interface CSVic20 : CSMachine <CSKeyboardMachine>
|
@interface CSVic20 : CSMachine <CSKeyboardMachine, CSCommonOptions>
|
||||||
|
|
||||||
- (void)setKernelROM:(nonnull NSData *)rom;
|
- (void)setKernelROM:(nonnull NSData *)rom;
|
||||||
- (void)setBASICROM:(nonnull NSData *)rom;
|
- (void)setBASICROM:(nonnull NSData *)rom;
|
||||||
@ -18,4 +19,6 @@
|
|||||||
- (void)setPRG:(nonnull NSData *)prg;
|
- (void)setPRG:(nonnull NSData *)prg;
|
||||||
- (BOOL)openTAPAtURL:(nonnull NSURL *)URL;
|
- (BOOL)openTAPAtURL:(nonnull NSURL *)URL;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL useFastLoadingHack;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -137,4 +137,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setUseFastLoadingHack:(BOOL)useFastLoadingHack {
|
||||||
|
@synchronized(self) {
|
||||||
|
_useFastLoadingHack = useFastLoadingHack;
|
||||||
|
_vic20.set_use_fast_tape_hack(useFastLoadingHack ? true : false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user