Skip to content

Commit

Permalink
ActionReplay: Implement editing and add functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
OatmealDome committed Jun 26, 2023
1 parent 615a7fb commit 7d1d468
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 3 deletions.
@@ -0,0 +1,25 @@
// Copyright 2023 DolphiniOS Project
// SPDX-License-Identifier: GPL-2.0-or-later

#import <UIKit/UIKit.h>

namespace ActionReplay {
class ARCode;
}

@protocol ActionReplayCodeEditViewControllerDelegate;

NS_ASSUME_NONNULL_BEGIN

@interface ActionReplayCodeEditViewController : UITableViewController

@property (weak, nonatomic, nullable) id<ActionReplayCodeEditViewControllerDelegate> delegate;

@property (nonatomic) ActionReplay::ARCode* code;

@property (weak, nonatomic) IBOutlet UITextField* nameField;
@property (weak, nonatomic) IBOutlet UITextView* codeView;

@end

NS_ASSUME_NONNULL_END
@@ -0,0 +1,212 @@
// Copyright 2023 DolphiniOS Project
// SPDX-License-Identifier: GPL-2.0-or-later

#import "ActionReplayCodeEditViewController.h"

#import "Common/Event.h"

#import "Core/ARDecrypt.h"
#import "Core/ActionReplay.h"

#import "ActionReplayCodeEditViewControllerDelegate.h"
#import "FoundationStringUtil.h"
#import "LocalizationUtil.h"

typedef NS_ENUM(NSInteger, DOLActionReplayCodeMixedResult) {
DOLActionReplayCodeMixedResultOK,
DOLActionReplayCodeMixedResultCancel,
DOLActionReplayCodeMixedResultAbort
};

@interface ActionReplayCodeEditViewController () <UITextViewDelegate>

@end

@implementation ActionReplayCodeEditViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.nameField.text = CppToFoundationString(self.code->name);

NSMutableArray<NSString*>* codeLinesArray = [[NSMutableArray alloc] init];
for (const auto& e : self.code->ops) {
[codeLinesArray addObject:CppToFoundationString(ActionReplay::SerializeLine(e))];
}

self.codeView.text = [codeLinesArray componentsJoinedByString:@"\n"];
}

- (void)disableViews {
self.nameField.enabled = false;
self.codeView.userInteractionEnabled = false;
}

- (void)enableViews {
self.nameField.enabled = true;
self.codeView.userInteractionEnabled = true;
}

- (void)textViewDidChange:(UITextView*)textView {
[self.tableView beginUpdates];
[self.tableView endUpdates];
}

- (IBAction)savePressed:(id)sender {
[self disableViews];

__block std::string name = FoundationToCppString(self.nameField.text);

NSArray<NSString*>* codeLines = [self.codeView.text componentsSeparatedByString:@"\n"];

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
std::vector<ActionReplay::AREntry> entries;
std::vector<std::string> encryptedLines;

for (size_t i = 0; i < [codeLines count]; i++) {
NSString* line = [codeLines objectAtIndex:i];

if ([line length] == 0) {
continue;
}

if (i == 0 && [line characterAtIndex:0] == u'$') {
if (name.empty()) {
name = FoundationToCppString([line substringFromIndex:1]);
}

continue;
}

const auto parseResult = ActionReplay::DeserializeLine(FoundationToCppString(line));

if (std::holds_alternative<ActionReplay::AREntry>(parseResult))
{
entries.push_back(std::get<ActionReplay::AREntry>(parseResult));
}
else if (std::holds_alternative<ActionReplay::EncryptedLine>(parseResult))
{
encryptedLines.emplace_back(std::get<ActionReplay::EncryptedLine>(parseResult));
}
else
{
__block bool continueParsing;

Common::Event waitEvent;
Common::Event* waitEventPtr = &waitEvent;

dispatch_async(dispatch_get_main_queue(), ^{
NSString* alertTextFormat = DOLCoreLocalizedStringWithArgs(@"Unable to parse line %1 of the entered AR code as a valid "
"encrypted or decrypted code. Make sure you typed it correctly.\n\n"
"Would you like to ignore this line and continue parsing?", @"d");
NSString* alertText = [NSString stringWithFormat:alertTextFormat, i + 1];

UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:DOLCoreLocalizedString(@"Parsing Error") message:alertText preferredStyle:UIAlertControllerStyleAlert];

[errorAlert addAction:[UIAlertAction actionWithTitle:DOLCoreLocalizedString(@"Abort") style:UIAlertActionStyleCancel handler:^(UIAlertAction*) {
continueParsing = false;

waitEventPtr->Set();
}]];

[errorAlert addAction:[UIAlertAction actionWithTitle:DOLCoreLocalizedString(@"OK") style:UIAlertActionStyleDefault handler:^(UIAlertAction*) {
continueParsing = true;

waitEventPtr->Set();
}]];

[self presentViewController:errorAlert animated:true completion:nil];
});

waitEvent.Wait();

if (!continueParsing) {
dispatch_async(dispatch_get_main_queue(), ^{
[self enableViews];
});

return;
}
}
}

