diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 3dab9ed..8e01fb4 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -226,6 +226,8 @@ 32C8233A2908822E0018438F /* DebuggerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C823392908822E0018438F /* DebuggerWindowController.swift */; }; 32C82356290888C50018438F /* DebuggerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C823392908822E0018438F /* DebuggerWindowController.swift */; }; 32C82360290888D10018438F /* CheatMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32100A8A2875387300D894EE /* CheatMenu.swift */; }; + 32D0897C291A44F200F2B486 /* 6502_bp.c in Sources */ = {isa = PBXBuildFile; fileRef = 32D0897B291A44F200F2B486 /* 6502_bp.c */; }; + 32D0897D291A44F200F2B486 /* 6502_bp.c in Sources */ = {isa = PBXBuildFile; fileRef = 32D0897B291A44F200F2B486 /* 6502_bp.c */; }; 32E3126624A7193700E61891 /* disk_ii_arm.sfx in Resources */ = {isa = PBXBuildFile; fileRef = 32E3126424A7193700E61891 /* disk_ii_arm.sfx */; }; 32E3126724A7194900E61891 /* disk_ii_arm.sfx in Copy SFX Files */ = {isa = PBXBuildFile; fileRef = 32E3126424A7193700E61891 /* disk_ii_arm.sfx */; }; 32E3126924A98B9300E61891 /* dsk2woz.c in Sources */ = {isa = PBXBuildFile; fileRef = 32E3126824A98B9300E61891 /* dsk2woz.c */; }; @@ -742,6 +744,8 @@ 32C4532D233345420000EBA1 /* MonitorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonitorView.swift; sourceTree = ""; }; 32C6995127C5439300D0F25D /* Debugger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debugger.swift; sourceTree = ""; }; 32C823392908822E0018438F /* DebuggerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebuggerWindowController.swift; sourceTree = ""; }; + 32D0897B291A44F200F2B486 /* 6502_bp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 6502_bp.c; sourceTree = ""; }; + 32D08987291A450400F2B486 /* 6502_bp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 6502_bp.h; sourceTree = ""; }; 32DBF7632334657900DD50E7 /* HiRes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiRes.swift; sourceTree = ""; }; 32DBF76723373FB400DD50E7 /* disassembler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = disassembler.h; sourceTree = ""; }; 32E21BE62491BF8B006C0C72 /* apple-rainbow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apple-rainbow.png"; sourceTree = ""; }; @@ -990,6 +994,8 @@ 32439F7422ECD8AD0077AAE0 /* 6502.c */, 325B7652290A32CC00B29605 /* 6502_debugger.h */, 325B75DF2909F95000B29605 /* 6502_debugger.c */, + 32D08987291A450400F2B486 /* 6502_bp.h */, + 32D0897B291A44F200F2B486 /* 6502_bp.c */, 320F2A8924CFFBE300671B35 /* 6502_std.h */, 320F2A8A24D0001600671B35 /* 6502_und.h */, 320F2A8B24D0828600671B35 /* 6502_C.h */, @@ -1657,6 +1663,7 @@ 32799F86264B1A5700255669 /* HiRes.swift in Sources */, 32799F87264B1A5700255669 /* LoRes.swift in Sources */, 32C6995327C5439300D0F25D /* Debugger.swift in Sources */, + 32D0897D291A44F200F2B486 /* 6502_bp.c in Sources */, 325B761B290A0C4200B29605 /* 6502_debugger.c in Sources */, 327B75D829064FDC00A86A71 /* DebuggerViewController.swift in Sources */, 32799F88264B1A5700255669 /* RepeatingTimer.swift in Sources */, @@ -1676,6 +1683,7 @@ 32E3126D24AC033A00E61891 /* ToolBarController.swift in Sources */, 323D043024898AB70086A901 /* PreferencesViewController.swift in Sources */, 32100A9F28753AAA00D894EE /* SubMenu.swift in Sources */, + 32D0897C291A44F200F2B486 /* 6502_bp.c in Sources */, 32BCCCE9264DBDC8002151C5 /* 6502.c in Sources */, 323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */, 32E3126924A98B9300E61891 /* dsk2woz.c in Sources */, diff --git a/A2Mac/A2Mac-Bridging-Header.h b/A2Mac/A2Mac-Bridging-Header.h index d9c5376..0ebffe6 100644 --- a/A2Mac/A2Mac-Bridging-Header.h +++ b/A2Mac/A2Mac-Bridging-Header.h @@ -29,6 +29,7 @@ #import "6502.h" +#import "6502_bp.h" #import "6502_debugger.h" #import "disassembler.h" #import "speaker.h" // So we can access to speaker stuff from Swift diff --git a/A2Mac/DebuggerWindowController.swift b/A2Mac/DebuggerWindowController.swift index 7113169..213e787 100644 --- a/A2Mac/DebuggerWindowController.swift +++ b/A2Mac/DebuggerWindowController.swift @@ -39,6 +39,8 @@ class DebuggerWindowController: NSWindowController, NSWindowDelegate { if isWindowFullscreen { window?.toggleFullScreen(self) } + + m6502_dbg_init() } diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index e4038cd..e2ec58e 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -1267,7 +1267,7 @@ class ViewController: NSViewController { let UpdateSemaphore = DispatchSemaphore(value: 1) func Update() { - if UpdateSemaphore.wait(timeout: DispatchTime.now() + 0.001) == .timedOut { + if UpdateSemaphore.wait(timeout: .now() + 0.001) == .timedOut { // get back here next time... print("UpdateSemaphore.wait") return diff --git a/src/cpu/6502.c b/src/cpu/6502.c index 4a12fb7..bb53cbb 100644 --- a/src/cpu/6502.c +++ b/src/cpu/6502.c @@ -39,6 +39,7 @@ #include #include #include "6502.h" +#include "6502_bp.h" #include "speaker.h" @@ -435,6 +436,12 @@ void m6502_Debug(void) { } } + if ( m6502_dbg_bp_is_exists(m6502.PC) ) { + cpuState = cpuState_halted; + m6502.debugger.wMask = 0; + return; + } + for ( clk_6502_per_frm_max = clk_6502_per_frm; m6502.clkfrm < clk_6502_per_frm_max ; m6502.clkfrm += m6502_Step() ) { switch (m6502.interrupt) { case HALT: diff --git a/src/cpu/6502_bp.c b/src/cpu/6502_bp.c new file mode 100644 index 0000000..bff4aa8 --- /dev/null +++ b/src/cpu/6502_bp.c @@ -0,0 +1,118 @@ +// +// main.c +// 6502 +// +// Created by Tamas Rudnai on 7/14/19. +// Copyright © 2019, 2020 Tamas Rudnai. All rights reserved. +// +// This file is part of Steve ][ -- The Apple ][ Emulator. +// +// Steve ][ is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Steve ][ is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Steve ][. If not, see . +// +// Documentations: +// +// http://nesdev.com/6502_cpu.txt +// http://www.oxyron.de/html/opcodes02.html +// https://macgui.com/kb/article/46 +// https://www.masswerk.at/6502/6502_instruction_set.html +// + +#include +#include "6502_bp.h" + + +uint16_t breakpoints[DEBUG_MAX_BREAKPOINTS]; +int bp_idx = 0; + + +/// m6502_dbg_bp_get_empty +/// Get an empty slot in the bp astorage +/// @return Index of the empty breakpoint or -1 if error +int m6502_dbg_bp_get_empty() { + for (int i = 0; i < DEBUG_MAX_BREAKPOINTS; i++) { + if ( breakpoints[i] == 0 ) { + return i; + } + } + // no empty slots + return -1; +} + + +/// m6502_dbg_bp_get_first +/// Get first valid BP +/// @return addr of BP or 0 if non +uint16_t m6502_dbg_bp_get_next() { + while ( bp_idx < DEBUG_MAX_BREAKPOINTS ) { + uint16_t addr = breakpoints[++bp_idx]; + if (addr) { + return addr; + } + } + // no empty slots + return 0; +} + + +/// m6502_dbg_bp_get_first +/// Get first valid BP +/// @return addr of BP or 0 if non +uint16_t m6502_dbg_bp_get_first() { + bp_idx = -1; + return m6502_dbg_bp_get_next(); +} + + +/// m6502_dbg_bp_get_first +/// Get first valid BP +/// @return addr of BP or 0 if non +uint16_t m6502_dbg_bp_is_exists(uint16_t addr) { + for (uint16_t bp = m6502_dbg_bp_get_first(); bp; bp = m6502_dbg_bp_get_next()) { + if ( bp == addr) { + // found it! + return bp; + } + } + return 0; +} + + +/// m6502_dbg_bp_add +/// Add breakpoint +/// @param addr address to add +/// @return Index of breakpoint or -1 if error +int m6502_dbg_bp_add(uint16_t addr) { + int i = m6502_dbg_bp_get_empty(); + if ( i >= 0 ) { + breakpoints[i] = addr; + return i; + } + // no empty slots + return -1; +} + + +void m6502_dbg_bp_init(void) { + bp_idx = 0; + memset(breakpoints, 0, sizeof(breakpoints)); + + m6502_dbg_bp_add(0xC28B); // keyin DOS 3.3 +} + + +void m6502_dbg_init(void) { + m6502_dbg_bp_init(); +} + + diff --git a/src/cpu/6502_bp.h b/src/cpu/6502_bp.h new file mode 100644 index 0000000..5e6ba8f --- /dev/null +++ b/src/cpu/6502_bp.h @@ -0,0 +1,22 @@ +// +// 6502_debugger.h +// A2Mac +// +// Created by Tamas Rudnai on 10/26/22. +// Copyright © 2022 GameAlloy. All rights reserved. +// + +#ifndef _6502_bp_h +#define _6502_bp_h + +#include + +#define DEBUG_MAX_BREAKPOINTS 256 +extern uint16_t breakpoints[DEBUG_MAX_BREAKPOINTS]; + +extern void m6502_dbg_init(void); +extern int m6502_dbg_bp_add(uint16_t addr); +extern uint16_t m6502_dbg_bp_is_exists(uint16_t addr); + + +#endif /* _6502_bp_h */ diff --git a/src/cpu/6502_debugger.c b/src/cpu/6502_debugger.c index 8303b47..77f3bdf 100644 --- a/src/cpu/6502_debugger.c +++ b/src/cpu/6502_debugger.c @@ -74,6 +74,7 @@ typedef struct { **/ +#include "6502_debugger.h" #include "6502_instructions.h" INLINE int m6502_Disass_1_Instr(void) { diff --git a/src/util/disassembler.c b/src/util/disassembler.c index 3e32208..f71db4f 100644 --- a/src/util/disassembler.c +++ b/src/util/disassembler.c @@ -33,8 +33,14 @@ INLINE flags_t getFlags2(void) { void _disHexB( char ** s, const uint8_t b ) { // if ( m6502.dbgLevel.trace ) { + if ( (*s >= disassembly.opcode) && (*s < disassembly.opcode + sizeof(disassembly.opcode)) ) { snprintf(*s, 4, "%02X ", b); *s += 3; + } + else { + fprintf(stderr, "_disHexB *s is WRONG! (%p vs %p)\n", *s, disassembly.opcode); + } + // } }