summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/sdl/debugosx.m
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2010-01-13 04:01:20 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2010-01-13 04:01:20 +0000
commitb53bb2c6acce9ab44b48d18c76a9059261e97548 (patch)
tree33e03fd2fd5dd91dedac105de03e28fdc9cab3d3 /src/osd/sdl/debugosx.m
parentf8b28bd2f1f915b3c463dce87b6035d95aa2c9f5 (diff)
SDLMAME initial import [R. Belmont, Couriersud]
Diffstat (limited to 'src/osd/sdl/debugosx.m')
-rw-r--r--src/osd/sdl/debugosx.m2352
1 files changed, 2352 insertions, 0 deletions
diff --git a/src/osd/sdl/debugosx.m b/src/osd/sdl/debugosx.m
new file mode 100644
index 00000000000..cf6516dbb52
--- /dev/null
+++ b/src/osd/sdl/debugosx.m
@@ -0,0 +1,2352 @@
+//============================================================
+//
+// debugosx.m - MacOS X Cocoa debug window handling
+//
+// Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
+// Visit http://mamedev.org for licensing and usage restrictions.
+//
+//============================================================
+
+
+// TODO:
+// * Automatic scrolling for console and log views
+// * Using alpha for disabled foreground colours doesn't really work
+// * New windows created from auxiliary windows should inherit focus rather than pointing at current CPU
+// * Should have map of machine to console for multiple machine support rather than a single console
+// * Improve behaviour of expression history in memory and disassembly windows - the double tap is annoying
+// * Keyboard shortcuts in error log windows
+// * Don't accept keyboard input while the game is running
+// * Interior focus rings - standard/exterior focus rings look really ugly here
+// * Scroll views with content narrower than clipping area are flaky under Tiger - nothing I can do about this
+
+
+// standard Cocoa headers
+#include <AvailabilityMacros.h>
+#import <Cocoa/Cocoa.h>
+
+// MAME headers
+#include "driver.h"
+#include "debug/debugvw.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+#include "debugger.h"
+
+// MAMEOS headers
+#include "debugosx.h"
+
+
+
+//============================================================
+// LOCAL VARIABLES
+//============================================================
+
+static MAMEDebugConsole *main_console = nil;
+
+static BOOL waiting_for_debugger = NO;
+
+static NSString *const MAMEHideDebuggerNotification = @"MAMEHideDebuggerNotification";
+static NSString *const MAMEShowDebuggerNotification = @"MAMEShowDebuggerNotification";
+static NSString *const MAMEAuxiliaryDebugWindowWillCloseNotification
+ = @"MAMEAuxiliaryDebugWindowWillCloseNotification";
+
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+static void debugwin_view_update(debug_view *view, void *osdprivate);
+
+static void console_create_window(running_machine *machine);
+
+
+//============================================================
+// osd_wait_for_debugger
+//============================================================
+
+void osd_wait_for_debugger(const device_config *device, int firststop)
+{
+ // create a console window
+ if (main_console == nil)
+ console_create_window(device->machine);
+
+ // make sure the debug windows are visible
+ waiting_for_debugger = YES;
+ if (firststop) {
+ NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:device],
+ @"MAMEDebugDevice",
+ nil];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MAMEShowDebuggerNotification
+ object:main_console
+ userInfo:info];
+ }
+
+ // get and process messages
+ {
+ NSEvent *ev = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (ev != nil)
+ [NSApp sendEvent:ev];
+ }
+
+ // mark the debugger as active
+ waiting_for_debugger = NO;
+}
+
+
+//============================================================
+// debugwin_update_during_game
+//============================================================
+
+void debugwin_update_during_game(running_machine *machine)
+{
+}
+
+
+//============================================================
+// debugwin_view_update
+//============================================================
+
+static void debugwin_view_update(debug_view *view, void *osdprivate)
+{
+ [(MAMEDebugView *)osdprivate update];
+}
+
+
+//============================================================
+// console_create_window
+//============================================================
+
+void console_create_window(running_machine *machine)
+{
+ main_console = [[MAMEDebugConsole alloc] initWithMachine:machine];
+}
+
+
+//============================================================
+// MAMEDebugView class
+//============================================================
+
+@implementation MAMEDebugCommandHistory
+
++ (NSInteger)defaultLength {
+ return 100;
+}
+
+
+- (id)init {
+ if (!(self = [super init]))
+ return nil;
+ length = [[self class] defaultLength];
+ position = -1;
+ current = nil;
+ history = [[NSMutableArray alloc] initWithCapacity:length];
+ return self;
+}
+
+
+- (void)dealloc {
+ if (current != nil)
+ [current release];
+ if (history != nil)
+ [history release];
+ [super dealloc];
+}
+
+
+- (NSInteger)length {
+ return length;
+}
+
+
+- (void)setLength:(NSInteger)l {
+ length = l;
+ while ([history count] > length)
+ [history removeLastObject];
+}
+
+
+- (void)add:(NSString *)entry {
+ if (([history count] == 0) || ![[history objectAtIndex:0] isEqualToString:entry]) {
+ [history insertObject:entry atIndex:0];
+ while ([history count] > length)
+ [history removeLastObject];
+ }
+ position = -1;
+}
+
+
+- (NSString *)previous:(NSString *)cur {
+ if ((position + 1) < [history count]) {
+ if (position < 0) {
+ [current autorelease];
+ current = [cur copy];
+ }
+ return [history objectAtIndex:++position];
+ } else {
+ return nil;
+ }
+}
+
+
+- (NSString *)next:(NSString *)cur {
+ if (position > 0) {
+ return [history objectAtIndex:--position];
+ } else if (position == 0) {
+ position--;
+ return [[current retain] autorelease];
+ } else {
+ return nil;
+ }
+}
+
+
+- (void)reset {
+ position = -1;
+ if (current != nil) {
+ [current release];
+ current = nil;
+ }
+}
+
+
+- (void)clear {
+ position = -1;
+ if (current != nil) {
+ [current release];
+ current = nil;
+ }
+ [history removeAllObjects];
+}
+
+@end
+
+
+//============================================================
+// MAMEDebugView class
+//============================================================
+
+@implementation MAMEDebugView
+
+- (NSColor *)foregroundForAttribute:(UINT8)attrib {
+ const CGFloat alpha = (attrib & DCA_DISABLED) ? 0.5 : 1.0;
+ if (attrib & DCA_COMMENT)
+ return [NSColor colorWithCalibratedRed:0.0 green:0.375 blue:0.0 alpha:1.0];
+ else if (attrib & DCA_INVALID)
+ return [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:alpha];
+ else if (attrib & DCA_CHANGED)
+ return [NSColor colorWithCalibratedRed:0.875 green:0.0 blue:0.0 alpha:alpha];
+ else
+ return [NSColor colorWithCalibratedWhite:0.0 alpha:alpha];
+}
+
+
+- (NSColor *)backgroundForAttribute:(UINT8)attrib {
+ if ((attrib & DCA_SELECTED) && (attrib & DCA_CURRENT)) {
+ if ([[self window] isKeyWindow] && ([[self window] firstResponder] == self))
+ return [NSColor colorWithCalibratedRed:0.875 green:0.625 blue:0.875 alpha:1.0];
+ else
+ return [NSColor colorWithCalibratedRed:0.875 green:0.5 blue:0.625 alpha:1.0];
+ } else if (attrib & DCA_CURRENT) {
+ return [NSColor colorWithCalibratedRed:1.0 green:0.625 blue:0.625 alpha:1.0];
+ } else if (attrib & DCA_SELECTED) {
+ if ([[self window] isKeyWindow] && ([[self window] firstResponder] == self))
+ return [NSColor colorWithCalibratedRed:0.75 green:0.875 blue:1.0 alpha:1.0];
+ else
+ return [NSColor colorWithCalibratedWhite:0.875 alpha:1.0];
+ } else if (attrib & DCA_ANCILLARY) {
+ return [NSColor colorWithCalibratedWhite:0.75 alpha:1.0];
+ } else {
+ return [NSColor colorWithCalibratedWhite:1.0 alpha:1.0];
+ }
+}
+
+
+- (debug_view_xy)convertLocation:(NSPoint)location {
+ debug_view_xy position;
+ position.x = lround(floor(location.x / fontWidth));
+ position.y = lround(floor(location.y / fontHeight));
+ if (position.x < 0)
+ position.x = 0;
+ else if (position.x >= totalSize.x)
+ position.x = totalSize.x - 1;
+ if (position.y < 0)
+ position.y = 0;
+ else if (position.y >= totalSize.y)
+ position.y = totalSize.y - 1;
+ return position;
+}
+
+
+- (void)convertBounds:(NSRect)b toPosition:(debug_view_xy *)origin size:(debug_view_xy *)size {
+ origin->x = lround(floor(b.origin.x / fontWidth));
+ origin->y = lround(floor(b.origin.y / fontHeight));
+ size->x = lround(ceil((b.origin.x + b.size.width) / fontWidth)) - origin->x;
+ size->y = lround(ceil((b.origin.y + b.size.height) / fontHeight)) - origin->y;
+}
+
+
+- (void)recomputeVisible {
+ if ([self window] != nil) {
+ debug_view_xy origin, size;
+
+ // this gets all the characters that are at least paritally visible
+ [self convertBounds:[self visibleRect] toPosition:&origin size:&size];
+
+ // need to render entire lines or we get screwed up characters when widening views
+ origin.x = 0;
+ size.x = totalSize.x;
+
+ // tell them what we think
+ debug_view_set_visible_size(view, size);
+ debug_view_set_visible_position(view, origin);
+ topLeft = origin;
+ }
+}
+
+
+- (void)typeCharacterAndScrollToCursor:(char)ch {
+ if (debug_view_get_cursor_supported(view)) {
+ debug_view_xy oldPos = debug_view_get_cursor_position(view);
+ debug_view_type_character(view, ch);
+ {
+ debug_view_xy newPos = debug_view_get_cursor_position(view);
+ if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y)) {
+ [self scrollRectToVisible:NSMakeRect(newPos.x * fontWidth,
+ newPos.y * fontHeight,
+ fontWidth,
+ fontHeight)];
+ }
+ }
+ } else {
+ debug_view_type_character(view, ch);
+ }
+}
+
+
++ (NSFont *)defaultFont {
+ // maybe we should get the configured system fixed-width font...
+ return [NSFont fontWithName:@"Monaco" size:10];
+}
+
+
+- (id)initWithFrame:(NSRect)f type:(int)t machine:(running_machine *)m {
+ if (!(self = [super initWithFrame:f]))
+ return nil;
+ type = t;
+ machine = m;
+ view = debug_view_alloc(machine, type, debugwin_view_update, self);
+ if (view == nil) {
+ [self release];
+ return nil;
+ }
+ totalSize.x = totalSize.y = 0;
+ topLeft.x = topLeft.y = 0;
+ [self setFont:[[self class] defaultFont]];
+ return self;
+}
+
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ if (view != NULL)
+ debug_view_free(view);
+ if (font != nil)
+ [font release];
+ [super dealloc];
+}
+
+
+- (void)update {
+ debug_view_xy newSize, newOrigin;
+
+ // resize our frame if the total size has changed
+ newSize = debug_view_get_total_size(view);
+ if ((newSize.x != totalSize.x) || (newSize.y != totalSize.y)) {
+ [self setFrameSize:NSMakeSize(fontWidth * newSize.x, fontHeight * newSize.y)];
+ totalSize = newSize;
+ }
+
+ // scroll the view if we're being told to
+ newOrigin = debug_view_get_visible_position(view);
+ if (newOrigin.y != topLeft.y) {
+ [self scrollPoint:NSMakePoint([self visibleRect].origin.x, newOrigin.y * fontHeight)];
+ topLeft.y = newOrigin.y;
+ }
+
+ // recompute the visible area and mark as dirty
+ [self recomputeVisible];
+ [self setNeedsDisplay:YES];
+}
+
+
+- (NSSize)maximumFrameSize {
+ debug_view_xy max = debug_view_get_total_size(view);
+ return NSMakeSize(max.x * fontWidth, max.y * fontHeight);
+}
+
+
+- (NSFont *)font {
+ return [[font retain] autorelease];
+}
+
+
+- (void)setFont:(NSFont *)f {
+ [font autorelease];
+ font = [f retain];
+ fontWidth = [font maximumAdvancement].width;
+ fontHeight = ceil([font ascender] - [font descender]);
+ fontAscent = [font ascender];
+ [[self enclosingScrollView] setLineScroll:fontHeight];
+ totalSize.x = totalSize.y = 0;
+ [self update];
+}
+
+
+- (void)windowDidBecomeKey:(NSNotification *)notification {
+ NSWindow *win = [notification object];
+ if ((win == [self window]) && ([win firstResponder] == self) && debug_view_get_cursor_supported(view))
+ [self setNeedsDisplay:YES];
+}
+
+
+- (void)windowDidResignKey:(NSNotification *)notification {
+ NSWindow *win = [notification object];
+ if ((win == [self window]) && ([win firstResponder] == self) && debug_view_get_cursor_supported(view))
+ [self setNeedsDisplay:YES];
+}
+
+
+- (BOOL)acceptsFirstResponder {
+ return debug_view_get_cursor_supported(view);
+}
+
+
+- (BOOL)becomeFirstResponder {
+ if (debug_view_get_cursor_supported(view)) {
+ debug_view_xy pos;
+ debug_view_set_cursor_visible(view, TRUE);
+ pos = debug_view_get_cursor_position(view);
+ [self scrollRectToVisible:NSMakeRect(pos.x * fontWidth, pos.y * fontHeight, fontWidth, fontHeight)];
+ [self setNeedsDisplay:YES];
+ return [super becomeFirstResponder];
+ } else {
+ return NO;
+ }
+}
+
+
+- (BOOL)resignFirstResponder {
+ if (debug_view_get_cursor_supported(view))
+ [self setNeedsDisplay:YES];
+ return [super resignFirstResponder];
+}
+
+
+- (void)viewDidMoveToSuperview {
+ [[self enclosingScrollView] setLineScroll:fontHeight];
+ [super viewDidMoveToSuperview];
+}
+
+
+- (void)viewDidMoveToWindow {
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:nil];
+ if ([self window] != nil) {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(windowDidBecomeKey:)
+ name:NSWindowDidBecomeKeyNotification
+ object:[self window]];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(windowDidResignKey:)
+ name:NSWindowDidResignKeyNotification
+ object:[self window]];
+ [self recomputeVisible];
+ }
+}
+
+
+- (BOOL)isFlipped {
+ return YES;
+}
+
+
+- (void)drawRect:(NSRect)dirtyRect {
+ const debug_view_char *base;
+ debug_view_xy origin, size;
+ debug_view_xy position, clip;
+ NSMutableString *text;
+ NSMutableDictionary *attributes;
+ UINT32 pass, row, col;
+
+ // work out how much we need to draw
+ [self recomputeVisible];
+ origin = debug_view_get_visible_position(view);
+ size = debug_view_get_visible_size(view);
+ [self convertBounds:dirtyRect toPosition:&position size:&clip];
+
+ // this gets the text for the whole visible area
+ base = debug_view_get_chars(view);
+ if (!base)
+ return;
+
+ text = [[NSMutableString alloc] initWithCapacity:clip.x];
+ attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:font, NSFontAttributeName, nil];
+ for (pass = 0; pass < 2; pass++) {
+ const debug_view_char *data = base + ((position.y - origin.y) * size.x);
+ for (row = position.y; row < position.y + clip.y; row++, data += size.x) {
+ int attr = -1;
+
+ if ((row < origin.y) || (row >= origin.y + size.y))
+ continue;
+
+ // render entire lines to get character alignment right
+ for (col = origin.x; col < origin.x + size.x; col++) {
+ if ((attr != data[col - origin.x].attrib) && ([text length] > 0)) {
+ if (pass == 0) {
+ [[self backgroundForAttribute:attr] set];
+ [NSBezierPath fillRect:NSMakeRect((col - [text length]) * fontWidth,
+ row * fontHeight,
+ [text length] * fontWidth,
+ fontHeight)];
+ } else {
+ [attributes setObject:[self foregroundForAttribute:attr]
+ forKey:NSForegroundColorAttributeName];
+ [text drawAtPoint:NSMakePoint((col - [text length]) * fontWidth, row * fontHeight)
+ withAttributes:attributes];
+ }
+ [text setString:@""];
+ }
+ attr = data[col - origin.x].attrib;
+ [text appendFormat:@"%c", data[col - origin.x].byte];
+ }
+ if ([text length] > 0) {
+ if (pass == 0) {
+ [[self backgroundForAttribute:attr] set];
+ [NSBezierPath fillRect:NSMakeRect((col - [text length]) * fontWidth,
+ row * fontHeight,
+ [text length] * fontWidth,
+ fontHeight)];
+ } else {
+ [attributes setObject:[self foregroundForAttribute:attr]
+ forKey:NSForegroundColorAttributeName];
+ [text drawAtPoint:NSMakePoint((col - [text length]) * fontWidth, row * fontHeight)
+ withAttributes:attributes];
+ }
+ [text setString:@""];
+ }
+ }
+ }
+ [attributes release];
+ [text release];
+}
+
+
+- (void)mouseDown:(NSEvent *)event {
+ NSPoint location = [self convertPoint:[event locationInWindow] fromView:nil];
+ if (debug_view_get_cursor_supported(view)) {
+ debug_view_set_cursor_position(view, [self convertLocation:location]);
+ debug_view_set_cursor_visible(view, TRUE);
+ [self setNeedsDisplay:YES];
+ }
+}
+
+
+- (void)mouseDragged:(NSEvent *)event {
+ NSPoint location = [self convertPoint:[event locationInWindow] fromView:nil];
+ if (debug_view_get_cursor_supported(view)) {
+ [self autoscroll:event];
+ debug_view_set_cursor_position(view, [self convertLocation:location]);
+ [self setNeedsDisplay:YES];
+ }
+}
+
+
+- (void)rightMouseDown:(NSEvent *)event {
+ NSPoint location = [self convertPoint:[event locationInWindow] fromView:nil];
+ if (debug_view_get_cursor_supported(view)) {
+ debug_view_set_cursor_position(view, [self convertLocation:location]);
+ debug_view_set_cursor_visible(view, TRUE);
+ [self setNeedsDisplay:YES];
+ }
+ [super rightMouseDown:event];
+}
+
+
+- (void)keyDown:(NSEvent *)event {
+ NSUInteger modifiers = [event modifierFlags];
+ NSString *str = [event charactersIgnoringModifiers];
+
+ if ([str length] == 1) {
+ if (modifiers & NSNumericPadKeyMask) {
+ switch ([str characterAtIndex:0]) {
+ case NSUpArrowFunctionKey:
+ if (modifiers & NSCommandKeyMask)
+ debug_view_type_character(view, DCH_CTRLHOME);
+ else
+ debug_view_type_character(view, DCH_UP);
+ return;
+ case NSDownArrowFunctionKey:
+ if (modifiers & NSCommandKeyMask)
+ debug_view_type_character(view, DCH_CTRLEND);
+ else
+ debug_view_type_character(view, DCH_DOWN);
+ return;
+ case NSLeftArrowFunctionKey:
+ if (modifiers & NSCommandKeyMask)
+ [self typeCharacterAndScrollToCursor:DCH_HOME];
+ else if (modifiers & NSAlternateKeyMask)
+ [self typeCharacterAndScrollToCursor:DCH_CTRLLEFT];
+ else
+ [self typeCharacterAndScrollToCursor:DCH_LEFT];
+ return;
+ case NSRightArrowFunctionKey:
+ if (modifiers & NSCommandKeyMask)
+ [self typeCharacterAndScrollToCursor:DCH_END];
+ else if (modifiers & NSAlternateKeyMask)
+ [self typeCharacterAndScrollToCursor:DCH_CTRLRIGHT];
+ else
+ [self typeCharacterAndScrollToCursor:DCH_RIGHT];
+ return;
+ default:
+ [self interpretKeyEvents:[NSArray arrayWithObject:event]];
+ return;
+ }
+ } else if (modifiers & NSFunctionKeyMask) {
+ switch ([str characterAtIndex:0]) {
+ case NSPageUpFunctionKey:
+ if (modifiers & NSAlternateKeyMask) {
+ debug_view_type_character(view, DCH_PUP);
+ return;
+ }
+ case NSPageDownFunctionKey:
+ if (modifiers & NSAlternateKeyMask) {
+ debug_view_type_character(view, DCH_PDOWN);
+ return;
+ }
+ default:
+ ;
+ }
+ [super keyDown:event];
+ return;
+ }
+ }
+ [self interpretKeyEvents:[NSArray arrayWithObject:event]];
+}
+
+
+- (void)insertTab:(id)sender {
+ if ([[self window] firstResponder] == self)
+ [[self window] selectNextKeyView:self];
+}
+
+
+- (void)insertBacktab:(id)sender {
+ if ([[self window] firstResponder] == self)
+ [[self window] selectPreviousKeyView:self];
+}
+
+
+- (void)insertNewline:(id)sender {
+ debug_cpu_single_step(machine, 1);
+}
+
+
+- (void)insertText:(id)string {
+ NSUInteger len;
+ NSRange found;
+ if ([string isKindOfClass:[NSAttributedString class]])
+ string = [string string];
+ for (len = [string length], found = NSMakeRange(0, 0);
+ found.location < len;
+ found.location += found.length) {
+ found = [string rangeOfComposedCharacterSequenceAtIndex:found.location];
+ if (found.length == 1) {
+ unichar ch = [string characterAtIndex:found.location];
+ if ((ch >= 32) && (ch < 127))
+ [self typeCharacterAndScrollToCursor:ch];
+ }
+ }
+}
+
+@end
+
+
+//============================================================
+// MAMEMemoryView class
+//============================================================
+
+@implementation MAMEMemoryView
+
+- (id)initWithFrame:(NSRect)f machine:(running_machine *)m {
+ NSMenu *contextMenu;
+
+ if (!(self = [super initWithFrame:f type:DVT_MEMORY machine:m]))
+ return nil;
+
+ contextMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Memory"];
+ [self insertActionItemsInMenu:contextMenu atIndex:0];
+ [self setMenu:contextMenu];
+ [contextMenu release];
+
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+- (BOOL)validateMenuItem:(NSMenuItem *)item {
+ SEL action = [item action];
+ NSInteger tag = [item tag];
+
+ if (action == @selector(showChunkSize:)) {
+ [item setState:((tag == memory_view_get_bytes_per_chunk(view)) ? NSOnState : NSOffState)];
+ } else if (action == @selector(showPhysicalAddresses:)) {
+ [item setState:((tag == memory_view_get_physical(view)) ? NSOnState : NSOffState)];
+ } else if (action == @selector(showReverseView:)) {
+ [item setState:((tag == memory_view_get_reverse(view)) ? NSOnState : NSOffState)];
+ } else if (action == @selector(showReverseViewToggle:)) {
+ [item setState:(memory_view_get_reverse(view) ? NSOnState : NSOffState)];
+ }
+ return YES;
+}
+
+
+- (NSSize)maximumFrameSize {
+ const int selected = memory_view_get_subview(view);
+ const memory_subview_item *subitem;
+ debug_view_xy max;
+
+ max.x = max.y = 0;
+ for (subitem = memory_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ debug_view_xy current;
+ memory_view_set_subview(view, subitem->index);
+ current = debug_view_get_total_size(view);
+ if (current.x > max.x)
+ max.x = current.x;
+ if (current.y > max.y)
+ max.y = current.y;
+ }
+ memory_view_set_subview(view, selected);
+ return NSMakeSize(max.x * fontWidth, max.y * fontHeight);
+}
+
+
+- (NSString *)selectedSubviewName {
+ const memory_subview_item *subitem = memory_view_get_current_subview(view);
+ if (subitem != NULL)
+ return [NSString stringWithUTF8String:subitem->name];
+ else
+ return @"";
+}
+
+
+- (int)selectedSubviewIndex {
+ const memory_subview_item *subitem = memory_view_get_current_subview(view);
+ if (subitem != NULL)
+ return subitem->index;
+ else
+ return -1;
+}
+
+
+- (void)selectSubviewAtIndex:(int)index {
+ const int selected = memory_view_get_subview(view);
+ if (selected != index) {
+ memory_view_set_subview(view, index);
+ if ([[self window] firstResponder] != self)
+ debug_view_set_cursor_visible(view, FALSE);
+ }
+}
+
+
+- (void)selectSubviewForCPU:(const device_config *)device {
+ const int selected = memory_view_get_subview(view);
+ const memory_subview_item *subitem;
+ for (subitem = memory_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ if (subitem->space->cpu == device) {
+ if (selected != subitem->index) {
+ memory_view_set_subview(view, subitem->index);
+ if ([[self window] firstResponder] != self)
+ debug_view_set_cursor_visible(view, FALSE);
+ }
+ break;
+ }
+ }
+}
+
+
+- (NSString *)expression {
+ return [NSString stringWithUTF8String:memory_view_get_expression(view)];
+}
+
+
+- (void)setExpression:(NSString *)exp {
+ memory_view_set_expression(view, [exp UTF8String]);
+}
+
+
+- (IBAction)showChunkSize:(id)sender {
+ memory_view_set_bytes_per_chunk(view, [sender tag]);
+}
+
+
+- (IBAction)showPhysicalAddresses:(id)sender {
+ memory_view_set_physical(view, [sender tag]);
+}
+
+
+- (IBAction)showReverseView:(id)sender {
+ memory_view_set_reverse(view, [sender tag]);
+}
+
+
+- (IBAction)showReverseViewToggle:(id)sender {
+ memory_view_set_reverse(view, !memory_view_get_reverse(view));
+}
+
+
+- (void)insertActionItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index {
+ {
+ NSInteger tag;
+ for (tag = 1; tag <= 8; tag <<= 1) {
+ NSString *title = [NSString stringWithFormat:@"%d-byte Chunks", tag];
+ NSMenuItem *chunkItem = [menu insertItemWithTitle:title
+ action:@selector(showChunkSize:)
+ keyEquivalent:[NSString stringWithFormat:@"%d", tag]
+ atIndex:index++];
+ [chunkItem setTarget:self];
+ [chunkItem setTag:tag];
+ }
+ }
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+ {
+ NSMenuItem *logicalItem = [menu insertItemWithTitle:@"Logical Addresses"
+ action:@selector(showPhysicalAddresses:)
+ keyEquivalent:@"v"
+ atIndex:index++];
+ [logicalItem setTarget:self];
+ [logicalItem setTag:FALSE];
+ }
+ {
+ NSMenuItem *physicalItem = [menu insertItemWithTitle:@"Physical Addresses"
+ action:@selector(showPhysicalAddresses:)
+ keyEquivalent:@"y"
+ atIndex:index++];
+ [physicalItem setTarget:self];
+ [physicalItem setTag:TRUE];
+ }
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+ {
+ NSMenuItem *reverseItem = [menu insertItemWithTitle:@"Reverse View"
+ action:@selector(showReverseViewToggle:)
+ keyEquivalent:@"r"
+ atIndex:index++];
+ [reverseItem setTarget:self];
+ }
+ if (index < [menu numberOfItems])
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+}
+
+
+- (void)insertSubviewItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index {
+ const memory_subview_item *subitem;
+ for (subitem = memory_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ [[menu insertItemWithTitle:[NSString stringWithUTF8String:subitem->name]
+ action:NULL
+ keyEquivalent:@""
+ atIndex:index++] setTag:subitem->index];
+ }
+ if (index < [menu numberOfItems])
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+}
+
+@end
+
+
+//============================================================
+// MAMEDisassemblyView class
+//============================================================
+
+@implementation MAMEDisassemblyView
+
+- (debug_cpu_breakpoint *)findBreakpointAtAddress:(offs_t)address inAddressSpace:(const address_space *)space {
+ cpu_debug_data *cpuinfo = cpu_get_debug_data(space->cpu);
+ debug_cpu_breakpoint *bp;
+ for (bp = cpuinfo->bplist; (bp != NULL) && (address != bp->address); bp = bp->next) {}
+ return bp;
+}
+
+- (void)createContextMenu {
+ NSMenu *contextMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Disassembly"];
+ NSMenuItem *item;
+
+ item = [contextMenu addItemWithTitle:@"Toggle Breakpoint"
+ action:@selector(debugToggleBreakpoint:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF9FunctionKey]];
+ [item setKeyEquivalentModifierMask:0];
+ [item setTarget:self];
+
+ item = [contextMenu addItemWithTitle:@"Disable Breakpoint"
+ action:@selector(debugToggleBreakpointEnable:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF9FunctionKey]];
+ [item setKeyEquivalentModifierMask:NSShiftKeyMask];
+ [item setTarget:self];
+
+ [contextMenu addItem:[NSMenuItem separatorItem]];
+
+ item = [contextMenu addItemWithTitle:@"Run to Cursor"
+ action:@selector(debugRunToCursor:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF4FunctionKey]];
+ [item setKeyEquivalentModifierMask:0];
+ [item setTarget:self];
+
+ [contextMenu addItem:[NSMenuItem separatorItem]];
+
+ item = [contextMenu addItemWithTitle:@"Raw Opcodes"
+ action:@selector(showRightColumn:)
+ keyEquivalent:@"r"];
+ [item setTarget:self];
+ [item setTag:DASM_RIGHTCOL_RAW];
+
+ item = [contextMenu addItemWithTitle:@"Encrypted Opcodes"
+ action:@selector(showRightColumn:)
+ keyEquivalent:@"e"];
+ [item setTarget:self];
+ [item setTag:DASM_RIGHTCOL_ENCRYPTED];
+
+ item = [contextMenu addItemWithTitle:@"Comments"
+ action:@selector(showRightColumn:)
+ keyEquivalent:@"n"];
+ [item setTarget:self];
+ [item setTag:DASM_RIGHTCOL_COMMENTS];
+
+ [self setMenu:contextMenu];
+ [contextMenu release];
+}
+
+
+- (id)initWithFrame:(NSRect)f machine:(running_machine *)m useConsole:(BOOL)uc {
+ if (!(self = [super initWithFrame:f type:DVT_DISASSEMBLY machine:m]))
+ return nil;
+ useConsole = uc;
+ [self createContextMenu];
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+- (BOOL)validateMenuItem:(NSMenuItem *)item {
+ SEL action = [item action];
+ BOOL inContextMenu = ([item menu] == [self menu]);
+ BOOL haveCursor = NO, isCurrent = NO;
+ debug_cpu_breakpoint *breakpoint = NULL;
+
+ if (debug_view_get_cursor_visible(view)) {
+ const address_space *space = disasm_view_get_current_subview(view)->space;
+ isCurrent = (debug_cpu_get_visible_cpu(machine) == space->cpu);
+ if (!useConsole || isCurrent) {
+ offs_t address = memory_byte_to_address(space, disasm_view_get_selected_address(view));
+ haveCursor = YES;
+ breakpoint = [self findBreakpointAtAddress:address inAddressSpace:space];
+ }
+ }
+
+ if (action == @selector(debugToggleBreakpoint:)) {
+ if (haveCursor) {
+ if (breakpoint != NULL) {
+ if (inContextMenu)
+ [item setTitle:@"Clear Breakpoint"];
+ else
+ [item setTitle:@"Clear Breakpoint at Cursor"];
+ } else {
+ if (inContextMenu)
+ [item setTitle:@"Set Breakpoint"];
+ else
+ [item setTitle:@"Set Breakpoint at Cursor"];
+ }
+ } else {
+ if (inContextMenu)
+ [item setTitle:@"Toggle Breakpoint"];
+ else
+ [item setTitle:@"Toggle Breakpoint at Cursor"];
+ }
+ return haveCursor;
+ } else if (action == @selector(debugToggleBreakpointEnable:)) {
+ if ((breakpoint != NULL) && !breakpoint->enabled) {
+ if (inContextMenu)
+ [item setTitle:@"Enable Breakpoint"];
+ else
+ [item setTitle:@"Enable Breakpoint at Cursor"];
+ } else {
+ if (inContextMenu)
+ [item setTitle:@"Disable Breakpoint"];
+ else
+ [item setTitle:@"Disable Breakpoint at Cursor"];
+ }
+ return (breakpoint != NULL);
+ } else if (action == @selector(debugRunToCursor:)) {
+ return isCurrent;
+ } else if (action == @selector(showRightColumn:)) {
+ [item setState:((disasm_view_get_right_column(view) == [item tag]) ? NSOnState : NSOffState)];
+ return YES;
+ } else {
+ return YES;
+ }
+}
+
+
+- (NSSize)maximumFrameSize {
+ const int selected = disasm_view_get_subview(view);
+ const disasm_subview_item *subitem;
+ debug_view_xy max;
+
+ max.x = max.y = 0;
+ for (subitem = disasm_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ debug_view_xy current;
+ disasm_view_set_subview(view, subitem->index);
+ current = debug_view_get_total_size(view);
+ if (current.x > max.x)
+ max.x = current.x;
+ if (current.y > max.y)
+ max.y = current.y;
+ }
+ disasm_view_set_subview(view, selected);
+ return NSMakeSize(max.x * fontWidth, max.y * fontHeight);
+}
+
+
+- (NSString *)selectedSubviewName {
+ const disasm_subview_item *subitem = disasm_view_get_current_subview(view);
+ if (subitem != NULL)
+ return [NSString stringWithUTF8String:subitem->name];
+ else
+ return @"";
+}
+
+
+- (int)selectedSubviewIndex {
+ const disasm_subview_item *subitem = disasm_view_get_current_subview(view);
+ if (subitem != NULL)
+ return subitem->index;
+ else
+ return -1;
+}
+
+
+- (void)selectSubviewAtIndex:(int)index {
+ const int selected = disasm_view_get_subview(view);
+ if (selected != index) {
+ disasm_view_set_subview(view, index);
+ if ([[self window] firstResponder] != self)
+ debug_view_set_cursor_visible(view, FALSE);
+ }
+}
+
+
+- (void)selectSubviewForCPU:(const device_config *)device {
+ const int selected = disasm_view_get_subview(view);
+ const disasm_subview_item *subitem;
+ for (subitem = disasm_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ if (subitem->space->cpu == device) {
+ if (selected != subitem->index) {
+ disasm_view_set_subview(view, subitem->index);
+ if ([[self window] firstResponder] != self)
+ debug_view_set_cursor_visible(view, FALSE);
+ }
+ break;
+ }
+ }
+}
+
+
+- (NSString *)expression {
+ return [NSString stringWithUTF8String:disasm_view_get_expression(view)];
+}
+
+
+- (void)setExpression:(NSString *)exp {
+ disasm_view_set_expression(view, [exp UTF8String]);
+}
+
+
+- (IBAction)debugToggleBreakpoint:(id)sender {
+ if (debug_view_get_cursor_visible(view)) {
+ const address_space *space = disasm_view_get_current_subview(view)->space;
+ if (!useConsole || (debug_cpu_get_visible_cpu(machine) == space->cpu)) {
+ offs_t address = memory_byte_to_address(space, disasm_view_get_selected_address(view));
+ debug_cpu_breakpoint *bp = [self findBreakpointAtAddress:address inAddressSpace:space];
+
+ // if it doesn't exist, add a new one
+ if (useConsole) {
+ NSString *command;
+ if (bp == NULL)
+ command = [NSString stringWithFormat:@"bpset %lX", (unsigned long)address];
+ else
+ command = [NSString stringWithFormat:@"bpclear %X", (unsigned)bp->index];
+ debug_console_execute_command(machine, [command UTF8String], 1);
+ } else {
+ if (bp == NULL)
+ debug_cpu_breakpoint_set(space->cpu, address, NULL, NULL);
+ else
+ debug_cpu_breakpoint_clear(machine, bp->index);
+ debug_view_update_type(machine, DVT_DISASSEMBLY);
+ }
+ }
+ }
+}
+
+
+- (IBAction)debugToggleBreakpointEnable:(id)sender {
+ if (debug_view_get_cursor_visible(view)) {
+ const address_space *space = disasm_view_get_current_subview(view)->space;
+ if (!useConsole || (debug_cpu_get_visible_cpu(machine) == space->cpu)) {
+ offs_t address = memory_byte_to_address(space, disasm_view_get_selected_address(view));
+ debug_cpu_breakpoint *bp = [self findBreakpointAtAddress:address inAddressSpace:space];
+
+ if (bp != NULL) {
+ NSString *command;
+ if (useConsole) {
+ if (bp->enabled)
+ command = [NSString stringWithFormat:@"bpdisable %X", (unsigned)bp->index];
+ else
+ command = [NSString stringWithFormat:@"bpenable %X", (unsigned)bp->index];
+ debug_console_execute_command(machine, [command UTF8String], 1);
+ } else {
+ debug_cpu_breakpoint_enable(machine, bp->index, !bp->enabled);
+ debug_view_update_type(machine, DVT_DISASSEMBLY);
+ }
+ }
+ }
+ }
+}
+
+
+- (IBAction)debugRunToCursor:(id)sender {
+ if (debug_view_get_cursor_visible(view)) {
+ const address_space *space = disasm_view_get_current_subview(view)->space;
+ if (debug_cpu_get_visible_cpu(machine) == space->cpu) {
+ offs_t address = memory_byte_to_address(space, disasm_view_get_selected_address(view));
+ if (useConsole) {
+ NSString *command = [NSString stringWithFormat:@"go %lX", (unsigned long)address];
+ debug_console_execute_command(machine, [command UTF8String], 1);
+ } else {
+ debug_cpu_go(machine, address);
+ }
+ }
+ }
+}
+
+
+- (IBAction)showRightColumn:(id)sender {
+ disasm_view_set_right_column(view, [sender tag]);
+}
+
+
+- (void)insertActionItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index {
+ {
+ NSMenuItem *breakItem = [menu insertItemWithTitle:@"Toggle Breakpoint at Cursor"
+ action:@selector(debugToggleBreakpoint:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF9FunctionKey]
+ atIndex:index++];
+ [breakItem setKeyEquivalentModifierMask:0];
+ [breakItem setTarget:self];
+ }
+ {
+ NSMenuItem *disableItem = [menu insertItemWithTitle:@"Disable Breakpoint at Cursor"
+ action:@selector(debugToggleBreakpointEnable:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF9FunctionKey]
+ atIndex:index++];
+ [disableItem setKeyEquivalentModifierMask:NSShiftKeyMask];
+ [disableItem setAlternate:YES];
+ [disableItem setTarget:self];
+ }
+ {
+ NSMenu *runMenu = [[menu itemWithTitle:@"Run"] submenu];
+ NSMenuItem *runItem;
+ if (runMenu != nil) {
+ runItem = [runMenu addItemWithTitle:@"to Cursor"
+ action:@selector(debugRunToCursor:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF4FunctionKey]];
+ } else {
+ runItem = [menu insertItemWithTitle:@"Run to Cursor"
+ action:@selector(debugRunToCursor:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF4FunctionKey]
+ atIndex:index++];
+ }
+ [runItem setKeyEquivalentModifierMask:0];
+ [runItem setTarget:self];
+ }
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+ {
+ NSMenuItem *rawItem = [menu insertItemWithTitle:@"Show Raw Opcodes"
+ action:@selector(showRightColumn:)
+ keyEquivalent:@"r"
+ atIndex:index++];
+ [rawItem setTarget:self];
+ [rawItem setTag:DASM_RIGHTCOL_RAW];
+ }
+ {
+ NSMenuItem *encItem = [menu insertItemWithTitle:@"Show Encrypted Opcodes"
+ action:@selector(showRightColumn:)
+ keyEquivalent:@"e"
+ atIndex:index++];
+ [encItem setTarget:self];
+ [encItem setTag:DASM_RIGHTCOL_ENCRYPTED];
+ }
+ {
+ NSMenuItem *commentsItem = [menu insertItemWithTitle:@"Show Comments"
+ action:@selector(showRightColumn:)
+ keyEquivalent:@"n"
+ atIndex:index++];
+ [commentsItem setTarget:self];
+ [commentsItem setTag:DASM_RIGHTCOL_COMMENTS];
+ }
+ if (index < [menu numberOfItems])
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+}
+
+
+- (void)insertSubviewItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index {
+ const disasm_subview_item *subitem;
+ for (subitem = disasm_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ [[menu insertItemWithTitle:[NSString stringWithUTF8String:subitem->name]
+ action:NULL
+ keyEquivalent:@""
+ atIndex:index++] setTag:subitem->index];
+ }
+ if (index < [menu numberOfItems])
+ [menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
+}
+
+@end
+
+
+//============================================================
+// MAMERegistersView class
+//============================================================
+
+@implementation MAMERegistersView
+
+- (id)initWithFrame:(NSRect)f machine:(running_machine *)m {
+ if (!(self = [super initWithFrame:f type:DVT_REGISTERS machine:m]))
+ return nil;
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+- (NSSize)maximumFrameSize {
+ const int selected = registers_view_get_subview(view);
+ const registers_subview_item *subitem;
+ debug_view_xy max;
+
+ max.x = max.y = 0;
+ for (subitem = registers_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ debug_view_xy current;
+ registers_view_set_subview(view, subitem->index);
+ current = debug_view_get_total_size(view);
+ if (current.x > max.x)
+ max.x = current.x;
+ if (current.y > max.y)
+ max.y = current.y;
+ }
+ registers_view_set_subview(view, selected);
+ return NSMakeSize(max.x * fontWidth, max.y * fontHeight);
+}
+
+
+- (NSString *)selectedSubviewName {
+ const registers_subview_item *subitem = registers_view_get_current_subview(view);
+ if (subitem != NULL)
+ return [NSString stringWithUTF8String:subitem->name];
+ else
+ return @"";
+}
+
+
+- (int)selectedSubviewIndex {
+ const registers_subview_item *subitem = registers_view_get_current_subview(view);
+ if (subitem != NULL)
+ return subitem->index;
+ else
+ return -1;
+}
+
+
+- (void)selectSubviewAtIndex:(int)index {
+ const int selected = registers_view_get_subview(view);
+ if (selected != index) {
+ registers_view_set_subview(view, index);
+ if ([[self window] firstResponder] != self)
+ debug_view_set_cursor_visible(view, FALSE);
+ }
+}
+
+
+- (void)selectSubviewForCPU:(const device_config *)device {
+ const int selected = registers_view_get_subview(view);
+ const registers_subview_item *subitem;
+ for (subitem = registers_view_get_subview_list(view); subitem != NULL; subitem = subitem->next) {
+ if (subitem->device == device) {
+ if (selected != subitem->index) {
+ registers_view_set_subview(view, subitem->index);
+ if ([[self window] firstResponder] != self)
+ debug_view_set_cursor_visible(view, FALSE);
+ }
+ break;
+ }
+ }
+}
+
+@end
+
+
+//============================================================
+// MAMEConsoleView class
+//============================================================
+
+@implementation MAMEConsoleView
+
+- (id)initWithFrame:(NSRect)f machine:(running_machine *)m {
+ if (!(self = [super initWithFrame:f type:DVT_CONSOLE machine:m]))
+ return nil;
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+@end
+
+
+//============================================================
+// MAMEErrorLogView class
+//============================================================
+
+@implementation MAMEErrorLogView
+
+- (id)initWithFrame:(NSRect)f machine:(running_machine *)m {
+ if (!(self = [super initWithFrame:f type:DVT_LOG machine:m]))
+ return nil;
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+@end
+
+
+//============================================================
+// MAMEDebugWindowHandler class
+//============================================================
+
+@implementation MAMEDebugWindowHandler
+
++ (void)addCommonActionItems:(NSMenu *)menu {
+ {
+ NSMenuItem *runParentItem = [menu addItemWithTitle:@"Run"
+ action:@selector(debugRun:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF5FunctionKey]];
+ NSMenu *runMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Run"];
+ [runParentItem setSubmenu:runMenu];
+ [runMenu release];
+ [runParentItem setKeyEquivalentModifierMask:0];
+ [[runMenu addItemWithTitle:@"and Hide Debugger"
+ action:@selector(debugRunAndHide:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF12FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ [[runMenu addItemWithTitle:@"to Next CPU"
+ action:@selector(debugRunToNextCPU:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF6FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ [[runMenu addItemWithTitle:@"until Next Interrupt on Current CPU"
+ action:@selector(debugRunToNextInterrupt:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF7FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ [[runMenu addItemWithTitle:@"until Next VBLANK"
+ action:@selector(debugRunToNextVBLANK:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF8FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ }
+ {
+ NSMenuItem *stepParentItem = [menu addItemWithTitle:@"Step" action:NULL keyEquivalent:@""];
+ NSMenu *stepMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Step"];
+ [stepParentItem setSubmenu:stepMenu];
+ [stepMenu release];
+ [[stepMenu addItemWithTitle:@"Into"
+ action:@selector(debugStepInto:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF11FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ [[stepMenu addItemWithTitle:@"Over"
+ action:@selector(debugStepOver:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF10FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ [[stepMenu addItemWithTitle:@"Out"
+ action:@selector(debugStepOut:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF10FunctionKey]]
+ setKeyEquivalentModifierMask:NSShiftKeyMask];
+ }
+ {
+ NSMenuItem *resetParentItem = [menu addItemWithTitle:@"Reset" action:NULL keyEquivalent:@""];
+ NSMenu *resetMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Reset"];
+ [resetParentItem setSubmenu:resetMenu];
+ [resetMenu release];
+ [[resetMenu addItemWithTitle:@"Soft"
+ action:@selector(debugSoftReset:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF3FunctionKey]]
+ setKeyEquivalentModifierMask:0];
+ [[resetMenu addItemWithTitle:@"Hard"
+ action:@selector(debugHardReset:)
+ keyEquivalent:[NSString stringWithFormat:@"%C", NSF3FunctionKey]]
+ setKeyEquivalentModifierMask:NSShiftKeyMask];
+ }
+ [menu addItem:[NSMenuItem separatorItem]];
+ {
+ NSMenuItem *newParentItem = [menu addItemWithTitle:@"New" action:NULL keyEquivalent:@""];
+ NSMenu *newMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"New"];
+ [newParentItem setSubmenu:newMenu];
+ [newMenu release];
+ [newMenu addItemWithTitle:@"Memory Window"
+ action:@selector(debugNewMemoryWindow:)
+ keyEquivalent:@"d"];
+ [newMenu addItemWithTitle:@"Disassembly Window"
+ action:@selector(debugNewDisassemblyWindow:)
+ keyEquivalent:@"a"];
+ [newMenu addItemWithTitle:@"Error Log Window"
+ action:@selector(debugNewErrorLogWindow:)
+ keyEquivalent:@"l"];
+ }
+ [menu addItem:[NSMenuItem separatorItem]];
+ [menu addItemWithTitle:@"Close Window" action:@selector(performClose:) keyEquivalent:@"w"];
+ [menu addItemWithTitle:@"Exit" action:@selector(debugExit:) keyEquivalent:@""];
+}
+
+
++ (NSPopUpButton *)newActionButtonWithFrame:(NSRect)frame {
+ NSPopUpButton *actionButton = [[NSPopUpButton alloc] initWithFrame:frame pullsDown:YES];
+ [actionButton setTitle:@""];
+ [actionButton addItemWithTitle:@""];
+ [actionButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [actionButton setFocusRingType:NSFocusRingTypeNone];
+ [[actionButton cell] setArrowPosition:NSPopUpArrowAtCenter];
+ [[self class] addCommonActionItems:[actionButton menu]];
+ return actionButton;
+}
+
+
+- (id)initWithMachine:(running_machine *)m title:(NSString *)t {
+ if (!(self = [super init]))
+ return nil;
+
+ window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 320, 240)
+ styleMask:(NSTitledWindowMask |
+ NSClosableWindowMask |
+ NSMiniaturizableWindowMask |
+ NSResizableWindowMask)
+ backing:NSBackingStoreBuffered
+ defer:YES];
+ [window setReleasedWhenClosed:NO];
+ [window setDelegate:self];
+ [window setTitle:t];
+ [window setContentMinSize:NSMakeSize(320, 240)];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(showDebugger:)
+ name:MAMEShowDebuggerNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(hideDebugger:)
+ name:MAMEHideDebuggerNotification
+ object:nil];
+
+ machine = m;
+
+ return self;
+}
+
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ if (window != nil)
+ [window release];
+
+ [super dealloc];
+}
+
+
+- (void)activate {
+ [window makeKeyAndOrderFront:self];
+}
+
+
+- (IBAction)debugRun:(id)sender {
+ debug_cpu_go(machine, ~0);
+}
+
+
+- (IBAction)debugRunAndHide:(id)sender {
+ [[NSNotificationCenter defaultCenter] postNotificationName:MAMEHideDebuggerNotification object:self];
+ debug_cpu_go(machine, ~0);
+}
+
+
+- (IBAction)debugRunToNextCPU:(id)sender {
+ debug_cpu_next_cpu(machine);
+}
+
+
+- (IBAction)debugRunToNextInterrupt:(id)sender {
+ debug_cpu_go_interrupt(machine, -1);
+}
+
+
+- (IBAction)debugRunToNextVBLANK:(id)sender {
+ debug_cpu_go_vblank(machine);
+}
+
+
+- (IBAction)debugStepInto:(id)sender {
+ debug_cpu_single_step(machine, 1);
+}
+
+
+- (IBAction)debugStepOver:(id)sender {
+ debug_cpu_single_step_over(machine, 1);
+}
+
+
+- (IBAction)debugStepOut:(id)sender {
+ debug_cpu_single_step_out(machine);
+}
+
+
+- (IBAction)debugSoftReset:(id)sender {
+ mame_schedule_soft_reset(machine);
+}
+
+
+- (IBAction)debugHardReset:(id)sender {
+ mame_schedule_hard_reset(machine);
+}
+
+
+- (IBAction)debugExit:(id)sender {
+ mame_schedule_exit(machine);
+}
+
+
+- (void)showDebugger:(NSNotification *)notification {
+ const device_config *device = [[[notification userInfo] objectForKey:@"MAMEDebugDevice"] pointerValue];
+ if (device->machine == machine) {
+ if (![window isVisible] && ![window isMiniaturized])
+ [window orderFront:self];
+ }
+}
+
+
+- (void)hideDebugger:(NSNotification *)notification {
+ [window orderOut:self];
+}
+
+@end
+
+
+
+//============================================================
+// MAMEDebugConsole class
+//============================================================
+
+@implementation MAMEDebugConsole
+
+- (id)initWithMachine:(running_machine *)m {
+ NSSplitView *regSplit, *dasmSplit;
+ NSScrollView *regScroll, *dasmScroll, *consoleScroll;
+ NSView *consoleContainer;
+ NSPopUpButton *actionButton;
+ NSRect rct;
+
+ // initialise superclass
+ if (!(self = [super initWithMachine:m title:@"Debug"]))
+ return nil;
+ history = [[MAMEDebugCommandHistory alloc] init];
+ auxiliaryWindows = [[NSMutableArray alloc] init];
+
+ // create the register view
+ regView = [[MAMERegistersView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) machine:machine];
+ regScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [regScroll setDrawsBackground:YES];
+ [regScroll setHasHorizontalScroller:YES];
+ [regScroll setHasVerticalScroller:YES];
+ [regScroll setAutohidesScrollers:YES];
+ [regScroll setBorderType:NSBezelBorder];
+ [regScroll setDocumentView:regView];
+ [regView release];
+
+ // create the disassembly view
+ dasmView = [[MAMEDisassemblyView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)
+ machine:machine
+ useConsole:YES];
+ [dasmView setExpression:@"curpc"];
+ dasmScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [dasmScroll setDrawsBackground:YES];
+ [dasmScroll setHasHorizontalScroller:YES];
+ [dasmScroll setHasVerticalScroller:YES];
+ [dasmScroll setAutohidesScrollers:YES];
+ [dasmScroll setBorderType:NSBezelBorder];
+ [dasmScroll setDocumentView:dasmView];
+ [dasmView release];
+
+ // create the console view
+ consoleView = [[MAMEConsoleView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) machine:machine];
+ consoleScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [consoleScroll setDrawsBackground:YES];
+ [consoleScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [consoleScroll setHasHorizontalScroller:YES];
+ [consoleScroll setHasVerticalScroller:YES];
+ [consoleScroll setAutohidesScrollers:YES];
+ [consoleScroll setBorderType:NSBezelBorder];
+ [consoleScroll setDocumentView:consoleView];
+ [consoleView release];
+
+ // create the command field
+ commandField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)];
+ [commandField setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)];
+ [commandField setFont:[[MAMEDebugView class] defaultFont]];
+ [commandField setFocusRingType:NSFocusRingTypeNone];
+ [commandField setTarget:self];
+ [commandField setAction:@selector(doCommand:)];
+ [commandField setDelegate:self];
+ rct = [commandField frame];
+ [commandField setFrame:NSMakeRect(rct.size.height, 0, rct.size.width - rct.size.height, rct.size.height)];
+
+ // create the action pull-down button
+ actionButton = [[self class] newActionButtonWithFrame:NSMakeRect(0, 0, rct.size.height, rct.size.height)];
+ [actionButton setAutoresizingMask:(NSViewMaxXMargin | NSViewMaxYMargin)];
+ [dasmView insertActionItemsInMenu:[actionButton menu] atIndex:1];
+
+ // create the container for the console and command input field
+ consoleContainer = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [consoleScroll setFrame:NSMakeRect(0,
+ rct.size.height,
+ 100,
+ [consoleContainer bounds].size.height - rct.size.height)];
+ [consoleContainer addSubview:consoleScroll];
+ [consoleContainer addSubview:commandField];
+ [consoleContainer addSubview:actionButton];
+ [consoleScroll release];
+ [commandField release];
+ [actionButton release];
+
+ // create the split between the disassembly and the console
+ dasmSplit = [[NSSplitView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [dasmSplit setDelegate:self];
+ [dasmSplit setVertical:NO];
+ [dasmSplit addSubview:dasmScroll];
+ [dasmSplit addSubview:consoleContainer];
+ [dasmScroll release];
+ [consoleContainer release];
+
+ // create the split between the registers and the console
+ regSplit = [[NSSplitView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [regSplit setDelegate:self];
+ [regSplit setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [regSplit setVertical:YES];
+ [regSplit addSubview:regScroll];
+ [regSplit addSubview:dasmSplit];
+ [regScroll release];
+ [dasmSplit release];
+
+ // put the split views in the window and get them into a half-reasonable state
+ [window setContentView:regSplit];
+ [regSplit release];
+ [regSplit adjustSubviews];
+ [dasmSplit adjustSubviews];
+
+ // keyboard focus should start on the command field
+ [window makeFirstResponder:commandField];
+
+ // calculate the optimal size for everything
+ {
+ NSRect available = [[NSScreen mainScreen] visibleFrame];
+ NSRect windowFrame = [window frame];
+ NSSize regCurrent = [regScroll frame].size;
+ NSSize regSize = [NSScrollView frameSizeForContentSize:[regView maximumFrameSize]
+ hasHorizontalScroller:YES
+ hasVerticalScroller:YES
+ borderType:[regScroll borderType]];
+ NSSize dasmCurrent = [dasmScroll frame].size;
+ NSSize dasmSize = [NSScrollView frameSizeForContentSize:[dasmView maximumFrameSize]
+ hasHorizontalScroller:YES
+ hasVerticalScroller:YES
+ borderType:[dasmScroll borderType]];
+ NSSize consoleCurrent = [consoleContainer frame].size;
+ NSSize consoleSize = [NSScrollView frameSizeForContentSize:[consoleView maximumFrameSize]
+ hasHorizontalScroller:YES
+ hasVerticalScroller:YES
+ borderType:[consoleScroll borderType]];
+ NSSize adjustment;
+ NSRect lhsFrame, rhsFrame;
+
+ consoleSize.width += consoleCurrent.width - [consoleScroll frame].size.width;
+ consoleSize.height += consoleCurrent.height - [consoleScroll frame].size.height;
+ adjustment.width = regSize.width - regCurrent.width;
+ adjustment.height = regSize.height - regCurrent.height;
+ adjustment.width += MAX(dasmSize.width - dasmCurrent.width, consoleSize.width - consoleCurrent.width);
+
+ windowFrame.size.width += adjustment.width;
+ windowFrame.size.height += adjustment.height; // not used - better to go for fixed height
+ windowFrame.size.height = MIN(512.0, available.size.height);
+ windowFrame.size.width = MIN(windowFrame.size.width, available.size.width);
+ windowFrame.origin.x = available.origin.x + available.size.width - windowFrame.size.width;
+ windowFrame.origin.y = available.origin.y;
+ [window setFrame:windowFrame display:YES];
+
+ lhsFrame = [regScroll frame];
+ rhsFrame = [dasmSplit frame];
+ adjustment.width = MIN(regSize.width, ([regSplit frame].size.width - [regSplit dividerThickness]) / 2);
+ rhsFrame.origin.x -= lhsFrame.size.width - adjustment.width;
+ rhsFrame.size.width += lhsFrame.size.width - adjustment.width;
+ lhsFrame.size.width = adjustment.width;
+ [regScroll setFrame:lhsFrame];
+ [dasmSplit setFrame:rhsFrame];
+ }
+
+ // select the current processor
+ [self setCPU:machine->firstcpu];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(auxiliaryWindowWillClose:)
+ name:MAMEAuxiliaryDebugWindowWillCloseNotification
+ object:nil];
+
+ // don't forget the return value
+ return self;
+}
+
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ if (history != nil)
+ [history release];
+ if (auxiliaryWindows != nil)
+ [auxiliaryWindows release];
+
+ [super dealloc];
+}
+
+
+- (void)setCPU:(const device_config *)device {
+ [regView selectSubviewForCPU:device];
+ [dasmView selectSubviewForCPU:device];
+ [window setTitle:[NSString stringWithFormat:@"Debug: %s - %@",
+ device->machine->gamedrv->name,
+ [regView selectedSubviewName]]];
+}
+
+
+- (IBAction)doCommand:(id)sender {
+ NSString *command = [sender stringValue];
+ if ([command length] == 0) {
+ debug_cpu_single_step(machine, 1);
+ } else {
+ debug_console_execute_command(machine, [command UTF8String], 1);
+ [history add:command];
+ }
+ [sender setStringValue:@""];
+}
+
+
+- (IBAction)debugNewMemoryWindow:(id)sender {
+ MAMEMemoryViewer *win = [[MAMEMemoryViewer alloc] initWithMachine:machine console:self];
+ [auxiliaryWindows addObject:win];
+ [win release];
+ [win activate];
+}
+
+
+- (IBAction)debugNewDisassemblyWindow:(id)sender {
+ MAMEDisassemblyViewer *win = [[MAMEDisassemblyViewer alloc] initWithMachine:machine console:self];
+ [auxiliaryWindows addObject:win];
+ [win release];
+ [win activate];
+}
+
+
+- (IBAction)debugNewErrorLogWindow:(id)sender {
+ MAMEDisassemblyViewer *win = [[MAMEErrorLogViewer alloc] initWithMachine:machine console:self];
+ [auxiliaryWindows addObject:win];
+ [win release];
+ [win activate];
+}
+
+
+- (void)showDebugger:(NSNotification *)notification {
+ const device_config *device = [[[notification userInfo] objectForKey:@"MAMEDebugDevice"] pointerValue];
+ if (device->machine == machine) {
+ [self setCPU:device];
+ [window makeKeyAndOrderFront:self];
+ }
+}
+
+
+- (void)auxiliaryWindowWillClose:(NSNotification *)notification {
+ [auxiliaryWindows removeObjectIdenticalTo:[notification object]];
+}
+
+
+- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command {
+ if (control == commandField) {
+ if (command == @selector(cancelOperation:)) {
+ [commandField setStringValue:@""];
+ [history reset];
+ return YES;
+ } else if (command == @selector(moveUp:)) {
+ NSString *hist = [history previous:[commandField stringValue]];
+ if (hist != nil) {
+ [commandField setStringValue:hist];
+ [commandField selectText:self];
+ [(NSText *)[window firstResponder] setSelectedRange:NSMakeRange([hist length], 0)];
+ }
+ return YES;
+ } else if (command == @selector(moveDown:)) {
+ NSString *hist = [history next:[commandField stringValue]];
+ if (hist != nil) {
+ [commandField setStringValue:hist];
+ [commandField selectText:self];
+ [(NSText *)[window firstResponder] setSelectedRange:NSMakeRange([hist length], 0)];
+ }
+ return YES;
+ }
+ }
+ return NO;
+}
+
+
+- (void)windowWillClose:(NSNotification *)notification {
+ if ([notification object] != window)
+ return;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MAMEHideDebuggerNotification object:self];
+ debug_cpu_go(machine, ~0);
+}
+
+
+- (CGFloat)splitView:(NSSplitView *)sender constrainMinCoordinate:(CGFloat)min ofSubviewAt:(NSInteger)offs {
+ return (min < 100) ? 100 : min;
+}
+
+
+- (CGFloat)splitView:(NSSplitView *)sender constrainMaxCoordinate:(CGFloat)max ofSubviewAt:(NSInteger)offs {
+ NSSize sz = [sender bounds].size;
+ CGFloat allowed = ([sender isVertical] ? sz.width : sz.height) - 100 - [sender dividerThickness];
+ return (max > allowed) ? allowed : max;
+}
+
+
+- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview {
+ // allow registers or disassembly to be collapsed, but not console
+ return [[sender subviews] indexOfObjectIdenticalTo:subview] == 0;
+}
+
+
+- (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize {
+ // This can only deal with a single split, but that's all we use, anyway
+ NSRect first, second;
+ [sender adjustSubviews];
+ first = [[[sender subviews] objectAtIndex:0] frame];
+ second = [[[sender subviews] objectAtIndex:1] frame];
+ if ([sender isVertical]) {
+ if (first.size.width < 100) {
+ CGFloat diff = 100 - first.size.width;
+ first.size.width = 100;
+ second.origin.x += diff;
+ second.size.width -= diff;
+ } else if (second.size.width < 100) {
+ CGFloat diff = 100 - second.size.width;
+ second.size.width = 100;
+ second.origin.x -= diff;
+ first.size.width -= diff;
+ }
+ } else {
+ if (first.size.height < 100) {
+ CGFloat diff = 100 - first.size.height;
+ first.size.height = 100;
+ second.origin.y += diff;
+ second.size.height -= diff;
+ } else if (second.size.height < 100) {
+ CGFloat diff = 100 - second.size.height;
+ second.size.height = 100;
+ second.origin.y -= diff;
+ first.size.height -= diff;
+ }
+ }
+ [[[sender subviews] objectAtIndex:0] setFrame:first];
+ [[[sender subviews] objectAtIndex:1] setFrame:second];
+}
+
+@end
+
+
+//============================================================
+// MAMEAuxiliaryDebugWindowHandler class
+//============================================================
+
+@implementation MAMEAuxiliaryDebugWindowHandler
+
++ (void)cascadeWindow:(NSWindow *)window {
+ static NSPoint lastPosition = { 0, 0 };
+ if (NSEqualPoints(lastPosition, NSZeroPoint)) {
+ NSRect available = [[NSScreen mainScreen] visibleFrame];
+ lastPosition = NSMakePoint(available.origin.x + 12, available.origin.y + available.size.height - 8);
+ }
+ lastPosition = [window cascadeTopLeftFromPoint:lastPosition];
+}
+
+
+- (id)initWithMachine:(running_machine *)m title:(NSString *)t console:(MAMEDebugConsole *)c {
+ if (!(self = [super initWithMachine:m title:t]))
+ return nil;
+ console = c;
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+- (IBAction)debugNewMemoryWindow:(id)sender {
+ [console debugNewMemoryWindow:sender];
+}
+
+
+- (IBAction)debugNewDisassemblyWindow:(id)sender {
+ [console debugNewDisassemblyWindow:sender];
+}
+
+
+- (IBAction)debugNewErrorLogWindow:(id)sender {
+ [console debugNewErrorLogWindow:sender];
+}
+
+
+- (void)windowWillClose:(NSNotification *)notification {
+ [[NSNotificationCenter defaultCenter] postNotificationName:MAMEAuxiliaryDebugWindowWillCloseNotification
+ object:self];
+}
+
+- (void)cascadeWindowWithDesiredSize:(NSSize)desired forView:(NSView *)view {
+ NSRect available = [[NSScreen mainScreen] visibleFrame];
+ NSRect windowFrame = [window frame];
+ NSSize current = [view frame].size;
+
+ desired.width -= current.width;
+ desired.height -= current.height;
+
+ windowFrame.size.width += desired.width;
+ windowFrame.size.height += desired.height;
+ windowFrame.size.height = MIN(MIN(windowFrame.size.height, 240), available.size.height);
+ windowFrame.size.width = MIN(windowFrame.size.width, available.size.width);
+ windowFrame.origin.x = available.origin.x + available.size.width - windowFrame.size.width;
+ windowFrame.origin.y = available.origin.y;
+ [window setFrame:windowFrame display:YES];
+ [[self class] cascadeWindow:window];
+
+ windowFrame = [[window contentView] frame];
+ desired = [window contentMinSize];
+ [window setContentMinSize:NSMakeSize(MIN(windowFrame.size.width, desired.width),
+ MIN(windowFrame.size.height, desired.height))];
+}
+
+@end
+
+
+//============================================================
+// MAMEExpreesionAuxiliaryDebugWindowHandler class
+//============================================================
+
+@implementation MAMEExpressionAuxiliaryDebugWindowHandler
+
+- (id)initWithMachine:(running_machine *)m title:(NSString *)t console:(MAMEDebugConsole *)c {
+ if (!(self = [super initWithMachine:m title:t console:c]))
+ return nil;
+ history = [[MAMEDebugCommandHistory alloc] init];
+ return self;
+}
+
+
+- (void)dealloc {
+ if (history != nil)
+ [history release];
+ [super dealloc];
+}
+
+
+- (id <MAMEDebugViewExpressionSupport>)documentView {
+ return nil;
+}
+
+
+- (IBAction)doExpression:(id)sender {
+ NSString *expr = [sender stringValue];
+ if ([expr length] > 0) {
+ [history add:expr];
+ [[self documentView] setExpression:expr];
+ } else {
+ [sender setStringValue:[[self documentView] expression]];
+ [history reset];
+ }
+ [sender selectText:self];
+}
+
+
+- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command {
+ if (control == expressionField) {
+ if (command == @selector(cancelOperation:)) {
+ [history reset];
+ [expressionField setStringValue:[[self documentView] expression]];
+ [expressionField selectText:self];
+ return YES;
+ } else if (command == @selector(moveUp:)) {
+ NSString *hist = [history previous:[expressionField stringValue]];
+ if (hist != nil) {
+ [expressionField setStringValue:hist];
+ [expressionField selectText:self];
+ }
+ return YES;
+ } else if (command == @selector(moveDown:)) {
+ NSString *hist = [history next:[expressionField stringValue]];
+ if (hist != nil) {
+ [expressionField setStringValue:hist];
+ [expressionField selectText:self];
+ }
+ return YES;
+ }
+ }
+ return NO;
+}
+
+@end
+
+
+//============================================================
+// MAMEMemoryViewer class
+//============================================================
+
+@implementation MAMEMemoryViewer
+
+- (id)initWithMachine:(running_machine *)m console:(MAMEDebugConsole *)c {
+ NSScrollView *memoryScroll;
+ NSView *expressionContainer;
+ NSPopUpButton *actionButton, *subviewButton;
+ NSRect contentBounds, expressionFrame;
+
+ if (!(self = [super initWithMachine:m title:@"Memory" console:c]))
+ return nil;
+ contentBounds = [[window contentView] bounds];
+
+ // create the expression field
+ expressionField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)];
+ [expressionField setAutoresizingMask:(NSViewWidthSizable | NSViewMaxXMargin | NSViewMinYMargin)];
+ [expressionField setFont:[[MAMEDebugView class] defaultFont]];
+ [expressionField setFocusRingType:NSFocusRingTypeNone];
+ [expressionField setTarget:self];
+ [expressionField setAction:@selector(doExpression:)];
+ [expressionField setDelegate:self];
+ expressionFrame = [expressionField frame];
+ expressionFrame.size.width = (contentBounds.size.width - expressionFrame.size.height) / 2;
+ [expressionField setFrameSize:expressionFrame.size];
+
+ // create the subview popup
+ subviewButton = [[NSPopUpButton alloc] initWithFrame:NSOffsetRect(expressionFrame,
+ expressionFrame.size.width,
+ 0)];
+ [subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinXMargin | NSViewMinYMargin)];
+ [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [subviewButton setFocusRingType:NSFocusRingTypeNone];
+ [subviewButton setFont:[[MAMEDebugView class] defaultFont]];
+ [subviewButton setTarget:self];
+ [subviewButton setAction:@selector(changeSubview:)];
+ [[subviewButton cell] setArrowPosition:NSPopUpArrowAtBottom];
+
+ // create a container for the expression field and subview popup
+ expressionFrame = NSMakeRect(expressionFrame.size.height,
+ contentBounds.size.height - expressionFrame.size.height,
+ contentBounds.size.width - expressionFrame.size.height,
+ expressionFrame.size.height);
+ expressionContainer = [[NSView alloc] initWithFrame:expressionFrame];
+ [expressionContainer setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
+ [expressionContainer addSubview:expressionField];
+ [expressionField release];
+ [expressionContainer addSubview:subviewButton];
+ [subviewButton release];
+ [[window contentView] addSubview:expressionContainer];
+ [expressionContainer release];
+
+ // create the memory view
+ memoryView = [[MAMEMemoryView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)
+ machine:machine];
+ [memoryView insertSubviewItemsInMenu:[subviewButton menu] atIndex:0];
+ memoryScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,
+ 0,
+ contentBounds.size.width,
+ expressionFrame.origin.y)];
+ [memoryScroll setDrawsBackground:YES];
+ [memoryScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [memoryScroll setHasHorizontalScroller:YES];
+ [memoryScroll setHasVerticalScroller:YES];
+ [memoryScroll setAutohidesScrollers:YES];
+ [memoryScroll setBorderType:NSNoBorder];
+ [memoryScroll setDocumentView:memoryView];
+ [memoryView release];
+ [[window contentView] addSubview:memoryScroll];
+ [memoryScroll release];
+
+ // create the action popup
+ actionButton = [[self class] newActionButtonWithFrame:NSMakeRect(0,
+ expressionFrame.origin.y,
+ expressionFrame.size.height,
+ expressionFrame.size.height)];
+ [actionButton setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)];
+ [memoryView insertActionItemsInMenu:[actionButton menu] atIndex:1];
+ [[window contentView] addSubview:actionButton];
+ [actionButton release];
+
+ // set default state
+ [memoryView selectSubviewForCPU:debug_cpu_get_visible_cpu(machine)];
+ [memoryView setExpression:@"0"];
+ [expressionField setStringValue:@"0"];
+ [expressionField selectText:self];
+ [subviewButton selectItemAtIndex:[subviewButton indexOfItemWithTag:[memoryView selectedSubviewIndex]]];
+ [window makeFirstResponder:expressionField];
+ [window setTitle:[NSString stringWithFormat:@"Memory: %@", [memoryView selectedSubviewName]]];
+
+ // calculate the optimal size for everything
+ {
+ NSSize desired = [NSScrollView frameSizeForContentSize:[memoryView maximumFrameSize]
+ hasHorizontalScroller:YES
+ hasVerticalScroller:YES
+ borderType:[memoryScroll borderType]];
+ [self cascadeWindowWithDesiredSize:desired forView:memoryScroll];
+ }
+
+ // don't forget the result
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+- (id <MAMEDebugViewExpressionSupport>)documentView {
+ return memoryView;
+}
+
+
+- (IBAction)changeSubview:(id)sender {
+ [memoryView selectSubviewAtIndex:[[sender selectedItem] tag]];
+ [window setTitle:[NSString stringWithFormat:@"Memory: %@", [memoryView selectedSubviewName]]];
+}
+
+@end
+
+
+//============================================================
+// MAMEDisassemblyViewer class
+//============================================================
+
+@implementation MAMEDisassemblyViewer
+
+- (id)initWithMachine:(running_machine *)m console:(MAMEDebugConsole *)c {
+ NSScrollView *dasmScroll;
+ NSView *expressionContainer;
+ NSPopUpButton *actionButton, *subviewButton;
+ NSRect contentBounds, expressionFrame;
+
+ if (!(self = [super initWithMachine:m title:@"Disassembly" console:c]))
+ return nil;
+ contentBounds = [[window contentView] bounds];
+
+ // create the expression field
+ expressionField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 19)];
+ [expressionField setAutoresizingMask:(NSViewWidthSizable | NSViewMaxXMargin | NSViewMinYMargin)];
+ [expressionField setFont:[[MAMEDebugView class] defaultFont]];
+ [expressionField setFocusRingType:NSFocusRingTypeNone];
+ [expressionField setTarget:self];
+ [expressionField setAction:@selector(doExpression:)];
+ [expressionField setDelegate:self];
+ expressionFrame = [expressionField frame];
+ expressionFrame.size.width = (contentBounds.size.width - expressionFrame.size.height) / 2;
+ [expressionField setFrameSize:expressionFrame.size];
+
+ // create the subview popup
+ subviewButton = [[NSPopUpButton alloc] initWithFrame:NSOffsetRect(expressionFrame,
+ expressionFrame.size.width,
+ 0)];
+ [subviewButton setAutoresizingMask:(NSViewWidthSizable | NSViewMinXMargin | NSViewMinYMargin)];
+ [subviewButton setBezelStyle:NSShadowlessSquareBezelStyle];
+ [subviewButton setFocusRingType:NSFocusRingTypeNone];
+ [subviewButton setFont:[[MAMEDebugView class] defaultFont]];
+ [subviewButton setTarget:self];
+ [subviewButton setAction:@selector(changeSubview:)];
+ [[subviewButton cell] setArrowPosition:NSPopUpArrowAtBottom];
+
+ // create a container for the expression field and subview popup
+ expressionFrame = NSMakeRect(expressionFrame.size.height,
+ contentBounds.size.height - expressionFrame.size.height,
+ contentBounds.size.width - expressionFrame.size.height,
+ expressionFrame.size.height);
+ expressionContainer = [[NSView alloc] initWithFrame:expressionFrame];
+ [expressionContainer setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
+ [expressionContainer addSubview:expressionField];
+ [expressionField release];
+ [expressionContainer addSubview:subviewButton];
+ [subviewButton release];
+ [[window contentView] addSubview:expressionContainer];
+ [expressionContainer release];
+
+ // create the disassembly view
+ dasmView = [[MAMEDisassemblyView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)
+ machine:machine
+ useConsole:NO];
+ [dasmView insertSubviewItemsInMenu:[subviewButton menu] atIndex:0];
+ dasmScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,
+ 0,
+ contentBounds.size.width,
+ expressionFrame.origin.y)];
+ [dasmScroll setDrawsBackground:YES];
+ [dasmScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [dasmScroll setHasHorizontalScroller:YES];
+ [dasmScroll setHasVerticalScroller:YES];
+ [dasmScroll setAutohidesScrollers:YES];
+ [dasmScroll setBorderType:NSNoBorder];
+ [dasmScroll setDocumentView:dasmView];
+ [dasmView release];
+ [[window contentView] addSubview:dasmScroll];
+ [dasmScroll release];
+
+ // create the action popup
+ actionButton = [[self class] newActionButtonWithFrame:NSMakeRect(0,
+ expressionFrame.origin.y,
+ expressionFrame.size.height,
+ expressionFrame.size.height)];
+ [actionButton setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)];
+ [dasmView insertActionItemsInMenu:[actionButton menu] atIndex:1];
+ [[window contentView] addSubview:actionButton];
+ [actionButton release];
+
+ // set default state
+ [dasmView selectSubviewForCPU:debug_cpu_get_visible_cpu(machine)];
+ [dasmView setExpression:@"curpc"];
+ [expressionField setStringValue:@"curpc"];
+ [expressionField selectText:self];
+ [subviewButton selectItemAtIndex:[subviewButton indexOfItemWithTag:[dasmView selectedSubviewIndex]]];
+ [window makeFirstResponder:expressionField];
+ [window setTitle:[NSString stringWithFormat:@"Disassembly: %@", [dasmView selectedSubviewName]]];
+
+ // calculate the optimal size for everything
+ {
+ NSSize desired = [NSScrollView frameSizeForContentSize:[dasmView maximumFrameSize]
+ hasHorizontalScroller:YES
+ hasVerticalScroller:YES
+ borderType:[dasmScroll borderType]];
+ [self cascadeWindowWithDesiredSize:desired forView:dasmScroll];
+ }
+
+ // don't forget the result
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+- (id <MAMEDebugViewExpressionSupport>)documentView {
+ return dasmView;
+}
+
+
+- (IBAction)changeSubview:(id)sender {
+ [dasmView selectSubviewAtIndex:[[sender selectedItem] tag]];
+ [window setTitle:[NSString stringWithFormat:@"Disassembly: %@", [dasmView selectedSubviewName]]];
+}
+
+@end
+
+
+//============================================================
+// MAMEErrorLogViewer class
+//============================================================
+
+@implementation MAMEErrorLogViewer
+
+- (id)initWithMachine:(running_machine *)m console:(MAMEDebugConsole *)c {
+ NSScrollView *logScroll;
+ NSString *title;
+
+ title = [NSString stringWithFormat:@"Error Log: %@ [%@]",
+ [NSString stringWithUTF8String:m->gamedrv->description],
+ [NSString stringWithUTF8String:m->gamedrv->name]];
+ if (!(self = [super initWithMachine:m title:title console:c]))
+ return nil;
+
+ // create the error log view
+ logView = [[MAMEErrorLogView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) machine:machine];
+ logScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [logScroll setDrawsBackground:YES];
+ [logScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [logScroll setHasHorizontalScroller:YES];
+ [logScroll setHasVerticalScroller:YES];
+ [logScroll setAutohidesScrollers:YES];
+ [logScroll setBorderType:NSNoBorder];
+ [logScroll setDocumentView:logView];
+ [logView release];
+ [window setContentView:logScroll];
+ [logScroll release];
+
+ // calculate the optimal size for everything
+ {
+ NSSize desired = [NSScrollView frameSizeForContentSize:[logView maximumFrameSize]
+ hasHorizontalScroller:YES
+ hasVerticalScroller:YES
+ borderType:[logScroll borderType]];
+
+ // this thing starts with no content, so its prefered height may be very small
+ desired.height = MAX(desired.height, 240);
+ [self cascadeWindowWithDesiredSize:desired forView:logScroll];
+ }
+
+ // don't forget the result
+ return self;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+@end