if (!encryptedLines.empty()) {
if (!entries.empty()) {
__block DOLActionReplayCodeMixedResult mixedResult;

Common::Event waitEvent;
Common::Event* waitEventPtr = &waitEvent;

dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:DOLCoreLocalizedString(@"Parsing Error")
message:DOLCoreLocalizedString(@"This Action Replay code contains both encrypted and unencrypted lines; "
"you should check that you have entered it correctly.\n\n"
"Do you want to discard all unencrypted lines?")
preferredStyle:UIAlertControllerStyleAlert];

[errorAlert addAction:[UIAlertAction actionWithTitle:DOLCoreLocalizedString(@"OK") style:UIAlertActionStyleDefault handler:^(UIAlertAction*) {
mixedResult = DOLActionReplayCodeMixedResultOK;

waitEventPtr->Set();
}]];

[errorAlert addAction:[UIAlertAction actionWithTitle:DOLCoreLocalizedString(@"Cancel") style:UIAlertActionStyleDefault handler:^(UIAlertAction*) {
mixedResult = DOLActionReplayCodeMixedResultCancel;

waitEventPtr->Set();
}]];

[errorAlert addAction:[UIAlertAction actionWithTitle:DOLCoreLocalizedString(@"Abort") style:UIAlertActionStyleCancel handler:^(UIAlertAction*) {
mixedResult = DOLActionReplayCodeMixedResultAbort;

waitEventPtr->Set();
}]];

[self presentViewController:errorAlert animated:true completion:nil];
});

waitEvent.Wait();

if (mixedResult == DOLActionReplayCodeMixedResultOK) {
entries.clear();
} else if (mixedResult == DOLActionReplayCodeMixedResultCancel) {
encryptedLines.clear();
} else if (mixedResult == DOLActionReplayCodeMixedResultAbort) {
dispatch_async(dispatch_get_main_queue(), ^{
[self enableViews];
});

return;
}
}

ActionReplay::DecryptARCode(encryptedLines, &entries);
}

if (entries.empty()) {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* emptyAlert = [UIAlertController alertControllerWithTitle:DOLCoreLocalizedString(@"Error") message:DOLCoreLocalizedString(@"The resulting decrypted AR code doesn't contain any lines.") preferredStyle:UIAlertControllerStyleAlert];

[emptyAlert addAction:[UIAlertAction actionWithTitle:DOLCoreLocalizedString(@"OK") style:UIAlertActionStyleDefault handler:^(UIAlertAction*) {
[self enableViews];
}]];

[self presentViewController:emptyAlert animated:true completion:nil];
});

return;
}

self.code->name = name;
self.code->ops = std::move(entries);
self.code->user_defined = true;

dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate userDidSaveCode:self];

[self.navigationController popViewControllerAnimated:true];
});
});
}

@end
@@ -0,0 +1,16 @@
// Copyright 2023 DolphiniOS Project
// SPDX-License-Identifier: GPL-2.0-or-later

#import <Foundation/Foundation.h>

@class ActionReplayCodeEditViewController;

NS_ASSUME_NONNULL_BEGIN

@protocol ActionReplayCodeEditViewControllerDelegate <NSObject>

- (void)userDidSaveCode:(ActionReplayCodeEditViewController*)viewController;

@end

NS_ASSUME_NONNULL_END
Expand Up @@ -9,11 +9,13 @@
#import "Core/ActionReplay.h"
#import "Core/ConfigManager.h"

#import "ActionReplayCodeEditViewController.h"
#import "ActionReplayCodeEditViewControllerDelegate.h"
#import "DOLSwitch.h"
#import "FoundationStringUtil.h"
#import "Swift.h"

@interface ActionReplayCodeViewController ()
@interface ActionReplayCodeViewController () <ActionReplayCodeEditViewControllerDelegate>

@end

Expand Down Expand Up @@ -117,5 +119,22 @@ - (IBAction)codeEnabledChanged:(DOLSwitch*)sender {
[self saveCodes];
}

- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"edit"]) {
ActionReplayCodeEditViewController* editController = segue.destinationViewController;
editController.delegate = self;
editController.code = self->_editTargetCode;
}
}

- (void)userDidSaveCode:(ActionReplayCodeEditViewController*)viewController {
if (self->_editTargetIsNew) {
self->_codes.push_back(std::move(self->_newCode));
}

[self saveCodes];

[self.tableView reloadData];
}

@end
8 changes: 8 additions & 0 deletions Source/iOS/App/DolphiniOS.xcodeproj/project.pbxproj
Expand Up @@ -121,6 +121,7 @@
B9809C792A4A166D00877579 /* DOLSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9809C782A4A166C00877579 /* DOLSwitch.swift */; };
B9809C7C2A4A180700877579 /* ActionReplay.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9809C7B2A4A180700877579 /* ActionReplay.storyboard */; };
B9809C802A4A190C00877579 /* ActionReplayCodeViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = B9809C7F2A4A190C00877579 /* ActionReplayCodeViewController.mm */; };
B9809C832A4A22EB00877579 /* ActionReplayCodeEditViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = B9809C822A4A22EB00877579 /* ActionReplayCodeEditViewController.mm */; };
B991377C28808D9000588446 /* GameCubeSystemLanguageViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = B991377B28808D8F00588446 /* GameCubeSystemLanguageViewController.mm */; };
B9913781288096A300588446 /* ConfigWiiViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = B9913780288096A300588446 /* ConfigWiiViewController.mm */; };
B9913785288146D700588446 /* WiiAspectRatioViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = B9913784288146D700588446 /* WiiAspectRatioViewController.mm */; };
Expand Down Expand Up @@ -423,6 +424,9 @@
B9809C7B2A4A180700877579 /* ActionReplay.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ActionReplay.storyboard; sourceTree = "<group>"; };
B9809C7E2A4A190C00877579 /* ActionReplayCodeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActionReplayCodeViewController.h; sourceTree = "<group>"; };
B9809C7F2A4A190C00877579 /* ActionReplayCodeViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ActionReplayCodeViewController.mm; sourceTree = "<group>"; };
B9809C812A4A22EB00877579 /* ActionReplayCodeEditViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActionReplayCodeEditViewController.h; sourceTree = "<group>"; };
B9809C822A4A22EB00877579 /* ActionReplayCodeEditViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ActionReplayCodeEditViewController.mm; sourceTree = "<group>"; };
B9809C842A4A2A4700877579 /* ActionReplayCodeEditViewControllerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActionReplayCodeEditViewControllerDelegate.h; sourceTree = "<group>"; };
B991377A28808D8F00588446 /* GameCubeSystemLanguageViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameCubeSystemLanguageViewController.h; sourceTree = "<group>"; };
B991377B28808D8F00588446 /* GameCubeSystemLanguageViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GameCubeSystemLanguageViewController.mm; sourceTree = "<group>"; };
B991377F288096A300588446 /* ConfigWiiViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConfigWiiViewController.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1345,6 +1349,9 @@
children = (
B9809C7E2A4A190C00877579 /* ActionReplayCodeViewController.h */,
B9809C7F2A4A190C00877579 /* ActionReplayCodeViewController.mm */,
B9809C812A4A22EB00877579 /* ActionReplayCodeEditViewController.h */,
B9809C822A4A22EB00877579 /* ActionReplayCodeEditViewController.mm */,
B9809C842A4A2A4700877579 /* ActionReplayCodeEditViewControllerDelegate.h */,
);
path = ActionReplay;
sourceTree = "<group>";
Expand Down Expand Up @@ -1991,6 +1998,7 @@
B9749240296035F500794509 /* FastmemManager.m in Sources */,
B904AD3B288904AC008B6BE9 /* MappingGroupEditBoolCell.m in Sources */,
B9809C602A48236900877579 /* SoftwarePropertiesInfoViewController.mm in Sources */,
B9809C832A4A22EB00877579 /* ActionReplayCodeEditViewController.mm in Sources */,
B9B2C64F288E1C4F00CB6569 /* MainDisplaySceneDelegate.swift in Sources */,
B904AD012887B9D1008B6BE9 /* ControllersPortViewController.mm in Sources */,
B904AD272888D346008B6BE9 /* MappingUtil.mm in Sources */,
Expand Down
12 changes: 10 additions & 2 deletions Source/iOS/App/DolphiniOS/UI/Cheats/ActionReplay.storyboard
Expand Up @@ -11,7 +11,7 @@
<!--Action Replay Edit-->
<scene sceneID="6dW-87-BL1">
<objects>
<tableViewController id="w0g-qD-Me6" userLabel="Action Replay Edit" sceneMemberID="viewController">
<tableViewController id="w0g-qD-Me6" userLabel="Action Replay Edit" customClass="ActionReplayCodeEditViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="eaz-Gk-hbz">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
Expand Down Expand Up @@ -88,8 +88,16 @@
</connections>
</tableView>
<navigationItem key="navigationItem" title="Edit" id="0c0-eg-hy8">
<barButtonItem key="rightBarButtonItem" systemItem="save" id="gAl-Rc-a3k"/>
<barButtonItem key="rightBarButtonItem" systemItem="save" id="gAl-Rc-a3k">
<connections>
<action selector="savePressed:" destination="w0g-qD-Me6" id="Ff8-0C-XOV"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="codeView" destination="jo0-lN-bfP" id="Eks-7H-O4i"/>
<outlet property="nameField" destination="pGc-Oj-2xC" id="mxh-CA-zwF"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ym0-Da-92i" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
<exit id="qbc-I3-DKe" userLabel="Exit" sceneMemberID="exit"/>
Expand Down

0 comments on commit 7d1d468

Please sign in to comment.