mirror of https://github.com/LIJI32/SameBoy.git
The Cocoa memory viewer new symbolicates the selection
This commit is contained in:
parent
ac45888a37
commit
fb3db82d42
|
@ -13,6 +13,7 @@
|
||||||
#import "GBPaletteEditorController.h"
|
#import "GBPaletteEditorController.h"
|
||||||
#import "GBObjectView.h"
|
#import "GBObjectView.h"
|
||||||
#import "GBPaletteView.h"
|
#import "GBPaletteView.h"
|
||||||
|
#import "GBHexStatusBarRepresenter.h"
|
||||||
#import "NSObject+DefaultsObserver.h"
|
#import "NSObject+DefaultsObserver.h"
|
||||||
|
|
||||||
#define likely(x) GB_likely(x)
|
#define likely(x) GB_likely(x)
|
||||||
|
@ -82,6 +83,7 @@ enum model {
|
||||||
|
|
||||||
NSString *_lastConsoleInput;
|
NSString *_lastConsoleInput;
|
||||||
HFLineCountingRepresenter *_lineRep;
|
HFLineCountingRepresenter *_lineRep;
|
||||||
|
GBHexStatusBarRepresenter *_statusRep;
|
||||||
|
|
||||||
CVImageBufferRef _cameraImage;
|
CVImageBufferRef _cameraImage;
|
||||||
AVCaptureSession *_cameraSession;
|
AVCaptureSession *_cameraSession;
|
||||||
|
@ -878,7 +880,9 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
||||||
HFStringEncodingTextRepresenter *asciiRep = [[HFStringEncodingTextRepresenter alloc] init];
|
HFStringEncodingTextRepresenter *asciiRep = [[HFStringEncodingTextRepresenter alloc] init];
|
||||||
HFVerticalScrollerRepresenter *scrollRep = [[HFVerticalScrollerRepresenter alloc] init];
|
HFVerticalScrollerRepresenter *scrollRep = [[HFVerticalScrollerRepresenter alloc] init];
|
||||||
_lineRep = [[HFLineCountingRepresenter alloc] init];
|
_lineRep = [[HFLineCountingRepresenter alloc] init];
|
||||||
HFStatusBarRepresenter *statusRep = [[HFStatusBarRepresenter alloc] init];
|
_statusRep = [[GBHexStatusBarRepresenter alloc] init];
|
||||||
|
_statusRep.gb = &_gb;
|
||||||
|
_statusRep.bankForDescription = -1;
|
||||||
|
|
||||||
_lineRep.lineNumberFormat = HFLineNumberFormatHexadecimal;
|
_lineRep.lineNumberFormat = HFLineNumberFormatHexadecimal;
|
||||||
|
|
||||||
|
@ -888,14 +892,14 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
||||||
[_hexController addRepresenter:asciiRep];
|
[_hexController addRepresenter:asciiRep];
|
||||||
[_hexController addRepresenter:scrollRep];
|
[_hexController addRepresenter:scrollRep];
|
||||||
[_hexController addRepresenter:_lineRep];
|
[_hexController addRepresenter:_lineRep];
|
||||||
[_hexController addRepresenter:statusRep];
|
[_hexController addRepresenter:_statusRep];
|
||||||
|
|
||||||
/* Tell the layout rep which reps it should lay out. */
|
/* Tell the layout rep which reps it should lay out. */
|
||||||
[layoutRep addRepresenter:hexRep];
|
[layoutRep addRepresenter:hexRep];
|
||||||
[layoutRep addRepresenter:scrollRep];
|
[layoutRep addRepresenter:scrollRep];
|
||||||
[layoutRep addRepresenter:asciiRep];
|
[layoutRep addRepresenter:asciiRep];
|
||||||
[layoutRep addRepresenter:_lineRep];
|
[layoutRep addRepresenter:_lineRep];
|
||||||
[layoutRep addRepresenter:statusRep];
|
[layoutRep addRepresenter:_statusRep];
|
||||||
|
|
||||||
|
|
||||||
[(NSView *)[hexRep view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
[(NSView *)[hexRep view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||||
|
@ -1827,6 +1831,7 @@ static bool is_path_writeable(const char *path)
|
||||||
|
|
||||||
[sender setStringValue:[NSString stringWithFormat:@"$%x", bank]];
|
[sender setStringValue:[NSString stringWithFormat:@"$%x", bank]];
|
||||||
[(GBMemoryByteArray *)(_hexController.byteArray) setSelectedBank:bank];
|
[(GBMemoryByteArray *)(_hexController.byteArray) setSelectedBank:bank];
|
||||||
|
_statusRep.bankForDescription = bank;
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[_hexController reloadData];
|
[_hexController reloadData];
|
||||||
});
|
});
|
||||||
|
@ -1846,33 +1851,37 @@ static bool is_path_writeable(const char *path)
|
||||||
- (IBAction)hexUpdateSpace:(NSPopUpButtonCell *)sender
|
- (IBAction)hexUpdateSpace:(NSPopUpButtonCell *)sender
|
||||||
{
|
{
|
||||||
self.memoryBankItem.enabled = [sender indexOfSelectedItem] != GBMemoryEntireSpace;
|
self.memoryBankItem.enabled = [sender indexOfSelectedItem] != GBMemoryEntireSpace;
|
||||||
|
[_hexController setSelectedContentsRanges:@[[HFRangeWrapper withRange:HFRangeMake(0, 0)]]];
|
||||||
GBMemoryByteArray *byteArray = (GBMemoryByteArray *)(_hexController.byteArray);
|
GBMemoryByteArray *byteArray = (GBMemoryByteArray *)(_hexController.byteArray);
|
||||||
[byteArray setMode:(GB_memory_mode_t)[sender indexOfSelectedItem]];
|
[byteArray setMode:(GB_memory_mode_t)[sender indexOfSelectedItem]];
|
||||||
uint16_t bank;
|
uint16_t bank = -1;
|
||||||
switch ((GB_memory_mode_t)[sender indexOfSelectedItem]) {
|
switch ((GB_memory_mode_t)[sender indexOfSelectedItem]) {
|
||||||
case GBMemoryEntireSpace:
|
case GBMemoryEntireSpace:
|
||||||
|
_statusRep.baseAddress = _lineRep.valueOffset = 0;
|
||||||
|
break;
|
||||||
case GBMemoryROM:
|
case GBMemoryROM:
|
||||||
_lineRep.valueOffset = 0;
|
_statusRep.baseAddress = _lineRep.valueOffset = 0;
|
||||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, NULL, &bank);
|
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, NULL, &bank);
|
||||||
byteArray.selectedBank = bank;
|
|
||||||
break;
|
break;
|
||||||
case GBMemoryVRAM:
|
case GBMemoryVRAM:
|
||||||
_lineRep.valueOffset = 0x8000;
|
_statusRep.baseAddress = _lineRep.valueOffset = 0x8000;
|
||||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_VRAM, NULL, &bank);
|
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_VRAM, NULL, &bank);
|
||||||
byteArray.selectedBank = bank;
|
|
||||||
break;
|
break;
|
||||||
case GBMemoryExternalRAM:
|
case GBMemoryExternalRAM:
|
||||||
_lineRep.valueOffset = 0xA000;
|
_statusRep.baseAddress = _lineRep.valueOffset = 0xA000;
|
||||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_CART_RAM, NULL, &bank);
|
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_CART_RAM, NULL, &bank);
|
||||||
byteArray.selectedBank = bank;
|
|
||||||
break;
|
break;
|
||||||
case GBMemoryRAM:
|
case GBMemoryRAM:
|
||||||
_lineRep.valueOffset = 0xC000;
|
_statusRep.baseAddress = _lineRep.valueOffset = 0xC000;
|
||||||
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_RAM, NULL, &bank);
|
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_RAM, NULL, &bank);
|
||||||
byteArray.selectedBank = bank;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[self.memoryBankInput setStringValue:[NSString stringWithFormat:@"$%x", byteArray.selectedBank]];
|
byteArray.selectedBank = bank;
|
||||||
|
_statusRep.bankForDescription = bank;
|
||||||
|
if (bank != (uint16_t)-1) {
|
||||||
|
[self.memoryBankInput setStringValue:[NSString stringWithFormat:@"$%x", byteArray.selectedBank]];
|
||||||
|
}
|
||||||
|
|
||||||
[_hexController reloadData];
|
[_hexController reloadData];
|
||||||
for (NSView *view in self.memoryView.subviews) {
|
for (NSView *view in self.memoryView.subviews) {
|
||||||
[view setNeedsDisplay:true];
|
[view setNeedsDisplay:true];
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#import <Core/gb.h>
|
||||||
|
#import <HexFiend/HFRepresenter.h>
|
||||||
|
|
||||||
|
|
||||||
|
@interface GBHexStatusBarRepresenter : HFRepresenter
|
||||||
|
@property GB_gameboy_t *gb;
|
||||||
|
@property (nonatomic) bool useDecimalLength;
|
||||||
|
@property (nonatomic) uint16_t bankForDescription;
|
||||||
|
@property (nonatomic) uint16_t baseAddress;
|
||||||
|
@end
|
|
@ -0,0 +1,220 @@
|
||||||
|
#import "GBHexStatusBarRepresenter.h"
|
||||||
|
#import <HexFiend/HFFunctions.h>
|
||||||
|
|
||||||
|
@interface GBHexStatusBarView : NSView
|
||||||
|
{
|
||||||
|
NSCell *_cell;
|
||||||
|
NSSize _cellSize;
|
||||||
|
GBHexStatusBarRepresenter *_representer;
|
||||||
|
NSDictionary *_cellAttributes;
|
||||||
|
bool _registeredForAppNotifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRepresenter:(GBHexStatusBarRepresenter *)rep;
|
||||||
|
- (void)setString:(NSString *)string;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation GBHexStatusBarView
|
||||||
|
|
||||||
|
- (void)_sharedInitStatusBarView
|
||||||
|
{
|
||||||
|
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||||
|
[style setAlignment:NSCenterTextAlignment];
|
||||||
|
style.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||||
|
_cellAttributes = @{
|
||||||
|
NSForegroundColorAttributeName: [NSColor windowFrameTextColor],
|
||||||
|
NSFontAttributeName: [NSFont labelFontOfSize:[NSFont smallSystemFontSize]],
|
||||||
|
NSParagraphStyleAttributeName: style,
|
||||||
|
};
|
||||||
|
_cell = [[NSCell alloc] initTextCell:@""];
|
||||||
|
[_cell setAlignment:NSCenterTextAlignment];
|
||||||
|
[_cell setBackgroundStyle:NSBackgroundStyleRaised];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(NSRect)frame
|
||||||
|
{
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
[self _sharedInitStatusBarView];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||||
|
{
|
||||||
|
self = [super initWithCoder:coder];
|
||||||
|
[self _sharedInitStatusBarView];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isFlipped
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRepresenter:(GBHexStatusBarRepresenter *)rep
|
||||||
|
{
|
||||||
|
_representer = rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setString:(NSString *)string
|
||||||
|
{
|
||||||
|
[_cell setAttributedStringValue:[[NSAttributedString alloc] initWithString:string attributes:_cellAttributes]];
|
||||||
|
_cellSize = [_cell cellSize];
|
||||||
|
[self setNeedsDisplay:true];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawRect:(NSRect)clip
|
||||||
|
{
|
||||||
|
NSRect bounds = [self bounds];
|
||||||
|
NSRect cellRect = NSMakeRect(NSMinX(bounds), HFCeil(NSMidY(bounds) - _cellSize.height / 2), NSWidth(bounds), _cellSize.height);
|
||||||
|
[_cell drawWithFrame:cellRect inView:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setFrame:(NSRect)frame
|
||||||
|
{
|
||||||
|
[super setFrame:frame];
|
||||||
|
[self.window setContentBorderThickness:frame.origin.y + frame.size.height forEdge:NSMinYEdge];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent *)event
|
||||||
|
{
|
||||||
|
_representer.useDecimalLength ^= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)windowDidChangeKeyStatus:(NSNotification *)note
|
||||||
|
{
|
||||||
|
[self setNeedsDisplay:true];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidMoveToWindow
|
||||||
|
{
|
||||||
|
HFRegisterViewForWindowAppearanceChanges(self, @selector(windowDidChangeKeyStatus:), !_registeredForAppNotifications);
|
||||||
|
_registeredForAppNotifications = true;
|
||||||
|
[self.window setContentBorderThickness:self.frame.origin.y + self.frame.size.height forEdge:NSMinYEdge];
|
||||||
|
[super viewDidMoveToWindow];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
|
||||||
|
{
|
||||||
|
HFUnregisterViewForWindowAppearanceChanges(self, NO);
|
||||||
|
[super viewWillMoveToWindow:newWindow];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
HFUnregisterViewForWindowAppearanceChanges(self, _registeredForAppNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GBHexStatusBarRepresenter
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSView *)createView {
|
||||||
|
GBHexStatusBarView *view = [[GBHexStatusBarView alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
|
||||||
|
[view setRepresenter:self];
|
||||||
|
[view setAutoresizingMask:NSViewWidthSizable];
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)describeLength:(unsigned long long)length
|
||||||
|
{
|
||||||
|
if (self.useDecimalLength) {
|
||||||
|
return [NSString stringWithFormat:@"%llu byte%s", length, length == 1 ? "" : "s"];
|
||||||
|
}
|
||||||
|
return [NSString stringWithFormat:@"$%llX byte%s", length, length == 1 ? "" : "s"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)describeOffset:(unsigned long long)offset isRangeEnd:(bool)isRangeEnd
|
||||||
|
{
|
||||||
|
if (!_gb) {
|
||||||
|
return [NSString stringWithFormat:@"$%llX", offset];
|
||||||
|
}
|
||||||
|
return @(GB_debugger_describe_address(_gb, offset + _baseAddress, _bankForDescription, false, isRangeEnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (NSString *)stringForEmptySelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
|
||||||
|
{
|
||||||
|
return [self describeOffset:offset isRangeEnd:false];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)stringForSingleByteSelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat:@"Byte %@ selected", [self describeOffset:offset isRangeEnd:false]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)stringForSingleRangeSelection:(HFRange)range length:(unsigned long long)length
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat:@"Range %@ to %@ selected (%@)",
|
||||||
|
[self describeOffset:range.location isRangeEnd:false],
|
||||||
|
[self describeOffset:range.location + range.length isRangeEnd:true],
|
||||||
|
[self describeLength:range.length]];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)updateString
|
||||||
|
{
|
||||||
|
NSString *string = nil;
|
||||||
|
HFController *controller = [self controller];
|
||||||
|
if (controller) {
|
||||||
|
unsigned long long length = [controller contentsLength];
|
||||||
|
NSArray *ranges = [controller selectedContentsRanges];
|
||||||
|
NSUInteger rangeCount = [ranges count];
|
||||||
|
if (rangeCount == 1) {
|
||||||
|
HFRange range = [ranges[0] HFRange];
|
||||||
|
if (range.length == 0) {
|
||||||
|
string = [self stringForEmptySelectionAtOffset:range.location length:length];
|
||||||
|
}
|
||||||
|
else if (range.length == 1) {
|
||||||
|
string = [self stringForSingleByteSelectionAtOffset:range.location length:length];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string = [self stringForSingleRangeSelection:range length:length];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string = @"Multiple ranges selected";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! string) string = @"";
|
||||||
|
[[self view] setString:string];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setUseDecimalLength:(bool)useDecimalLength
|
||||||
|
{
|
||||||
|
_useDecimalLength = useDecimalLength;
|
||||||
|
[self updateString];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setBaseAddress:(uint16_t)baseAddress
|
||||||
|
{
|
||||||
|
_baseAddress = baseAddress;
|
||||||
|
[self updateString];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setBankForDescription:(uint16_t)bankForDescription
|
||||||
|
{
|
||||||
|
_bankForDescription = bankForDescription;
|
||||||
|
[self updateString];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)controllerDidChange:(HFControllerPropertyBits)bits
|
||||||
|
{
|
||||||
|
if (bits & (HFControllerContentLength | HFControllerSelectedRanges)) {
|
||||||
|
[self updateString];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSPoint)defaultLayoutPosition
|
||||||
|
{
|
||||||
|
return NSMakePoint(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -2606,16 +2606,37 @@ const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr,
|
||||||
|
|
||||||
const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr, prefer_local);
|
const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr, prefer_local);
|
||||||
if (symbol) return symbol;
|
if (symbol) return symbol;
|
||||||
if (bank != 0) return GB_map_find_symbol(get_symbol_map(gb, 0), addr, false); /* Maybe the symbol incorrectly uses bank 0? */
|
if (bank != 0) return GB_map_find_symbol(get_symbol_map(gb, 0), addr, prefer_local); /* Maybe the symbol incorrectly uses bank 0? */
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr)
|
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr)
|
||||||
{
|
{
|
||||||
const GB_bank_symbol_t *symbol = GB_debugger_find_symbol(gb, addr, false);
|
return GB_debugger_describe_address(gb, addr, -1, true, false);
|
||||||
if (symbol && symbol->addr == addr) return symbol->name;
|
}
|
||||||
return NULL;
|
|
||||||
|
const char *GB_debugger_describe_address(GB_gameboy_t *gb,
|
||||||
|
uint16_t addr, uint16_t bank,
|
||||||
|
bool exact_match, bool prefer_local)
|
||||||
|
{
|
||||||
|
if (bank == (uint16_t)-1) {
|
||||||
|
bank = bank_for_addr(gb, addr);
|
||||||
|
}
|
||||||
|
if (exact_match) {
|
||||||
|
const GB_bank_symbol_t *symbol = GB_map_find_symbol(get_symbol_map(gb, bank), addr, prefer_local);
|
||||||
|
if (symbol && symbol->addr == addr) return symbol->name;
|
||||||
|
if (bank != 0) symbol = GB_map_find_symbol(get_symbol_map(gb, 0), addr, prefer_local); /* Maybe the symbol incorrectly uses bank 0? */
|
||||||
|
if (symbol && symbol->addr == addr) return symbol->name;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return debugger_value_to_string(gb, (value_t){
|
||||||
|
.value = addr,
|
||||||
|
.bank = bank,
|
||||||
|
.has_bank = true,
|
||||||
|
}, true, prefer_local);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The public version of debugger_evaluate */
|
/* The public version of debugger_evaluate */
|
||||||
|
|
|
@ -15,6 +15,8 @@ GB_debugger_execute_command(GB_gameboy_t *gb, char *input); /* Destroys input. *
|
||||||
char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context); /* Destroys input, result requires free */
|
char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context); /* Destroys input, result requires free */
|
||||||
void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path);
|
void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path);
|
||||||
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr);
|
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr);
|
||||||
|
/* Use -1 for bank to use the currently mapped bank */
|
||||||
|
const char *GB_debugger_describe_address(GB_gameboy_t *gb, uint16_t addr, uint16_t bank, bool exact_match, bool prefer_local);
|
||||||
bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result, uint16_t *result_bank); /* result_bank is -1 if unused. */
|
bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result, uint16_t *result_bank); /* result_bank is -1 if unused. */
|
||||||
bool GB_debugger_is_stopped(GB_gameboy_t *gb);
|
bool GB_debugger_is_stopped(GB_gameboy_t *gb);
|
||||||
void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled);
|
void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled);
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
//
|
|
||||||
// HFStatusBarRepresenter.h
|
|
||||||
// HexFiend_2
|
|
||||||
//
|
|
||||||
// Copyright 2007 ridiculous_fish. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <HexFiend/HFRepresenter.h>
|
|
||||||
|
|
||||||
/*! @enum HFStatusBarMode
|
|
||||||
The HFStatusBarMode enum is used to describe the format of the byte counts displayed by the status bar.
|
|
||||||
*/
|
|
||||||
typedef NS_ENUM(NSUInteger, HFStatusBarMode) {
|
|
||||||
HFStatusModeDecimal, ///< The status bar should display byte counts in decimal
|
|
||||||
HFStatusModeHexadecimal, ///< The status bar should display byte counts in hexadecimal
|
|
||||||
HFStatusModeApproximate, ///< The text should display byte counts approximately (e.g. "56.3 KB")
|
|
||||||
HFSTATUSMODECOUNT ///< The number of modes, to allow easy cycling
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! @class HFStatusBarRepresenter
|
|
||||||
@brief The HFRepresenter for the status bar.
|
|
||||||
|
|
||||||
HFStatusBarRepresenter is a subclass of HFRepresenter responsible for showing the status bar, which displays information like the total length of the document, or the number of selected bytes.
|
|
||||||
*/
|
|
||||||
@interface HFStatusBarRepresenter : HFRepresenter {
|
|
||||||
HFStatusBarMode statusMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (nonatomic) HFStatusBarMode statusMode;
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,240 +0,0 @@
|
||||||
//
|
|
||||||
// HFStatusBarRepresenter.m
|
|
||||||
// HexFiend_2
|
|
||||||
//
|
|
||||||
// Copyright 2007 ridiculous_fish. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <HexFiend/HFStatusBarRepresenter.h>
|
|
||||||
#import <HexFiend/HFFunctions.h>
|
|
||||||
|
|
||||||
#define kHFStatusBarDefaultModeUserDefaultsKey @"HFStatusBarDefaultMode"
|
|
||||||
|
|
||||||
@interface HFStatusBarView : NSView {
|
|
||||||
NSCell *cell;
|
|
||||||
NSSize cellSize;
|
|
||||||
HFStatusBarRepresenter *representer;
|
|
||||||
NSDictionary *cellAttributes;
|
|
||||||
BOOL registeredForAppNotifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setRepresenter:(HFStatusBarRepresenter *)rep;
|
|
||||||
- (void)setString:(NSString *)string;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
@implementation HFStatusBarView
|
|
||||||
|
|
||||||
- (void)_sharedInitStatusBarView {
|
|
||||||
NSMutableParagraphStyle *style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
|
|
||||||
[style setAlignment:NSCenterTextAlignment];
|
|
||||||
cellAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSColor windowFrameTextColor], NSForegroundColorAttributeName, [NSFont labelFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, style, NSParagraphStyleAttributeName, nil];
|
|
||||||
cell = [[NSCell alloc] initTextCell:@""];
|
|
||||||
[cell setAlignment:NSCenterTextAlignment];
|
|
||||||
[cell setBackgroundStyle:NSBackgroundStyleRaised];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(NSRect)frame {
|
|
||||||
self = [super initWithFrame:frame];
|
|
||||||
[self _sharedInitStatusBarView];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
|
||||||
HFASSERT([coder allowsKeyedCoding]);
|
|
||||||
self = [super initWithCoder:coder];
|
|
||||||
[self _sharedInitStatusBarView];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nothing to do in encodeWithCoder
|
|
||||||
|
|
||||||
- (BOOL)isFlipped { return YES; }
|
|
||||||
|
|
||||||
- (void)setRepresenter:(HFStatusBarRepresenter *)rep {
|
|
||||||
representer = rep;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setString:(NSString *)string {
|
|
||||||
[cell setAttributedStringValue:[[[NSAttributedString alloc] initWithString:string attributes:cellAttributes] autorelease]];
|
|
||||||
cellSize = [cell cellSize];
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)clip {
|
|
||||||
USE(clip);
|
|
||||||
NSRect bounds = [self bounds];
|
|
||||||
// [[NSColor colorWithCalibratedWhite:(CGFloat).91 alpha:1] set];
|
|
||||||
// NSRectFill(clip);
|
|
||||||
|
|
||||||
|
|
||||||
NSRect cellRect = NSMakeRect(NSMinX(bounds), HFCeil(NSMidY(bounds) - cellSize.height / 2), NSWidth(bounds), cellSize.height);
|
|
||||||
[cell drawWithFrame:cellRect inView:self];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setFrame:(NSRect)frame
|
|
||||||
{
|
|
||||||
[super setFrame:frame];
|
|
||||||
[self.window setContentBorderThickness:frame.origin.y + frame.size.height forEdge:NSMinYEdge];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void)mouseDown:(NSEvent *)event {
|
|
||||||
USE(event);
|
|
||||||
HFStatusBarMode newMode = ([representer statusMode] + 1) % HFSTATUSMODECOUNT;
|
|
||||||
[representer setStatusMode:newMode];
|
|
||||||
[[NSUserDefaults standardUserDefaults] setInteger:newMode forKey:kHFStatusBarDefaultModeUserDefaultsKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)windowDidChangeKeyStatus:(NSNotification *)note {
|
|
||||||
USE(note);
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewDidMoveToWindow {
|
|
||||||
HFRegisterViewForWindowAppearanceChanges(self, @selector(windowDidChangeKeyStatus:), !registeredForAppNotifications);
|
|
||||||
registeredForAppNotifications = YES;
|
|
||||||
[self.window setContentBorderThickness:self.frame.origin.y + self.frame.size.height forEdge:NSMinYEdge];
|
|
||||||
[super viewDidMoveToWindow];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
|
|
||||||
HFUnregisterViewForWindowAppearanceChanges(self, NO);
|
|
||||||
[super viewWillMoveToWindow:newWindow];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc {
|
|
||||||
HFUnregisterViewForWindowAppearanceChanges(self, registeredForAppNotifications);
|
|
||||||
[cell release];
|
|
||||||
[cellAttributes release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation HFStatusBarRepresenter
|
|
||||||
|
|
||||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
|
||||||
HFASSERT([coder allowsKeyedCoding]);
|
|
||||||
[super encodeWithCoder:coder];
|
|
||||||
[coder encodeInt64:statusMode forKey:@"HFStatusMode"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
|
||||||
HFASSERT([coder allowsKeyedCoding]);
|
|
||||||
self = [super initWithCoder:coder];
|
|
||||||
statusMode = (NSUInteger)[coder decodeInt64ForKey:@"HFStatusMode"];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)init {
|
|
||||||
self = [super init];
|
|
||||||
statusMode = [[NSUserDefaults standardUserDefaults] integerForKey:kHFStatusBarDefaultModeUserDefaultsKey];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSView *)createView {
|
|
||||||
HFStatusBarView *view = [[HFStatusBarView alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
|
|
||||||
[view setRepresenter:self];
|
|
||||||
[view setAutoresizingMask:NSViewWidthSizable];
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)describeLength:(unsigned long long)length {
|
|
||||||
switch (statusMode) {
|
|
||||||
case HFStatusModeDecimal: return [NSString stringWithFormat:@"%llu byte%s", length, length == 1 ? "" : "s"];
|
|
||||||
case HFStatusModeHexadecimal: return [NSString stringWithFormat:@"0x%llX byte%s", length, length == 1 ? "" : "s"];
|
|
||||||
case HFStatusModeApproximate: return [NSString stringWithFormat:@"%@", HFDescribeByteCount(length)];
|
|
||||||
default: [NSException raise:NSInternalInconsistencyException format:@"Unknown status mode %lu", (unsigned long)statusMode]; return @"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)describeOffset:(unsigned long long)offset {
|
|
||||||
switch (statusMode) {
|
|
||||||
case HFStatusModeDecimal: return [NSString stringWithFormat:@"%llu", offset];
|
|
||||||
case HFStatusModeHexadecimal: return [NSString stringWithFormat:@"0x%llX", offset];
|
|
||||||
case HFStatusModeApproximate: return [NSString stringWithFormat:@"%@", HFDescribeByteCount(offset)];
|
|
||||||
default: [NSException raise:NSInternalInconsistencyException format:@"Unknown status mode %lu", (unsigned long)statusMode]; return @"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* same as describeOffset, except we treat Approximate like Hexadecimal */
|
|
||||||
- (NSString *)describeOffsetExcludingApproximate:(unsigned long long)offset {
|
|
||||||
switch (statusMode) {
|
|
||||||
case HFStatusModeDecimal: return [NSString stringWithFormat:@"%llu", offset];
|
|
||||||
case HFStatusModeHexadecimal:
|
|
||||||
case HFStatusModeApproximate: return [NSString stringWithFormat:@"0x%llX", offset];
|
|
||||||
default: [NSException raise:NSInternalInconsistencyException format:@"Unknown status mode %lu", (unsigned long)statusMode]; return @"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)stringForEmptySelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length {
|
|
||||||
return [NSString stringWithFormat:@"%@ out of %@", [self describeOffset:offset], [self describeLength:length]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)stringForSingleByteSelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length {
|
|
||||||
return [NSString stringWithFormat:@"Byte %@ selected out of %@", [self describeOffset:offset], [self describeLength:length]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)stringForSingleRangeSelection:(HFRange)range length:(unsigned long long)length {
|
|
||||||
return [NSString stringWithFormat:@"%@ selected at offset %@ out of %@", [self describeLength:range.length], [self describeOffsetExcludingApproximate:range.location], [self describeLength:length]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)stringForMultipleSelectionsWithLength:(unsigned long long)multipleSelectionLength length:(unsigned long long)length {
|
|
||||||
return [NSString stringWithFormat:@"%@ selected at multiple offsets out of %@", [self describeLength:multipleSelectionLength], [self describeLength:length]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void)updateString {
|
|
||||||
NSString *string = nil;
|
|
||||||
HFController *controller = [self controller];
|
|
||||||
if (controller) {
|
|
||||||
unsigned long long length = [controller contentsLength];
|
|
||||||
NSArray *ranges = [controller selectedContentsRanges];
|
|
||||||
NSUInteger rangeCount = [ranges count];
|
|
||||||
if (rangeCount == 1) {
|
|
||||||
HFRange range = [ranges[0] HFRange];
|
|
||||||
if (range.length == 0) {
|
|
||||||
string = [self stringForEmptySelectionAtOffset:range.location length:length];
|
|
||||||
}
|
|
||||||
else if (range.length == 1) {
|
|
||||||
string = [self stringForSingleByteSelectionAtOffset:range.location length:length];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
string = [self stringForSingleRangeSelection:range length:length];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unsigned long long totalSelectionLength = 0;
|
|
||||||
FOREACH(HFRangeWrapper *, wrapper, ranges) {
|
|
||||||
HFRange range = [wrapper HFRange];
|
|
||||||
totalSelectionLength = HFSum(totalSelectionLength, range.length);
|
|
||||||
}
|
|
||||||
string = [self stringForMultipleSelectionsWithLength:totalSelectionLength length:length];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! string) string = @"";
|
|
||||||
[[self view] setString:string];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (HFStatusBarMode)statusMode {
|
|
||||||
return statusMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setStatusMode:(HFStatusBarMode)mode {
|
|
||||||
statusMode = mode;
|
|
||||||
[self updateString];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)controllerDidChange:(HFControllerPropertyBits)bits {
|
|
||||||
if (bits & (HFControllerContentLength | HFControllerSelectedRanges)) {
|
|
||||||
[self updateString];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSPoint)defaultLayoutPosition {
|
|
||||||
return NSMakePoint(0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -28,7 +28,6 @@
|
||||||
#import <HexFiend/HFFullMemoryByteSlice.h>
|
#import <HexFiend/HFFullMemoryByteSlice.h>
|
||||||
#import <HexFiend/HFHexTextRepresenter.h>
|
#import <HexFiend/HFHexTextRepresenter.h>
|
||||||
#import <HexFiend/HFLineCountingRepresenter.h>
|
#import <HexFiend/HFLineCountingRepresenter.h>
|
||||||
#import <HexFiend/HFStatusBarRepresenter.h>
|
|
||||||
#import <HexFiend/HFLayoutRepresenter.h>
|
#import <HexFiend/HFLayoutRepresenter.h>
|
||||||
#import <HexFiend/HFStringEncodingTextRepresenter.h>
|
#import <HexFiend/HFStringEncodingTextRepresenter.h>
|
||||||
#import <HexFiend/HFVerticalScrollerRepresenter.h>
|
#import <HexFiend/HFVerticalScrollerRepresenter.h>
|
||||||
|
|
Loading…
Reference in New Issue