Support for searching references of memory address in code
This commit is contained in:
parent
31c4370046
commit
04f65c9b1b
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.user-fonts</key>
|
||||
<array>
|
||||
<string>app-usage</string>
|
||||
<string>system-installation</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -632,6 +632,7 @@
|
|||
92A9D67425CC5B7D008F5031 /* DebugMemoryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugMemoryButton.swift; sourceTree = "<group>"; };
|
||||
92A9D67825CC5BB6008F5031 /* DebugMemoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugMemoryCell.swift; sourceTree = "<group>"; };
|
||||
92A9D67E25CC5C66008F5031 /* DebugMemoryActionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugMemoryActionViewController.swift; sourceTree = "<group>"; };
|
||||
92AF5B1325D1B7A00025578D /* ActiveGS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ActiveGS.entitlements; path = ActiveGS/ActiveGS.entitlements; sourceTree = "<group>"; };
|
||||
92B9EADD24D3369600E6CFB2 /* ActiveGS-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ActiveGS-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
92B9EADE24D3369700E6CFB2 /* EmulatorKeyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmulatorKeyboard.swift; sourceTree = "<group>"; };
|
||||
92E2063125AADF6E00AE3F28 /* PreviewUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewUI.swift; sourceTree = "<group>"; };
|
||||
|
@ -1072,6 +1073,7 @@
|
|||
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92AF5B1325D1B7A00025578D /* ActiveGS.entitlements */,
|
||||
096604C819127DB700A22C51 /* activegs.plist */,
|
||||
09052B4219053C9F00853FAE /* Libraries */,
|
||||
09520D8516AEF8250065E84A /* Drivers */,
|
||||
|
@ -1600,7 +1602,7 @@
|
|||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_ENTITLEMENTS = ActiveGS/ActiveGS.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
|
@ -1625,7 +1627,7 @@
|
|||
"$(inherited)",
|
||||
"\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/GraphicsServices.framework\"",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.activeGS.test;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.yoshisuga.activeGS;
|
||||
PRODUCT_NAME = ActiveGS;
|
||||
PROVISIONING_PROFILE = "";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1645,7 +1647,7 @@
|
|||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_ENTITLEMENTS = ActiveGS/ActiveGS.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
|
@ -1672,7 +1674,7 @@
|
|||
"$(inherited)",
|
||||
"\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/GraphicsServices.framework\"",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.activeGS.test;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.yoshisuga.activeGS;
|
||||
PRODUCT_NAME = ActiveGS;
|
||||
PROVISIONING_PROFILE = "";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1692,7 +1694,7 @@
|
|||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_ENTITLEMENTS = ActiveGS/ActiveGS.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
|
@ -1716,7 +1718,7 @@
|
|||
"$(inherited)",
|
||||
"\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/GraphicsServices.framework\"",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.activeGS.test;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.yoshisuga.activeGS;
|
||||
PRODUCT_NAME = ActiveGS;
|
||||
PROVISIONING_PROFILE = "";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -22,6 +22,9 @@ enum InterpreterError: Error {
|
|||
|
||||
public class Debug6502Interpreter: Bus {
|
||||
public func read(from address: UInt16) throws -> UInt8 {
|
||||
if address >= memory.count {
|
||||
return 0
|
||||
}
|
||||
return memory[Int(address)]
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// CheatFinderManager.swift
|
||||
// ActiveGS
|
||||
//
|
||||
// Created by Yoshi Sugawara on 1/29/21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class CheatFinderManager {
|
||||
private(set) var matchedMemoryAddresses = [Int: UInt8]()
|
||||
var comparisonMemory = [UInt8]()
|
||||
|
||||
enum UIState {
|
||||
case initial, startedNewSearch, isSearching, didSearch
|
||||
}
|
||||
|
||||
enum SearchMode {
|
||||
case less, greater, same
|
||||
case equalTo(Int)
|
||||
}
|
||||
|
||||
var uiState = UIState.initial
|
||||
|
||||
func update(with memory: UnsafeMutablePointer<UInt8>) {
|
||||
for address in 0..<0x95ff {
|
||||
matchedMemoryAddresses[address] = memory[address]
|
||||
}
|
||||
}
|
||||
|
||||
func findNewMatches(searchMode: SearchMode) {
|
||||
var newMatches = [Int: UInt8]()
|
||||
for (address, oldValue) in matchedMemoryAddresses {
|
||||
let newValue = comparisonMemory[address]
|
||||
var matched = false
|
||||
switch searchMode {
|
||||
case .less:
|
||||
matched = newValue < oldValue
|
||||
case .greater:
|
||||
matched = newValue > oldValue
|
||||
case .same:
|
||||
matched = newValue == oldValue
|
||||
case .equalTo(let searchValue):
|
||||
matched = newValue == searchValue
|
||||
}
|
||||
if matched {
|
||||
newMatches[address] = newValue
|
||||
}
|
||||
}
|
||||
matchedMemoryAddresses = newMatches
|
||||
}
|
||||
|
||||
// start new search:
|
||||
// put all memory into matched
|
||||
//
|
||||
// set less than
|
||||
// run findNewMatches
|
||||
}
|
|
@ -12,6 +12,7 @@ class EmuMemoryModel {
|
|||
let maxMemorySize = 128 * 1024
|
||||
|
||||
private(set) var memory = EmuWrapper.memory()
|
||||
private(set) var referencedAddresses = [UInt16: [AddressedInstruction]]()
|
||||
|
||||
var selectedAddress: Int?
|
||||
|
||||
|
@ -71,6 +72,7 @@ class EmuMemoryModel {
|
|||
}
|
||||
print("Setting memory address %04X to %02X",address,value)
|
||||
memory[address] = value
|
||||
refresh()
|
||||
}
|
||||
|
||||
func getMemory(at address:Int) -> UInt8 {
|
||||
|
@ -96,11 +98,40 @@ class EmuMemoryModel {
|
|||
}
|
||||
|
||||
lazy var interpretedInstructions: [AddressedInstruction] = {
|
||||
let interpreter = Debug6502Interpreter(memory: memoryAsArray)
|
||||
return interpreter.interpret()
|
||||
return interpreted()
|
||||
}()
|
||||
|
||||
|
||||
private func interpreted() -> [AddressedInstruction] {
|
||||
let interpreter = Debug6502Interpreter(memory: memoryAsArray)
|
||||
let instructions = interpreter.interpret()
|
||||
referencedAddresses = [UInt16: [AddressedInstruction]]()
|
||||
let updateBlock: ((UInt16, AddressedInstruction) -> Void) = { address, instruction in
|
||||
var instructions: [AddressedInstruction] = {
|
||||
if let existingInstructions = self.referencedAddresses[address] {
|
||||
return existingInstructions
|
||||
}
|
||||
return [AddressedInstruction]()
|
||||
}()
|
||||
instructions.append(instruction)
|
||||
self.referencedAddresses[address] = instructions
|
||||
}
|
||||
for instruction in instructions {
|
||||
switch instruction.instruction.addressingMode {
|
||||
case .absolute(let address):
|
||||
updateBlock(address, instruction)
|
||||
case .zeroPage(let zeroPageAddress):
|
||||
updateBlock(UInt16(zeroPageAddress), instruction)
|
||||
case .indirect(let fromAddress):
|
||||
updateBlock(fromAddress, instruction)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
return instructions
|
||||
}
|
||||
|
||||
func refresh() {
|
||||
memory = EmuWrapper.memory()
|
||||
interpretedInstructions = interpreted()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ protocol DebugMemoryActionViewControllerDelegate: class {
|
|||
func updateMemory(at address: Int, with memory:UInt8)
|
||||
var memory: UnsafeMutablePointer<UInt8>? { get }
|
||||
var selectedAddress: Int? { get }
|
||||
var referencedMemoryAddresses: [UInt16: [AddressedInstruction]] { get }
|
||||
}
|
||||
|
||||
class DebugMemoryActionViewController: UIViewController {
|
||||
|
@ -24,6 +25,8 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
var mode: Mode = .jumpToAddress
|
||||
var cheatFinder = CheatFinderManager()
|
||||
|
||||
var matchedInstructions = [AddressedInstruction]()
|
||||
|
||||
weak var delegate:DebugMemoryActionViewControllerDelegate?
|
||||
|
||||
let segmentedControl: UISegmentedControl = {
|
||||
|
@ -193,6 +196,16 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
button.widthAnchor.constraint(equalToConstant: 30).isActive = true
|
||||
return button
|
||||
}()
|
||||
|
||||
let findCodeButton: DebugMemoryButton = {
|
||||
let button = DebugMemoryButton()
|
||||
button.titleLabel?.font = UIFont(name: "Print Char 21", size: 9)
|
||||
button.setTitle("Find in Code >", for: .normal)
|
||||
button.setTitle("Cancel", for: .selected)
|
||||
button.setTitleColor(.red, for: .selected)
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
return button
|
||||
}()
|
||||
|
||||
// lazy var cheatFinderSearchStackView: UIStackView = {
|
||||
// let stackView = UIStackView(arrangedSubviews: [cheatFinderSearchLessButton, cheatFinderSearchGreaterButton])
|
||||
|
@ -260,7 +273,7 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
cheatFinderPromptLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -48).isActive = true
|
||||
cheatFinderMatchesTableView.topAnchor.constraint(equalTo: cheatFinderPromptLabel.bottomAnchor, constant: 4).isActive = true
|
||||
cheatFinderMatchesTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24).isActive = true
|
||||
cheatFinderMatchesTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 24).isActive = true
|
||||
cheatFinderMatchesTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -24).isActive = true
|
||||
cheatFinderMatchesTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 8).isActive = true
|
||||
[cheatFinderInitialActionsStackView, cheatFinderPromptLabel, cheatFinderMatchesTableView].forEach{ $0.isHidden = true }
|
||||
}
|
||||
|
@ -329,15 +342,14 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
// view.addSubview(memoryField)
|
||||
|
||||
view.addSubview(keyboardView)
|
||||
titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16).isActive = true
|
||||
titleLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 16).isActive = true
|
||||
titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
|
||||
segmentedControl.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8).isActive = true
|
||||
segmentedControl.centerXAnchor.constraint(equalTo: titleLabel.centerXAnchor).isActive = true
|
||||
editFieldsStackView.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 8).isActive = true
|
||||
// memoryField.widthAnchor.constraint(equalToConstant: 80).isActive = true
|
||||
// memoryField.heightAnchor.constraint(equalToConstant: 40).isActive = true
|
||||
editFieldsStackView.centerXAnchor.constraint(equalTo: titleLabel.centerXAnchor).isActive = true
|
||||
keyboardView.centerXAnchor.constraint(equalTo: titleLabel.centerXAnchor).isActive = true
|
||||
editFieldsStackView.centerXAnchor.constraint(equalTo: keyboardView.centerXAnchor).isActive = true
|
||||
keyboardView.topAnchor.constraint(equalTo: editFieldsStackView.bottomAnchor, constant: 8).isActive = true
|
||||
// keyboardView.widthAnchor.constraint(equalToConstant: 200).isActive = true
|
||||
keyboardView.heightAnchor.constraint(equalToConstant: 200).isActive = true
|
||||
|
@ -349,16 +361,127 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
emulatorScreenView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16).isActive = true
|
||||
emulatorScreenView.isHidden = true
|
||||
|
||||
view.backgroundColor = .black
|
||||
view.backgroundColor = UIColor.init(red: 0.14, green: 0.13, blue: 0.14, alpha: 1)
|
||||
}
|
||||
|
||||
// Jump tab: normal constraints
|
||||
private var keyboardViewCenterXConstraint: NSLayoutConstraint!
|
||||
private var findCodeButtonLeadingConstraint: NSLayoutConstraint!
|
||||
private var findCodeButtonCenterYConstraint: NSLayoutConstraint!
|
||||
private var findInCodeTableViewLeadingConstraintOutOfView: NSLayoutConstraint!
|
||||
private var findInCodeTableViewBottomConstraintOutOfView: NSLayoutConstraint!
|
||||
var jumpTabNormalModeConstraints: [NSLayoutConstraint] {
|
||||
[
|
||||
keyboardViewCenterXConstraint,
|
||||
findCodeButtonLeadingConstraint,
|
||||
findCodeButtonCenterYConstraint,
|
||||
findInCodeTableViewLeadingConstraintOutOfView,
|
||||
findInCodeTableViewBottomConstraintOutOfView
|
||||
]
|
||||
}
|
||||
|
||||
// Jump tab: find in code constraints
|
||||
private var keyboardViewLeadingConstraint: NSLayoutConstraint!
|
||||
private var findCodeButtonBottomConstraint: NSLayoutConstraint!
|
||||
private var findCodeButtonCenterXConstraint: NSLayoutConstraint!
|
||||
private var findInCodeTableViewLeadingConstraint: NSLayoutConstraint!
|
||||
private var findInCodeTableViewTrailingConstraint: NSLayoutConstraint!
|
||||
private var findInCodeTableViewBottomConstraint: NSLayoutConstraint!
|
||||
var jumpTabFindInCodeConstraints: [NSLayoutConstraint] {
|
||||
[
|
||||
keyboardViewLeadingConstraint,
|
||||
findCodeButtonBottomConstraint,
|
||||
findInCodeTableViewLeadingConstraint,
|
||||
findInCodeTableViewTrailingConstraint,
|
||||
findCodeButtonCenterXConstraint,
|
||||
findInCodeTableViewBottomConstraint
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
// Jump tab: find in code table
|
||||
lazy var findInCodeResultsTableView: UITableView = {
|
||||
let view = UITableView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.backgroundColor = .clear
|
||||
view.dataSource = self
|
||||
view.delegate = self
|
||||
view.register(UITableViewCell.self, forCellReuseIdentifier: "FindInCodeResultsCell")
|
||||
return view
|
||||
}()
|
||||
|
||||
func findInCodeSetupView() {
|
||||
view.addSubview(findCodeButton)
|
||||
view.addSubview(findInCodeResultsTableView)
|
||||
|
||||
// Find Code Button Normal config
|
||||
keyboardViewCenterXConstraint = keyboardView.centerXAnchor.constraint(equalTo: titleLabel.centerXAnchor)
|
||||
findCodeButtonLeadingConstraint = findCodeButton.leadingAnchor.constraint(equalTo: keyboardView.trailingAnchor, constant: 8)
|
||||
findCodeButtonCenterYConstraint = findCodeButton.centerYAnchor.constraint(equalTo: keyboardView.centerYAnchor)
|
||||
findInCodeTableViewLeadingConstraintOutOfView = findInCodeResultsTableView.leadingAnchor.constraint(equalTo: view.trailingAnchor, constant: 50)
|
||||
findInCodeTableViewBottomConstraintOutOfView = findInCodeResultsTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -8)
|
||||
|
||||
// Find Code Button Searching Config
|
||||
keyboardViewLeadingConstraint = keyboardView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 8)
|
||||
findCodeButtonBottomConstraint = findCodeButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 4)
|
||||
findCodeButtonCenterXConstraint = findCodeButton.centerXAnchor.constraint(equalTo: findInCodeResultsTableView.centerXAnchor)
|
||||
findInCodeTableViewBottomConstraint = findInCodeResultsTableView.bottomAnchor.constraint(equalTo: findCodeButton.topAnchor, constant: -4)
|
||||
findInCodeResultsTableView.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 8).isActive = true
|
||||
findInCodeTableViewLeadingConstraint = findInCodeResultsTableView.leadingAnchor.constraint(equalTo: keyboardView.trailingAnchor, constant: 8)
|
||||
findInCodeTableViewTrailingConstraint = findInCodeResultsTableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -8)
|
||||
|
||||
NSLayoutConstraint.deactivate(jumpTabFindInCodeConstraints)
|
||||
NSLayoutConstraint.activate(jumpTabNormalModeConstraints)
|
||||
|
||||
findCodeButton.onTapped = { isSelected in
|
||||
self.updateKeyboardPosition(isFindingCode: isSelected)
|
||||
self.updateMatchedInstructions()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateMatchedInstructions() {
|
||||
if let delegate = delegate,
|
||||
let text = memoryField.text,
|
||||
let address = getAddressFromText(text) {
|
||||
matchedInstructions = delegate.referencedMemoryAddresses[UInt16(address)] ?? [AddressedInstruction]()
|
||||
findInCodeResultsTableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateKeyboardPosition(isFindingCode: Bool = false) {
|
||||
let animator = UIViewPropertyAnimator(duration: 0.2, curve: .linear) {
|
||||
if isFindingCode {
|
||||
NSLayoutConstraint.deactivate(self.jumpTabNormalModeConstraints)
|
||||
NSLayoutConstraint.activate(self.jumpTabFindInCodeConstraints)
|
||||
} else {
|
||||
NSLayoutConstraint.deactivate(self.jumpTabFindInCodeConstraints)
|
||||
NSLayoutConstraint.activate(self.jumpTabNormalModeConstraints)
|
||||
}
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
animator.startAnimation()
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupView()
|
||||
cheatFinderSetupView()
|
||||
findInCodeSetupView()
|
||||
update()
|
||||
}
|
||||
|
||||
func getAddressFromText(_ text: String?) -> UInt64? {
|
||||
guard let text = text else {
|
||||
return nil
|
||||
}
|
||||
let scanner = Scanner(string: text)
|
||||
var address: UInt64 = 0
|
||||
if scanner.scanHexInt64(&address) && address < 0x95ff {
|
||||
return address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateTextField(with keyCode: Int) {
|
||||
guard var text = memoryField.text else {
|
||||
print("no text in address field!")
|
||||
|
@ -378,11 +501,10 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
if text.count > charLimit {
|
||||
text.removeFirst()
|
||||
}
|
||||
if mode == .jumpToAddress {
|
||||
let scanner = Scanner(string: text)
|
||||
var address: UInt64 = 0
|
||||
if scanner.scanHexInt64(&address) && address < 0x95ff {
|
||||
delegate?.jump(to: Int(address))
|
||||
if mode == .jumpToAddress, let address = getAddressFromText(text) {
|
||||
delegate?.jump(to: Int(address))
|
||||
if findCodeButton.isSelected {
|
||||
updateMatchedInstructions()
|
||||
}
|
||||
}
|
||||
memoryField.text = text
|
||||
|
@ -407,6 +529,8 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
func update() {
|
||||
cheatFinderHide()
|
||||
emulatorScreenView.isHidden = true
|
||||
findCodeButton.isHidden = true
|
||||
findInCodeResultsTableView.isHidden = true
|
||||
switch mode {
|
||||
case .jumpToAddress:
|
||||
memoryField.isHidden = false
|
||||
|
@ -416,9 +540,12 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
updateMemoryButton.isHidden = true
|
||||
resetMemoryButton.isHidden = true
|
||||
keyboardView.isHidden = false
|
||||
findCodeButton.isHidden = false
|
||||
findInCodeResultsTableView.isHidden = false
|
||||
if let selectedAddress = delegate?.selectedAddress {
|
||||
memoryField.text = String(format: "%04X", selectedAddress)
|
||||
}
|
||||
updateKeyboardPosition(isFindingCode: findCodeButton.isSelected)
|
||||
case .changeMemory:
|
||||
memoryField.isHidden = false
|
||||
memoryField.layer.borderColor = UIColor.orange.cgColor
|
||||
|
@ -430,6 +557,7 @@ class DebugMemoryActionViewController: UIViewController {
|
|||
if let selectedAddress = delegate?.selectedAddress {
|
||||
memoryField.text = delegate?.memoryHex(at: selectedAddress)
|
||||
}
|
||||
updateKeyboardPosition()
|
||||
case .cheat:
|
||||
memoryField.isHidden = true
|
||||
editFieldsStackView.isHidden = true
|
||||
|
@ -473,6 +601,7 @@ extension DebugMemoryActionViewController: EmulatorKeyboardKeyPressedDelegate {
|
|||
extension DebugMemoryActionViewController: DebugMemoryViewControllerDelegate {
|
||||
func refreshActionController() {
|
||||
update()
|
||||
updateMatchedInstructions()
|
||||
}
|
||||
func updateEmulatorScreen() {
|
||||
let emulatorView = EmuWrapper.getEmulatorView()
|
||||
|
@ -485,29 +614,49 @@ extension DebugMemoryActionViewController: DebugMemoryViewControllerDelegate {
|
|||
|
||||
extension DebugMemoryActionViewController: UITableViewDataSource {
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return cheatFinder.matchedMemoryAddresses.keys.count
|
||||
if tableView == findInCodeResultsTableView {
|
||||
return matchedInstructions.count
|
||||
} else {
|
||||
return cheatFinder.matchedMemoryAddresses.keys.count
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "CheatFinderMatchCell", for: indexPath)
|
||||
let addresses = cheatFinder.matchedMemoryAddresses.keys
|
||||
let index = addresses.index(addresses.startIndex, offsetBy: indexPath.row)
|
||||
let address = addresses[index]
|
||||
cell.textLabel?.text = String(format: "%04X",address)
|
||||
cell.textLabel?.font = UIFont(name: "Print Char 21", size: 14)
|
||||
cell.textLabel?.textColor = .red
|
||||
cell.textLabel?.textAlignment = .center
|
||||
return cell
|
||||
if tableView == findInCodeResultsTableView {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "FindInCodeResultsCell", for: indexPath)
|
||||
let instruction = matchedInstructions[indexPath.row]
|
||||
cell.textLabel?.text = instruction.description
|
||||
cell.textLabel?.font = UIFont(name: "Print Char 21", size: 11)
|
||||
cell.textLabel?.textColor = .yellow
|
||||
cell.textLabel?.textAlignment = .center
|
||||
return cell
|
||||
} else {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "CheatFinderMatchCell", for: indexPath)
|
||||
let addresses = cheatFinder.matchedMemoryAddresses.keys
|
||||
let index = addresses.index(addresses.startIndex, offsetBy: indexPath.row)
|
||||
let address = addresses[index]
|
||||
cell.textLabel?.text = String(format: "%04X: %02X",address,cheatFinder.matchedMemoryAddresses[address]!)
|
||||
cell.textLabel?.font = UIFont(name: "Print Char 21", size: 14)
|
||||
cell.textLabel?.textColor = .red
|
||||
cell.textLabel?.textAlignment = .center
|
||||
return cell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension DebugMemoryActionViewController: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let addresses = cheatFinder.matchedMemoryAddresses.keys
|
||||
let index = addresses.index(addresses.startIndex, offsetBy: indexPath.row)
|
||||
let address = addresses[index]
|
||||
delegate?.jump(to: address)
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
if tableView == findInCodeResultsTableView {
|
||||
let instruction = matchedInstructions[indexPath.row]
|
||||
let address = instruction.address
|
||||
delegate?.jump(to: Int(address))
|
||||
} else {
|
||||
let addresses = cheatFinder.matchedMemoryAddresses.keys
|
||||
let index = addresses.index(addresses.startIndex, offsetBy: indexPath.row)
|
||||
let address = addresses[index]
|
||||
delegate?.jump(to: address)
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -219,10 +219,10 @@ protocol DebugMemoryViewControllerDelegate: class {
|
|||
actionController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(actionController.view)
|
||||
actionController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
actionControllerBottomConstraint = actionController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 250)
|
||||
actionControllerBottomConstraint = actionController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 250)
|
||||
actionControllerBottomConstraint?.isActive = true
|
||||
|
||||
actionControllerHeightConstraint = actionController.view.heightAnchor.constraint(equalToConstant: 320)
|
||||
actionControllerHeightConstraint = actionController.view.heightAnchor.constraint(equalToConstant: 380)
|
||||
actionControllerLeadingToViewLeadingConstraint = actionController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor)
|
||||
actionControllerTopToTableViewBottomConstraint = actionController.view.topAnchor.constraint(equalTo: dataTableView.bottomAnchor)
|
||||
tableViewTrailingToViewTrailingConstraint = dataTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8)
|
||||
|
@ -303,6 +303,17 @@ protocol DebugMemoryViewControllerDelegate: class {
|
|||
framesSinceUpdateScreen += 1
|
||||
}
|
||||
|
||||
func registerAppleIIFont() {
|
||||
let fontUrl = Bundle.main.url(forResource: "PrintChar21", withExtension: "ttf")
|
||||
CTFontManagerRegisterFontURLs([fontUrl] as CFArray, .persistent, true) { errors, done -> Bool in
|
||||
if(done) {
|
||||
print("Done installing custom font!")
|
||||
}
|
||||
print(errors as Array)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupView()
|
||||
|
@ -310,6 +321,7 @@ protocol DebugMemoryViewControllerDelegate: class {
|
|||
setupTableView()
|
||||
setupPauseResumeButton()
|
||||
memoryViewModeControlChanged(memoryViewModeControl)
|
||||
// registerAppleIIFont()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
@ -379,6 +391,9 @@ extension DebugMemoryViewController: UITableViewDataSource {
|
|||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
if tableView == codeTableView {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: DebugMemoryCell.identifier, for: indexPath) as! DebugMemoryCell
|
||||
if indexPath.row >= memoryModel.interpretedInstructions.count {
|
||||
return cell
|
||||
}
|
||||
let instruction = memoryModel.interpretedInstructions[indexPath.row]
|
||||
let values = [
|
||||
instruction.instruction.mnemonic.description,
|
||||
|
@ -461,6 +476,12 @@ extension DebugMemoryViewController: DebugMemoryActionViewControllerDelegate {
|
|||
print("jumping to address: \(String(format: "%04X",address)) decimal: \(address)")
|
||||
let indexPath = memoryModel.indexPath(for: address)
|
||||
dataTableView.scrollToRow(at: indexPath, at: .middle, animated: true)
|
||||
|
||||
if let codeIndex = memoryModel.interpretedInstructions.firstIndex(where: { $0.address == address }) {
|
||||
let indexPath = IndexPath(row: codeIndex, section: 0)
|
||||
codeTableView.scrollToRow(at: indexPath, at: .middle, animated: true)
|
||||
}
|
||||
|
||||
updateSelection(to: address)
|
||||
}
|
||||
func memoryHex(at address: Int) -> String {
|
||||
|
@ -472,4 +493,7 @@ extension DebugMemoryViewController: DebugMemoryActionViewControllerDelegate {
|
|||
var selectedAddress: Int? {
|
||||
return memoryModel.selectedAddress
|
||||
}
|
||||
var referencedMemoryAddresses: [UInt16: [AddressedInstruction]] {
|
||||
return memoryModel.referencedAddresses
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue