From 7a6b8c1f3888b0dff7eddc41a1a8c670a2b486f3 Mon Sep 17 00:00:00 2001 From: tudnai Date: Wed, 16 Mar 2022 10:17:32 -0700 Subject: [PATCH] AUX RAM fix, Woz adjustments, disassembler separated, new ROMs --- A2Mac.xcodeproj/project.pbxproj | 46 ++++- .../xcdebugger/Expressions.xcexplist | 5 + A2Mac/Base.lproj/Main.storyboard | 8 +- A2Mac/ViewController.swift | 4 +- ...19 Apple IIe Diagnostic Card - English.rom | Bin 0 -> 16384 bytes .../rom/{Apple2e.rom => Apple2e_16k.rom} | Bin Resources/rom/Apple2e_32k.rom | Bin 0 -> 32768 bytes convert_disass.py | 27 +++ src/cpu/6502.c | 37 ++-- src/cpu/6502.h | 14 +- src/dev/audio/speaker.c | 11 +- src/dev/disk/woz.c | 10 +- src/dev/disk/woz.h | 1 + src/dev/mem/mmio.c | 182 +++++++++++++----- src/dev/mem/mmio.h | 5 +- src/util/disassembler.c | 107 ++++++++++ src/util/disassembler.h | 116 ++--------- 17 files changed, 385 insertions(+), 188 deletions(-) create mode 100644 Resources/rom/077-0019 Apple IIe Diagnostic Card - English.rom rename Resources/rom/{Apple2e.rom => Apple2e_16k.rom} (100%) create mode 100755 Resources/rom/Apple2e_32k.rom create mode 100755 convert_disass.py create mode 100644 src/util/disassembler.c diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 16498d1..a555945 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ 323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 323D04312489BFD80086A901 /* PreferencesWindowController.swift */; }; 323D04442490B3930086A901 /* dotmatrix_effect.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 323D04432490B3930086A901 /* dotmatrix_effect.png */; }; 323E2DCF245531E600156805 /* Apple2e_Enhanced.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */; }; - 323E2DD1245531E600156805 /* Apple2e.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e.rom */; }; + 323E2DD1245531E600156805 /* Apple2e_16k.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e_16k.rom */; }; 32440BA32480D5C0000F9DA1 /* LoRes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32440BA22480D5C0000F9DA1 /* LoRes.swift */; }; 324D15D324ADAC71008AAFB0 /* floppy.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 324D15D224ADAC71008AAFB0 /* floppy.png */; }; 32544195264A6C1600B7E3ED /* DisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32544194264A6C1600B7E3ED /* DisplayView.swift */; }; @@ -58,6 +58,16 @@ 325EB6AC2401118300C6B4A4 /* Xonix.woz in Resources */ = {isa = PBXBuildFile; fileRef = 325EB69B2401118300C6B4A4 /* Xonix.woz */; }; 3267641624B6572E000BEA11 /* Merlin Assembler.woz in Copy Disk Images */ = {isa = PBXBuildFile; fileRef = 3267641524B6572E000BEA11 /* Merlin Assembler.woz */; }; 3267641824BCC9A5000BEA11 /* COPYING in Resources */ = {isa = PBXBuildFile; fileRef = 3267641724BCC9A5000BEA11 /* COPYING */; }; + 3268B97A27DE7D6A003FBDCC /* disassembler.c in Sources */ = {isa = PBXBuildFile; fileRef = 3268B97927DE7D6A003FBDCC /* disassembler.c */; }; + 3268B97B27DE7D6B003FBDCC /* disassembler.c in Sources */ = {isa = PBXBuildFile; fileRef = 3268B97927DE7D6A003FBDCC /* disassembler.c */; }; + 3268B97C27DE7D6B003FBDCC /* disassembler.c in Sources */ = {isa = PBXBuildFile; fileRef = 3268B97927DE7D6A003FBDCC /* disassembler.c */; }; + 3268B99127DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Resources */ = {isa = PBXBuildFile; fileRef = 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */; }; + 3268B99227DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Resources */ = {isa = PBXBuildFile; fileRef = 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */; }; + 3268B99327DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Resources */ = {isa = PBXBuildFile; fileRef = 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */; }; + 3268B9A627DEAD44003FBDCC /* Apple2e_32k.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 3268B98F27DEAC73003FBDCC /* Apple2e_32k.rom */; }; + 3268B9B027DEAD51003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */; }; + 3268B9C327DEAE37003FBDCC /* Apple2e_32k.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 3268B98F27DEAC73003FBDCC /* Apple2e_32k.rom */; }; + 3268B9E927DEDD61003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */; }; 326B56E524AD8E89009BA0AC /* gobackward.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 326B56E424AD8E89009BA0AC /* gobackward.png */; }; 326B56E724AD906D009BA0AC /* doc.text.viewfinder.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 326B56E624AD906D009BA0AC /* doc.text.viewfinder.png */; }; 3277D779273AE0DA00749544 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 32BFFB6022EACC660003B53F /* Main.storyboard */; }; @@ -87,7 +97,7 @@ 32799F94264B1A5700255669 /* PRNumber3.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 32089E4724556DBD0036E667 /* PRNumber3.ttf */; }; 32799F96264B1A5700255669 /* apple.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 32439F8422ECD8AD0077AAE0 /* apple.rom */; }; 32799F97264B1A5700255669 /* Apple2e_Enhanced.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */; }; - 32799F98264B1A5700255669 /* Apple2e.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e.rom */; }; + 32799F98264B1A5700255669 /* Apple2e_16k.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e_16k.rom */; }; 32799F99264B1A5700255669 /* Apple2Plus.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 325EB67F23FBDF8F00C6B4A4 /* Apple2Plus.rom */; }; 32799F9A264B1A5700255669 /* DISK_II_C600.ROM in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 325EB68223FBDFBA00C6B4A4 /* DISK_II_C600.ROM */; }; 32799F9C264B1A5700255669 /* blank.woz in Copy Disk Images */ = {isa = PBXBuildFile; fileRef = 32440B9C247F9DC7000F9DA1 /* blank.woz */; }; @@ -218,7 +228,7 @@ 32F8A87D24A3A84700EE6735 /* PRNumber3.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 32089E4724556DBD0036E667 /* PRNumber3.ttf */; }; 32F8A87F24A3A8A000EE6735 /* apple.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 32439F8422ECD8AD0077AAE0 /* apple.rom */; }; 32F8A88024A3A8A300EE6735 /* Apple2e_Enhanced.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */; }; - 32F8A88124A3A8A600EE6735 /* Apple2e.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e.rom */; }; + 32F8A88124A3A8A600EE6735 /* Apple2e_16k.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e_16k.rom */; }; 32F8A88224A3A8AA00EE6735 /* Apple2Plus.rom in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 325EB67F23FBDF8F00C6B4A4 /* Apple2Plus.rom */; }; 32F8A88324A3A8B200EE6735 /* DISK_II_C600.ROM in Copy ROM Images */ = {isa = PBXBuildFile; fileRef = 325EB68223FBDFBA00C6B4A4 /* DISK_II_C600.ROM */; }; 32F8A88524A3A91100EE6735 /* blank.woz in Copy Disk Images */ = {isa = PBXBuildFile; fileRef = 32440B9C247F9DC7000F9DA1 /* blank.woz */; }; @@ -310,9 +320,11 @@ dstPath = rom; dstSubfolderSpec = 7; files = ( + 3268B9E927DEDD61003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Copy ROM Images */, 32799F96264B1A5700255669 /* apple.rom in Copy ROM Images */, 32799F97264B1A5700255669 /* Apple2e_Enhanced.rom in Copy ROM Images */, - 32799F98264B1A5700255669 /* Apple2e.rom in Copy ROM Images */, + 32799F98264B1A5700255669 /* Apple2e_16k.rom in Copy ROM Images */, + 3268B9C327DEAE37003FBDCC /* Apple2e_32k.rom in Copy ROM Images */, 32799F99264B1A5700255669 /* Apple2Plus.rom in Copy ROM Images */, 32799F9A264B1A5700255669 /* DISK_II_C600.ROM in Copy ROM Images */, ); @@ -424,9 +436,11 @@ dstPath = rom; dstSubfolderSpec = 7; files = ( + 3268B9B027DEAD51003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Copy ROM Images */, 32F8A87F24A3A8A000EE6735 /* apple.rom in Copy ROM Images */, 32F8A88024A3A8A300EE6735 /* Apple2e_Enhanced.rom in Copy ROM Images */, - 32F8A88124A3A8A600EE6735 /* Apple2e.rom in Copy ROM Images */, + 32F8A88124A3A8A600EE6735 /* Apple2e_16k.rom in Copy ROM Images */, + 3268B9A627DEAD44003FBDCC /* Apple2e_32k.rom in Copy ROM Images */, 32F8A88224A3A8AA00EE6735 /* Apple2Plus.rom in Copy ROM Images */, 32F8A88324A3A8B200EE6735 /* DISK_II_C600.ROM in Copy ROM Images */, ); @@ -541,7 +555,7 @@ 323D04432490B3930086A901 /* dotmatrix_effect.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dotmatrix_effect.png; sourceTree = ""; }; 323D04452490BA1E0086A901 /* scanlines.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = scanlines.png; sourceTree = ""; }; 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = Apple2e_Enhanced.rom; sourceTree = ""; }; - 323E2DCD245531E500156805 /* Apple2e.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = Apple2e.rom; sourceTree = ""; }; + 323E2DCD245531E500156805 /* Apple2e_16k.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = Apple2e_16k.rom; sourceTree = ""; }; 32439F7222ECD8AC0077AAE0 /* A2Mac-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "A2Mac-Bridging-Header.h"; sourceTree = ""; }; 32439F7322ECD8AD0077AAE0 /* mmio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mmio.h; sourceTree = ""; }; 32439F7422ECD8AD0077AAE0 /* 6502.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 6502.c; sourceTree = ""; }; @@ -633,6 +647,9 @@ 3267641524B6572E000BEA11 /* Merlin Assembler.woz */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Merlin Assembler.woz"; sourceTree = ""; }; 3267641724BCC9A5000BEA11 /* COPYING */ = {isa = PBXFileReference; lastKnownFileType = text; path = COPYING; sourceTree = ""; }; 3268B96F27DBD219003FBDCC /* convert_spkr_buf_to_wav.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = convert_spkr_buf_to_wav.py; sourceTree = SOURCE_ROOT; }; + 3268B97927DE7D6A003FBDCC /* disassembler.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = disassembler.c; sourceTree = ""; }; + 3268B98F27DEAC73003FBDCC /* Apple2e_32k.rom */ = {isa = PBXFileReference; lastKnownFileType = file; name = Apple2e_32k.rom; path = Resources/rom/Apple2e_32k.rom; sourceTree = SOURCE_ROOT; }; + 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = "077-0019 Apple IIe Diagnostic Card - English.rom"; sourceTree = ""; }; 3268E68E2474E24900047474 /* paddle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = paddle.h; sourceTree = ""; }; 326B56E424AD8E89009BA0AC /* gobackward.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gobackward.png; sourceTree = ""; }; 326B56E624AD906D009BA0AC /* doc.text.viewfinder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = doc.text.viewfinder.png; sourceTree = ""; }; @@ -843,8 +860,10 @@ children = ( 326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */, 32439F8422ECD8AD0077AAE0 /* apple.rom */, + 3268B99027DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom */, 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */, - 323E2DCD245531E500156805 /* Apple2e.rom */, + 323E2DCD245531E500156805 /* Apple2e_16k.rom */, + 3268B98F27DEAC73003FBDCC /* Apple2e_32k.rom */, 325EB67F23FBDF8F00C6B4A4 /* Apple2Plus.rom */, 325EB68223FBDFBA00C6B4A4 /* DISK_II_C600.ROM */, ); @@ -922,6 +941,7 @@ 32439F8622ECD8AD0077AAE0 /* common.h */, 325EB63823F9E48100C6B4A4 /* common.c */, 32DBF76723373FB400DD50E7 /* disassembler.h */, + 3268B97927DE7D6A003FBDCC /* disassembler.c */, ); path = util; sourceTree = ""; @@ -1419,6 +1439,7 @@ 325EB68423FBDFBB00C6B4A4 /* DISK_II_C600.ROM in Resources */, 325EB69E2401118300C6B4A4 /* Lode Runner.woz in Resources */, 325EB68123FBDF8F00C6B4A4 /* Apple2Plus.rom in Resources */, + 3268B99327DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Resources */, 325EB6AA2401118300C6B4A4 /* Sneakers.woz in Resources */, 32E3126624A7193700E61891 /* disk_ii_arm.sfx in Resources */, 32089E4924556DBD0036E667 /* PRNumber3.ttf in Resources */, @@ -1428,7 +1449,7 @@ 325EB68A23FDDF6200C6B4A4 /* Hard Hat Mack - Disk 1, Side A.woz in Resources */, 325EB6A02401118300C6B4A4 /* Crossfire.woz in Resources */, 325EB64C23FBBAD100C6B4A4 /* Assets.xcassets in Resources */, - 323E2DD1245531E600156805 /* Apple2e.rom in Resources */, + 323E2DD1245531E600156805 /* Apple2e_16k.rom in Resources */, 325EB68D23FDDFD200C6B4A4 /* Merlin-8 v2.48 (DOS 3.3).woz in Resources */, 325EB6A62401118300C6B4A4 /* ProDOS_312.woz in Resources */, 325EB6AC2401118300C6B4A4 /* Xonix.woz in Resources */, @@ -1461,6 +1482,7 @@ 32BCCD1A2650D3B1002151C5 /* Debug-Info.plist in Resources */, 32799F8D264B1A5700255669 /* COPYING in Resources */, 32799F8F264B1A5700255669 /* Assets.xcassets in Resources */, + 3268B99227DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Resources */, 3277D783273AE0DC00749544 /* Main.storyboard in Resources */, 32799F90264B1A5700255669 /* Preferences.storyboard in Resources */, 32799F91264B1A5700255669 /* Steve2Icon.icns in Resources */, @@ -1474,6 +1496,7 @@ 32BCCD192650D3B1002151C5 /* Debug-Info.plist in Resources */, 3267641824BCC9A5000BEA11 /* COPYING in Resources */, 32BFFB5F22EACC660003B53F /* Assets.xcassets in Resources */, + 3268B99127DEAC84003FBDCC /* 077-0019 Apple IIe Diagnostic Card - English.rom in Resources */, 3277D779273AE0DA00749544 /* Main.storyboard in Resources */, 323D042E248980600086A901 /* Preferences.storyboard in Resources */, 320F2A8824CFD74100671B35 /* Steve2Icon.icns in Resources */, @@ -1529,6 +1552,7 @@ 32A9F74B2467B60B004902A1 /* speaker.c in Sources */, 32A6AB11266AF5160023257A /* paddle.c in Sources */, 32A6AB26266B196A0023257A /* hires.c in Sources */, + 3268B97C27DE7D6B003FBDCC /* disassembler.c in Sources */, 325EB67823FBC45300C6B4A4 /* disk.c in Sources */, 325EB64723FBBACF00C6B4A4 /* ViewController.swift in Sources */, 325EB64323FBBACF00C6B4A4 /* AppDelegate.swift in Sources */, @@ -1568,6 +1592,7 @@ 32799F7E264B1A5700255669 /* PreferencesWindowController.swift in Sources */, 32799F80264B1A5700255669 /* dsk2woz.c in Sources */, 32799F81264B1A5700255669 /* disk.c in Sources */, + 3268B97B27DE7D6B003FBDCC /* disassembler.c in Sources */, 32C6996727C548C900D0F25D /* Shaders.metal in Sources */, 32799F82264B1A5700255669 /* woz.c in Sources */, 32A6AB10266AF5160023257A /* paddle.c in Sources */, @@ -1597,6 +1622,7 @@ 323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */, 32E3126924A98B9300E61891 /* dsk2woz.c in Sources */, 325EB63623F8F78300C6B4A4 /* disk.c in Sources */, + 3268B97A27DE7D6A003FBDCC /* disassembler.c in Sources */, 32C6995D27C548C800D0F25D /* Shaders.metal in Sources */, 325EB62F23F8856F00C6B4A4 /* woz.c in Sources */, 32A6AB0F266AF5160023257A /* paddle.c in Sources */, @@ -2073,7 +2099,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MARKETING_VERSION = 0.86; OTHER_CFLAGS = ( - "-D_NO_DISASSEMBLER", + "-DDISASSEMBLER", "-D_NO_INTERRUPT_CHECK_PER_STEP", "-D_NO_CLK_ABSOLUTE_PRECISE", ); @@ -2115,7 +2141,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MARKETING_VERSION = 0.86; OTHER_CFLAGS = ( - "-D_NO_DISASSEMBLER", + "-DDISASSEMBLER", "-D_NO_INTERRUPT_CHECK_PER_STEP", "-D_NO_CLK_ABSOLUTE_PRECISE", ); diff --git a/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist b/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist index 82d931f..9c06755 100644 --- a/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist +++ b/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist @@ -462,6 +462,11 @@ + + + + diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index e3394a4..6827fcb 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -1035,12 +1035,18 @@ - + + + + + + + diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index ead7f4d..f068fe1 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -134,7 +134,9 @@ class ViewController: NSViewController { static var charConvTbl = charConvTblFlashOn - static var romFileName = "Apple2e_Enhanced.rom"; +// static var romFileName = "Apple2e_Enhanced.rom"; + static var romFileName = "Apple2e_32k.rom"; +// static var romFileName = "077-0019 Apple IIe Diagnostic Card - English.rom"; static let textLineOfs : [Int] = [ 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x028, 0x0A8, 0x128, 0x1A8, diff --git a/Resources/rom/077-0019 Apple IIe Diagnostic Card - English.rom b/Resources/rom/077-0019 Apple IIe Diagnostic Card - English.rom new file mode 100644 index 0000000000000000000000000000000000000000..c52c891016b12277b6f58847b2d0c90cfad8ca4e GIT binary patch literal 16384 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 QzyJO}{lgRgzuo`;Ke+1#wg3PC literal 0 HcmV?d00001 diff --git a/convert_disass.py b/convert_disass.py new file mode 100755 index 0000000..41e496e --- /dev/null +++ b/convert_disass.py @@ -0,0 +1,27 @@ +#!/usr/local/bin/python3 + +import re +import sys + +if __name__ == "__main__": +# print(f"Arguments count: {len(sys.argv)}") +# for i, arg in enumerate(sys.argv): +# print(f"Argument {i:>6}: {arg}") + + for filename in sys.argv[1:]: + print(f"Converting file: {filename}") + +# i = 20 + + with open(filename, 'r') as inf: + with open(filename + '.dis', 'w+') as outf: + for line in inf: + outf.write(re.sub('^\d*\t\d*\t', '', line)) + +# print('ORIG:', line) +# print('LINE:', re.sub('^\d*\t\d*\t', '', line)) +# +# i += 1 +# if i > 200: +# break + diff --git a/src/cpu/6502.c b/src/cpu/6502.c index 5de721d..144459b 100644 --- a/src/cpu/6502.c +++ b/src/cpu/6502.c @@ -117,7 +117,6 @@ m6502_t m6502 = { }; -disassembly_t disassembly; #include "../util/disassembler.h" #include "../dev/mem/mmio.h" @@ -641,17 +640,17 @@ void m6502_Run() { spkr_update_disk_sfx(); } -void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, const uint16_t addr ) { +void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, const uint16_t addr, const uint16_t size ) { char fullPath[256]; strcpy( fullPath, bundlePath ); strcat( fullPath, "/"); strcat( fullPath, filename ); - + FILE * f = fopen(fullPath, "rb"); if (f == NULL) { - perror("Failed to read ROM: "); + perror("Failed to read ROM image: "); return; } @@ -659,7 +658,12 @@ void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, co uint16_t flen = ftell(f); fseek(f, 0L, SEEK_SET); - fread( rom + addr, 1, flen, f); + if ( size && (size > flen) ) { + printf("ROM image is too small (size:0x%04X flen:0x04X)\n", size, flen); + return; + } + + fread( rom + addr, 1, size, f); fclose(f); } @@ -668,7 +672,7 @@ void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, co size_t getFileSize ( const char * fullPath ) { FILE * f = fopen(fullPath, "rb"); if (f == NULL) { - perror("Failed to read ROM: "); + perror("Failed to get filesize for ROM image: "); return 0; } @@ -689,20 +693,27 @@ void rom_loadFile( const char * bundlePath, const char * filename ) { strcat( fullPath, "/"); strcat( fullPath, filename ); + printf("Loading ROM: %s\n", filename); + size_t flen = getFileSize(fullPath); if ( flen == 0 ) { return; // there was an error } + else if ( flen == 32 * KB ) { + read_rom( bundlePath, filename, INT_64K_ROM + 0x8000, 0, 32 * KB); + memcpy(Apple2_64K_MEM + 0xC000, INT_64K_ROM + 0xC000, 16 * KB); // activate the upper ROM + } + else if ( flen == 16 * KB ) { - read_rom( bundlePath, filename, Apple2_64K_ROM + 0xC000, 0); - memcpy(Apple2_64K_MEM + 0xC000, Apple2_64K_ROM + 0xC000, 16 * KB); + read_rom( bundlePath, filename, INT_64K_ROM + 0xC000, 0, 16 * KB); + memcpy(Apple2_64K_MEM + 0xC000, INT_64K_ROM + 0xC000, 16 * KB); } else if ( flen == 12 * KB ) { - read_rom( bundlePath, filename, Apple2_64K_ROM + 0xD000, 0x1000); - memcpy(Apple2_64K_MEM + 0xD000, Apple2_64K_ROM + 0xD000, 12 * KB); + read_rom( bundlePath, filename, INT_64K_ROM + 0xD000, 0x1000, 12 * KB); + memcpy(Apple2_64K_MEM + 0xD000, INT_64K_ROM + 0xD000, 12 * KB); } } @@ -750,7 +761,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { #ifdef FUNCTIONTEST - read_rom( bundlePath, "6502_functional_test.bin", Apple2_64K_RAM, 0); + read_rom( bundlePath, "6502_functional_test.bin", Apple2_64K_RAM, 0, 0); memcpy(Apple2_64K_MEM, Apple2_64K_RAM, 65536); m6502.PC = 0x400; @@ -760,8 +771,8 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { rom_loadFile(bundlePath, romFileName); // Disk ][ ROM in Slot 6 - read_rom( bundlePath, "DISK_II_C600.ROM", Apple2_64K_ROM, 0xC600); - memcpy(Apple2_64K_MEM + 0xC600, Apple2_64K_ROM + 0xC600, 0x100); + read_rom( bundlePath, "DISK_II_C600.ROM", EXP_64K_ROM, 0xC600, 0x100); + memcpy(Apple2_64K_MEM + 0xC600, EXP_64K_ROM + 0xC600, 0x100); m6502.A = m6502.X = m6502.Y = 0xFF; // reset vector diff --git a/src/cpu/6502.h b/src/cpu/6502.h index 5fe0fe3..a40b220 100644 --- a/src/cpu/6502.h +++ b/src/cpu/6502.h @@ -124,7 +124,8 @@ typedef struct m6502_s { uint64_t clktime; // 14: uint64_t clklast; // 22: uint32_t clkfrm; // 30: - + + uint64_t clk_wrenable; // CPU clock when WRITE RAM is triggered debugLevel_t dbgLevel; // 34: 0: No Debug, 1: Disassembly Only, 2: Run till BRK, 3: StepByStep @@ -137,17 +138,6 @@ typedef struct m6502_s { //#pragma pack() -typedef struct disassembly_s { - uint64_t clk; // clock time - char addr[5]; // 4 digits + \0 - char opcode[4 * 3 + 1]; // max 4 bytes * (2 digits + 1 space) + \0 - char * pOpcode; // pointer for opcode string builder - char inst[6 + 1]; // 3 char (unknown instr? -- give it 6 chars) + \0 - char oper[14 + 2 + 1 + 1 + 1]; // 4 digits + 2 brackets + 1 comma + 1 index + \0 - char comment[256]; // to be able to add some comments -} disassembly_t; - - // Memory Config typedef struct MEMcfg_s { unsigned RAM_16K : 1; diff --git a/src/dev/audio/speaker.c b/src/dev/audio/speaker.c index 31e619a..c1f0200 100644 --- a/src/dev/audio/speaker.c +++ b/src/dev/audio/speaker.c @@ -675,13 +675,7 @@ void spkr_update() { memset(spkr_samples + size, 0, spkr_buf_size * sizeof(spkr_sample_t)); -// if ( spkr_sample_idx >= size ) { -// spkr_sample_idx -= size; -// } -// else { - spkr_sample_idx = 0; -// } - + spkr_sample_idx = 0; spkr_sample_last_idx = 0; } @@ -801,6 +795,7 @@ void spkr_play_disk_motor() { } } + void spkr_stop_disk_motor( int time ) { if ( ( disk_sfx_enabled ) && ( clk_6502_per_frm <= FRAME(iicplus_MHz_6502) ) ) { spkr_play_disk_motor_time = time; @@ -832,6 +827,7 @@ void spkr_stopAll() { } } + void update_disk_sfx( unsigned * time, ALuint src ) { if ( *time ) { if ( --*time == 0 ) { @@ -840,6 +836,7 @@ void update_disk_sfx( unsigned * time, ALuint src ) { } } + void spkr_update_disk_sfx() { // is user speeds up the machine, disk sfx needs to be stopped if ( ( ! disk_sfx_enabled ) || ( clk_6502_per_frm > FRAME(iicplus_MHz_6502) ) ) { diff --git a/src/dev/disk/woz.c b/src/dev/disk/woz.c index 168ca11..b8896a1 100644 --- a/src/dev/disk/woz.c +++ b/src/dev/disk/woz.c @@ -39,6 +39,7 @@ unsigned trackOffset = 0; unsigned bitOffset = 0; uint64_t clkelpased; +int extraForward = 6; // we search for 7 bit high a bit further to speed up disk read... char woz_filename[MAXFILENAME]; woz_flags_t woz_flags = {0,0,0,0}; @@ -330,10 +331,13 @@ uint8_t woz_read() { uint16_t usedBytes = (*woz_trks)[track].bytes_used < WOZ1_TRACK_BYTE_COUNT ? (*woz_trks)[track].bytes_used : WOZ1_TRACK_BYTE_COUNT; if ( usedBytes ) { - static const int extraForward = 4; // we search for 7 bit high a bit further to speed up disk read... +// static const int extraForward = 4; // we search for 7 bit high a bit further to speed up disk read... uint64_t bitForward = (clkelpased >> 2) + extraForward; + if ( bitForward > 100000000 ) { + bitForward = 4; + } - // Simulate idle spinning until s close point to the actual turn position + // Simulate idle spinning until a close point to the actual turn position while ( bitForward-- ) { if ( ++bitOffset > 7 ) { bitOffset = 0; @@ -355,7 +359,7 @@ uint8_t woz_read() { WOZread.latch = 0; // but we do not want to miss that latch valid nibble... // in other words synchronization is needed because of imperfect cycle calculation - if ( bitForward < 8 ) { + if ( bitForward < 18 ) { return latch; } } diff --git a/src/dev/disk/woz.h b/src/dev/disk/woz.h index e72a7c9..3df8701 100644 --- a/src/dev/disk/woz.h +++ b/src/dev/disk/woz.h @@ -195,6 +195,7 @@ extern woz_flags_t woz_flags; extern size_t woz_file_size; extern uint8_t * woz_file_buffer; +extern int extraForward; //extern woz_header_t woz_header; //extern woz_chunk_header_t woz_chunk_header; diff --git a/src/dev/mem/mmio.c b/src/dev/mem/mmio.c index f56a098..9795f11 100644 --- a/src/dev/mem/mmio.c +++ b/src/dev/mem/mmio.c @@ -34,11 +34,13 @@ videoMode_t videoMode = { 1 }; // 40 col text, page 1 +uint8_t INT_64K_ROM[ 64 * KB ] = {0}; // ROM C0, C8, D0, D8, E0, E8, F0, F8 +uint8_t AUX_64K_ROM[ 64 * KB ] = {0}; // ROM C0, C8, D0, D8, E0, E8, F0, F8 +uint8_t EXP_64K_ROM[ 64 * KB ] = {0}; // ROM C0, C8, D0, D8, E0, E8, F0, F8 + uint8_t Apple2_Dummy_Page[ 1 * PG ]; // Dummy Page to discard data uint8_t Apple2_Dummy_RAM[ 64 * KB ]; // Dummy RAM to discard data -uint8_t Apple2_64K_ROM[ 64 * KB ] = {0}; // ROM C0, C8, D0, D8, E0, E8, F0, F8 - uint8_t Apple2_64K_AUX[ 64 * KB ] = {0}; // 64K Expansion Memory uint8_t Apple2_64K_RAM[ 64 * KB ] = {0}; // Main Memory uint8_t Apple2_64K_MEM[ 64 * KB ] = {0}; // Shadow Copy of Memory (or current memory content) @@ -79,13 +81,62 @@ const uint8_t * const shadowLowMEM = Apple2_64K_MEM + 0x200; const uint8_t * currentLowMEM = Apple2_64K_RAM + 0x200; +/// No writing (Readonly), and mark it as NO need to commit from Shadow RAM +INLINE void set_MEM_readonly() { + printf("NOWR_AUX\n"); + + MEMcfg.WR_RAM = 0; + WRD0MEM = Apple2_Dummy_RAM; // for Discarding any writes to $D000 - $DFFF - BANK X + WRHIMEM = Apple2_Dummy_RAM; // for Discarding any writes to $E000 - $FFFF +} + + +/// Make AUX RAM writeable -- This is when AUX is also readable, othwrwise use set_AUX_write... +INLINE void set_MEM_write() { + // two consecutive read or write needs for write enable + // Note: if it is already writeable and was previously a ROM read + RAM write, then we also need to bound AUX to MEM + if ( ( (m6502.clktime + m6502.clkfrm - m6502.clk_wrenable) < 8 ) || (MEMcfg.WR_RAM) ) { + printf("WR_AUX\n"); + + // will write to Shadow RAM, and mark it as need to commit from Shadow RAM + MEMcfg.WR_RAM = 1; + WRD0MEM = Apple2_64K_MEM; // for Write $D000 - $DFFF (shadow memory) - BANK X + WRHIMEM = Apple2_64K_MEM; // for Write $E000 - $FFFF (shadow memory) + } + + m6502.clk_wrenable = m6502.clktime + m6502.clkfrm; +} + + +/// Make AUX RAM writeable -- This is when ROM is readable, othwrwise use set_MEM_write... +INLINE void set_AUX_write() { + // will write directly to Auxiliary RAM, and mark it as NO need to commit from Shadow RAM + // Note: if it is already writeable and was previously a RAM read + RAM write, then we also need to bound AUX to MEM + if ( ( (m6502.clktime + m6502.clkfrm - m6502.clk_wrenable) < 8 ) || (MEMcfg.WR_RAM) ) { + printf("WR_AUX\n"); + + MEMcfg.WR_RAM = 1; + if ( MEMcfg.RAM_BANK_2 ) { + WRD0MEM = Apple2_64K_AUX; // for Write $D000 - $DFFF (shadow memory) - BANK 2 at 0xD000 + } + else { + WRD0MEM = Apple2_64K_AUX - 0x1000; // for Write $D000 - $DFFF (shadow memory) - BANK 1 at 0xC000 + } + WRHIMEM = Apple2_64K_AUX; // for Write $E000 - $FFFF (shadow memory) + } + + m6502.clk_wrenable = m6502.clktime + m6502.clkfrm; +} + + INLINE void io_RAM_EXP( uint16_t addr ) { if ( MEMcfg.RAM_16K || MEMcfg.RAM_128K ) { - uint8_t * RAM_BANK = Apple2_64K_AUX + 0xC000; + // TODO: store 0xD000 BANK 1 at 0xC000 -- might be a problem emulating 64k/128k Saturn cards +// uint8_t * RAM_BANK = Apple2_64K_AUX + 0xC000; // save the content of Shadow Memory in needed - if ( MEMcfg.WR_RAM ) { + if ( MEMcfg.WR_RAM && MEMcfg.RD_INT_RAM ) { // printf("Saving RAM Bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank); memcpy(current_RAM_bank, Apple2_64K_MEM + 0xD000, 0x1000); memcpy(Apple2_64K_AUX + 0xE000, Apple2_64K_MEM + 0xE000, 0x2000); @@ -103,17 +154,17 @@ INLINE void io_RAM_EXP( uint16_t addr ) { case (uint8_t)io_MEM_RDROM_NOWR_2_: case (uint8_t)io_MEM_RDRAM_WRAM_2_: - // printf("RAM_BANK_2\n"); + printf("RAM_BANK_2\n"); MEMcfg.RAM_BANK_2 = 1; - RAM_BANK = Apple2_64K_AUX + 0xD000; + current_RAM_bank = Apple2_64K_AUX + 0xD000; break; default: - // printf("RAM_BANK_1\n"); + printf("RAM_BANK_1\n"); MEMcfg.RAM_BANK_2 = 0; - RAM_BANK = Apple2_64K_AUX + 0xC000; + current_RAM_bank = Apple2_64K_AUX + 0xC000; break; } @@ -129,24 +180,24 @@ INLINE void io_RAM_EXP( uint16_t addr ) { case (uint8_t)io_MEM_RDRAM_NOWR_1_: case (uint8_t)io_MEM_RDRAM_WRAM_1_: - // printf("RD_RAM\n"); + printf("RD_RAM\n"); MEMcfg.RD_INT_RAM = 1; // load the content of Aux Memory - memcpy(Apple2_64K_MEM + 0xD000, RAM_BANK, 0x1000); + memcpy(Apple2_64K_MEM + 0xD000, current_RAM_bank, 0x1000); memcpy(Apple2_64K_MEM + 0xE000, Apple2_64K_AUX + 0xE000, 0x2000); // set the RAM extension to read on the upper memory area break; default: - // printf("RD_ROM\n"); + printf("RD_ROM\n"); MEMcfg.RD_INT_RAM = 0; // load the content of ROM Memory - memcpy(Apple2_64K_MEM + 0xD000, Apple2_64K_ROM + 0xD000, 0x3000); + memcpy(Apple2_64K_MEM + 0xD000, INT_64K_ROM + 0xD000, 0x3000); // set the ROM to read on the upper memory area break; @@ -160,17 +211,10 @@ INLINE void io_RAM_EXP( uint16_t addr ) { case (uint8_t)io_MEM_RDROM_WRAM_2_: case (uint8_t)io_MEM_RDROM_WRAM_1_: - // printf("RD_ROM + WR_AUX\n"); + printf("RD_ROM + WR_AUX\n"); + + set_AUX_write(); - // will write directly to Auxiliary RAM, and mark it as NO need to commit from Shadow RAM - MEMcfg.WR_RAM = 0; - if ( MEMcfg.RAM_BANK_2 ) { - WRD0MEM = Apple2_64K_AUX; // for Write $D000 - $DFFF (shadow memory) - BANK 2 - } - else { - WRD0MEM = Apple2_64K_AUX - 0x1000; // for Write $D000 - $DFFF (shadow memory) - BANK 1 - } - WRHIMEM = Apple2_64K_AUX; // for Write $E000 - $FFFF (shadow memory) break; case (uint8_t)io_MEM_RDRAM_WRAM_2: @@ -179,25 +223,21 @@ INLINE void io_RAM_EXP( uint16_t addr ) { case (uint8_t)io_MEM_RDRAM_WRAM_2_: case (uint8_t)io_MEM_RDRAM_WRAM_1_: - // printf("RD_RAM + WR_RAM\n"); + printf("RD_RAM + WR_RAM\n"); - // will write to Shadow RAM, and mark it as need to commit from Shadow RAM - MEMcfg.WR_RAM = 1; - WRD0MEM = Apple2_64K_MEM; // for Write $D000 - $DFFF (shadow memory) - BANK X - WRHIMEM = Apple2_64K_MEM; // for Write $E000 - $FFFF (shadow memory) + set_MEM_write(); + break; default: - // printf("RD_ROM + NO_WR\n"); - - // No writing (Readonly), and mark it as NO need to commit from Shadow RAM - MEMcfg.WR_RAM = 0; - WRD0MEM = Apple2_Dummy_RAM; // for Discarding any writes to $D000 - $DFFF - BANK X - WRHIMEM = Apple2_Dummy_RAM; // for Discarding any writes to $E000 - $FFFF + printf("RD_ROM + NO_WR\n"); + + set_MEM_readonly(); + break; } - current_RAM_bank = RAM_BANK; +// current_RAM_bank = RAM_BANK; // printf("Set current_RAM_bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank); @@ -208,7 +248,15 @@ INLINE void io_RAM_EXP( uint16_t addr ) { INLINE uint8_t ioRead( uint16_t addr ) { // if (outdev) fprintf(outdev, "ioRead:%04X\n", addr); - // printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC); + +// switch(addr) { +// case io_KBD: +// case io_KBDSTRB: +// case io_SPKR: +// break; +// default: +// printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC); +// } unsigned int IOframe = m6502.clkfrm - lastIO; lastIO = m6502.clkfrm; @@ -229,6 +277,25 @@ INLINE uint8_t ioRead( uint16_t addr ) { } switch ( (uint8_t)addr ) { +// case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + printf("RD TAPEIO: %04X\n", addr); + return 0; + case (uint8_t)io_KBD: return Apple2_64K_RAM[io_KBD]; @@ -282,7 +349,7 @@ INLINE uint8_t ioRead( uint16_t addr ) { case (uint8_t)io_RDALTZP: return MEMcfg.ALT_ZP << 7; - + case (uint8_t)io_RDC3ROM: return MEMcfg.slot_C3_ROM << 7; @@ -469,7 +536,36 @@ INLINE uint8_t ioRead( uint16_t addr ) { INLINE void ioWrite( uint16_t addr, uint8_t val ) { // if (outdev) fprintf(outdev, "ioWrite:%04X (A:%02X)\n", addr, m6502.A); +// switch(addr) { +// case io_KBD: +// case io_KBDSTRB: +// case io_SPKR: +// break; +// default: +// printf("ioWrite:%04X (PC:%04X, val:%02X)\n", addr, m6502.PC, val); +// } + + switch ( (uint8_t)addr ) { +// case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + printf("WR TAPEIO: %04X\n", addr); + return; + case (uint8_t)io_KBDSTRB: Apple2_64K_RAM[io_KBD] &= 0x7F; break; @@ -765,7 +861,7 @@ INLINE uint8_t memread( uint16_t addr ) { INLINE void memwrite8_low( uint16_t addr, uint8_t data ) { WRLOMEM[addr] = data; } -INLINE void memwrite8_bank2( uint16_t addr, uint8_t data ) { +INLINE void memwrite8_bank( uint16_t addr, uint8_t data ) { WRD0MEM[addr] = data; } INLINE void memwrite8_high( uint16_t addr, uint8_t data ) { @@ -782,7 +878,7 @@ INLINE void memwrite( uint16_t addr, uint8_t data ) { } else if (addr < 0xE000) { // Aux RAM Bank 1 or 2 - memwrite8_bank2(addr, data); + memwrite8_bank(addr, data); } else { // ROM (dummy memory to screape writings) or Aux RAM @@ -1057,11 +1153,11 @@ void C3MemorySelect( MEMcfg_t newMEMcfg ) { if ( newMEMcfg.slot_C3_ROM ) { // load internal ROM to memory - memcpy(Apple2_64K_MEM + 0xC300, Apple2_64K_RAM + 0xC300, 0x100); + memcpy(Apple2_64K_MEM + 0xC300, INT_64K_ROM + 0xC300, 0x100); } else { // load peripheral ROM to memory - memcpy(Apple2_64K_MEM + 0xC300, Apple2_64K_ROM + 0xC300, 0x100); + memcpy(Apple2_64K_MEM + 0xC300, EXP_64K_ROM + 0xC300, 0x100); } MEMcfg = newMEMcfg; @@ -1072,11 +1168,11 @@ void CxMemorySelect( MEMcfg_t newMEMcfg ) { if ( newMEMcfg.int_Cx_ROM ) { // load internal ROM to memory - memcpy(Apple2_64K_MEM + 0xC100, Apple2_64K_ROM + 0xC100, 0xF00); + memcpy(Apple2_64K_MEM + 0xC100, INT_64K_ROM + 0xC100, 0xF00); } else { // load peripheral ROM to memory - memcpy(Apple2_64K_MEM + 0xC100, Apple2_64K_RAM + 0xC100, 0xF00); + memcpy(Apple2_64K_MEM + 0xC100, EXP_64K_ROM + 0xC100, 0xF00); // memcpy(Apple2_64K_MEM + 0xC600, Apple2_64K_RAM + 0xC600, 0x100); } @@ -1098,7 +1194,7 @@ void resetMemory() { CxMemorySelect(MEMcfg); // initializing disk controller - memcpy(Apple2_64K_MEM + 0xC600, Apple2_64K_ROM + 0xC600, 0x100); + memcpy(Apple2_64K_MEM + 0xC600, EXP_64K_ROM + 0xC600, 0x100); MEMcfg = newMEMcfg; diff --git a/src/dev/mem/mmio.h b/src/dev/mem/mmio.h index 957a7b2..7595b57 100644 --- a/src/dev/mem/mmio.h +++ b/src/dev/mem/mmio.h @@ -50,7 +50,8 @@ extern videoMode_t videoMode; // 40 col text, page 1 extern uint8_t Apple2_Dummy_Page[ 1 * PG ]; // Dummy Page to discard data extern uint8_t Apple2_Dummy_RAM[ 64 * KB ]; // Dummy RAM to discard data -extern uint8_t Apple2_64K_ROM[ 64 * KB ]; // ROM C0, C8, D0, D8, E0, E8, F0, F8 +extern uint8_t INT_64K_ROM[ 64 * KB ]; // ROM C0, C8, D0, D8, E0, E8, F0, F8 +extern uint8_t EXP_64K_ROM[ 64 * KB ]; // ROM C0, C8, D0, D8, E0, E8, F0, F8 extern uint8_t Apple2_64K_AUX[ 64 * KB ]; // 64K Expansion Memory extern uint8_t Apple2_64K_RAM[ 64 * KB ]; // Main Memory @@ -390,7 +391,7 @@ INLINE uint16_t memread16_low( uint16_t addr ); INLINE uint16_t memread16( uint16_t addr ); INLINE uint8_t memread( uint16_t addr ); INLINE void memwrite8_low( uint16_t addr, uint8_t data ); -INLINE void memwrite8_bank2( uint16_t addr, uint8_t data ); +INLINE void memwrite8_bank( uint16_t addr, uint8_t data ); INLINE void memwrite8_high( uint16_t addr, uint8_t data ); INLINE void memwrite( uint16_t addr, uint8_t data ); INLINE uint8_t fetch(void); diff --git a/src/util/disassembler.c b/src/util/disassembler.c new file mode 100644 index 0000000..377d001 --- /dev/null +++ b/src/util/disassembler.c @@ -0,0 +1,107 @@ +// +// disassembler.c +// A2Mac +// +// Created by Tamas Rudnai on 3/13/22. +// Copyright © 2022 GameAlloy. All rights reserved. +// + +#include +#include "disassembler.h" + +disassembly_t disassembly; +unsigned long long discnt = 0; + +INLINE flags_t getFlags2() { + flags_t f = { + m6502.C != 0, // Carry Flag + m6502.Z != 0, // Zero Flag + m6502.I != 0, // Interrupt Flag + m6502.D != 0, // Decimal Flag + m6502.B != 0, // B Flag + m6502.res != 0, // reserved -- should be always 1 + m6502.V != 0, // Overflow Flag ??? + m6502.N != 0, // Negative Flag + }; + + return f; +} + + +void printDisassembly( FILE * f ) { + if ( m6502.dbgLevel.trace && f ) { + // fprintf( f, "%s: %-14s%-6s%-14s%-16s A:%02X X:%02X Y:%02X S:%02X P:%02X (%c%c%c%c%c%c%c%c)\n", + // disassembly.addr, + // disassembly.opcode, + // disassembly.inst, + // disassembly.oper, + // disassembly.comment, + // m6502.A, + // m6502.X, + // m6502.Y, + // m6502.SP, + // m6502.SR, + // m6502.N ? 'N' : 'n', + // m6502.V ? 'V' : 'v', + // m6502.res ? 'R' : 'r', + // m6502.B ? 'B' : 'b', + // m6502.D ? 'D' : 'd', + // m6502.I ? 'I' : 'i', + // m6502.Z ? 'Z' : 'z', + // m6502.C ? 'C' : 'c' + // ); + + // fprintf( f, "%llu\t%llu %s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t;\t%s\n", // Virtual ][ style + // ++discnt, + // m6502.clktime + clkfrm, + // disassembly.addr, + // disassembly.opcode, + // disassembly.inst, + // disassembly.oper, + // m6502.A, + // m6502.X, + // m6502.Y, + // 0, + // //getFlags2(), + // m6502.SP, + // disassembly.comment + // ); + + // Virtual ][ Style + fprintf( f, "%llu\t%llu\t%s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\n", // Virtual ][ style + ++discnt, + disassembly.clk, + disassembly.addr, + disassembly.opcode, + disassembly.inst, + disassembly.oper, + m6502.A, + m6502.X, + m6502.Y, + getFlags2().SR, + m6502.SP + ); + +// static char line[256]; +// // Steve ][ Style +// snprintf( line, sizeof(line), "%10llu %10llu %s: %-11s%-4s%s", // Steve ][ style +// ++discnt, +// disassembly.clk, +// disassembly.addr, +// disassembly.opcode, +// disassembly.inst, +// disassembly.oper +// ); +// +// fprintf( f, "%-55s; 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", // Steve ][ style +// line, +// m6502.A, +// m6502.X, +// m6502.Y, +// getFlags2().SR, +// m6502.SP +// ); + + } +} + diff --git a/src/util/disassembler.h b/src/util/disassembler.h index d187280..14c3465 100644 --- a/src/util/disassembler.h +++ b/src/util/disassembler.h @@ -24,12 +24,29 @@ #ifndef disassembler_h #define disassembler_h -#undef DISASSEMBLER +#include "6502.h" +#include "common.h" + + +typedef struct disassembly_s { + uint64_t clk; // clock time + char addr[5]; // 4 digits + \0 + char opcode[4 * 3 + 1]; // max 4 bytes * (2 digits + 1 space) + \0 + char * pOpcode; // pointer for opcode string builder + char inst[6 + 1]; // 3 char (unknown instr? -- give it 6 chars) + \0 + char oper[14 + 2 + 1 + 1 + 1]; // 4 digits + 2 brackets + 1 comma + 1 index + \0 + char comment[256]; // to be able to add some comments +} disassembly_t; + +extern disassembly_t disassembly; + +//#define DISASSEMBLER +//#undef DISASSEMBLER #ifdef DISASSEMBLER //extern unsigned long long int clktime; -unsigned long long discnt = 0; +extern unsigned long long discnt; #define disHexB( to, b ) \ if ( m6502.dbgLevel.trace ) { \ @@ -69,100 +86,7 @@ unsigned long long discnt = 0; } \ } -INLINE flags_t getFlags2() { - flags_t f = { - m6502.C != 0, // Carry Flag - m6502.Z != 0, // Zero Flag - m6502.I != 0, // Interrupt Flag - m6502.D != 0, // Decimal Flag - m6502.B != 0, // B Flag - m6502.res != 0, // reserved -- should be always 1 - m6502.V != 0, // Overflow Flag ??? - m6502.N != 0, // Negative Flag - }; - - return f; -} - - -INLINE void printDisassembly( FILE * f ) { - if ( m6502.dbgLevel.trace && f ) { -// fprintf( f, "%s: %-14s%-6s%-14s%-16s A:%02X X:%02X Y:%02X S:%02X P:%02X (%c%c%c%c%c%c%c%c)\n", -// disassembly.addr, -// disassembly.opcode, -// disassembly.inst, -// disassembly.oper, -// disassembly.comment, -// m6502.A, -// m6502.X, -// m6502.Y, -// m6502.SP, -// m6502.SR, -// m6502.N ? 'N' : 'n', -// m6502.V ? 'V' : 'v', -// m6502.res ? 'R' : 'r', -// m6502.B ? 'B' : 'b', -// m6502.D ? 'D' : 'd', -// m6502.I ? 'I' : 'i', -// m6502.Z ? 'Z' : 'z', -// m6502.C ? 'C' : 'c' -// ); - -// fprintf( f, "%llu\t%llu %s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t;\t%s\n", // Virtual ][ style -// ++discnt, -// m6502.clktime + clkfrm, -// disassembly.addr, -// disassembly.opcode, -// disassembly.inst, -// disassembly.oper, -// m6502.A, -// m6502.X, -// m6502.Y, -// 0, -// //getFlags2(), -// m6502.SP, -// disassembly.comment -// ); - -// // Virtual ][ Style -// fprintf( f, "%llu\t%llu\t%s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\n", // Virtual ][ style -// ++discnt, -// disassembly.clk, -// disassembly.addr, -// disassembly.opcode, -// disassembly.inst, -// disassembly.oper, -// m6502.A, -// m6502.X, -// m6502.Y, -// getFlags2().SR, -// m6502.SP -// ); -// -// } - - static char line[256]; - // Steve ][ Style - snprintf( line, sizeof(line), "%10llu %10llu %s: %-11s%-4s%s", // Steve ][ style - ++discnt, - disassembly.clk, - disassembly.addr, - disassembly.opcode, - disassembly.inst, - disassembly.oper - ); - - fprintf( f, "%-55s; 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", // Steve ][ style - line, - m6502.A, - m6502.X, - m6502.Y, - getFlags2().SR, - m6502.SP - ); - - } -} +extern void printDisassembly( FILE * f ); #else // DISASSEMBLER