From fc5589a944e015996d402df0456d45e67af17859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20A=2E=20A=CC=81lvarez?= Date: Sun, 1 May 2016 19:05:36 +0200 Subject: [PATCH] initial implementation --- .clang-format | 58 + Mini vMac.xcodeproj/project.pbxproj | 143 ++- Mini vMac/AppDelegate.h | 1 + Mini vMac/AppDelegate.m | 31 +- Mini vMac/Base.lproj/Main.storyboard | 20 +- Mini vMac/Info.plist | 8 +- Mini vMac/MYOSGLUE.m | 1709 ++++++++++++++++++++++++++ Mini vMac/ScreenView.h | 16 + Mini vMac/ScreenView.m | 57 + Mini vMac/ViewController.m | 10 +- Mini vMac/mnvm_cfg/CNFGGLOB.h | 92 ++ Mini vMac/mnvm_cfg/CNFGRAPI.h | 35 + Mini vMac/mnvm_cfg/EMCONFIG.h | 172 +++ Mini vMac/mnvm_core/COMOSGLU.h | 1 + Mini vMac/mnvm_core/DATE2SEC.h | 1 + Mini vMac/mnvm_core/ENDIANAC.h | 1 + Mini vMac/mnvm_core/GLOBGLUE.c | 1 + Mini vMac/mnvm_core/GLOBGLUE.h | 1 + Mini vMac/mnvm_core/INTLCHAR.h | 1 + Mini vMac/mnvm_core/IWMEMDEV.c | 1 + Mini vMac/mnvm_core/IWMEMDEV.h | 1 + Mini vMac/mnvm_core/KBRDEMDV.c | 1 + Mini vMac/mnvm_core/KBRDEMDV.h | 1 + Mini vMac/mnvm_core/M68KITAB.c | 1 + Mini vMac/mnvm_core/M68KITAB.h | 1 + Mini vMac/mnvm_core/MINEM68K.c | 1 + Mini vMac/mnvm_core/MINEM68K.h | 1 + Mini vMac/mnvm_core/MOUSEMDV.c | 1 + Mini vMac/mnvm_core/MOUSEMDV.h | 1 + Mini vMac/mnvm_core/MYOSGLUE.h | 1 + Mini vMac/mnvm_core/PROGMAIN.c | 1 + Mini vMac/mnvm_core/PROGMAIN.h | 1 + Mini vMac/mnvm_core/ROMEMDEV.c | 1 + Mini vMac/mnvm_core/ROMEMDEV.h | 1 + Mini vMac/mnvm_core/RTCEMDEV.c | 1 + Mini vMac/mnvm_core/RTCEMDEV.h | 1 + Mini vMac/mnvm_core/SCCEMDEV.c | 1 + Mini vMac/mnvm_core/SCCEMDEV.h | 1 + Mini vMac/mnvm_core/SCRNEMDV.c | 1 + Mini vMac/mnvm_core/SCRNEMDV.h | 1 + Mini vMac/mnvm_core/SCRNMAPR.h | 1 + Mini vMac/mnvm_core/SCSIEMDV.c | 1 + Mini vMac/mnvm_core/SCSIEMDV.h | 1 + Mini vMac/mnvm_core/SNDEMDEV.c | 1 + Mini vMac/mnvm_core/SNDEMDEV.h | 1 + Mini vMac/mnvm_core/SONYEMDV.c | 1 + Mini vMac/mnvm_core/SONYEMDV.h | 1 + Mini vMac/mnvm_core/STRCONST.h | 1 + Mini vMac/mnvm_core/SYSDEPNS.h | 1 + Mini vMac/mnvm_core/VIAEMDEV.c | 1 + Mini vMac/mnvm_core/VIAEMDEV.h | 1 + 51 files changed, 2361 insertions(+), 29 deletions(-) create mode 100644 .clang-format create mode 100644 Mini vMac/MYOSGLUE.m create mode 100644 Mini vMac/ScreenView.h create mode 100644 Mini vMac/ScreenView.m create mode 100644 Mini vMac/mnvm_cfg/CNFGGLOB.h create mode 100644 Mini vMac/mnvm_cfg/CNFGRAPI.h create mode 100644 Mini vMac/mnvm_cfg/EMCONFIG.h create mode 100755 Mini vMac/mnvm_core/COMOSGLU.h create mode 100755 Mini vMac/mnvm_core/DATE2SEC.h create mode 100755 Mini vMac/mnvm_core/ENDIANAC.h create mode 100755 Mini vMac/mnvm_core/GLOBGLUE.c create mode 100755 Mini vMac/mnvm_core/GLOBGLUE.h create mode 100755 Mini vMac/mnvm_core/INTLCHAR.h create mode 100755 Mini vMac/mnvm_core/IWMEMDEV.c create mode 100755 Mini vMac/mnvm_core/IWMEMDEV.h create mode 100755 Mini vMac/mnvm_core/KBRDEMDV.c create mode 100755 Mini vMac/mnvm_core/KBRDEMDV.h create mode 100755 Mini vMac/mnvm_core/M68KITAB.c create mode 100755 Mini vMac/mnvm_core/M68KITAB.h create mode 100755 Mini vMac/mnvm_core/MINEM68K.c create mode 100755 Mini vMac/mnvm_core/MINEM68K.h create mode 100755 Mini vMac/mnvm_core/MOUSEMDV.c create mode 100755 Mini vMac/mnvm_core/MOUSEMDV.h create mode 100755 Mini vMac/mnvm_core/MYOSGLUE.h create mode 100755 Mini vMac/mnvm_core/PROGMAIN.c create mode 100755 Mini vMac/mnvm_core/PROGMAIN.h create mode 100755 Mini vMac/mnvm_core/ROMEMDEV.c create mode 100755 Mini vMac/mnvm_core/ROMEMDEV.h create mode 100755 Mini vMac/mnvm_core/RTCEMDEV.c create mode 100755 Mini vMac/mnvm_core/RTCEMDEV.h create mode 100755 Mini vMac/mnvm_core/SCCEMDEV.c create mode 100755 Mini vMac/mnvm_core/SCCEMDEV.h create mode 100755 Mini vMac/mnvm_core/SCRNEMDV.c create mode 100755 Mini vMac/mnvm_core/SCRNEMDV.h create mode 100755 Mini vMac/mnvm_core/SCRNMAPR.h create mode 100755 Mini vMac/mnvm_core/SCSIEMDV.c create mode 100755 Mini vMac/mnvm_core/SCSIEMDV.h create mode 100755 Mini vMac/mnvm_core/SNDEMDEV.c create mode 100755 Mini vMac/mnvm_core/SNDEMDEV.h create mode 100755 Mini vMac/mnvm_core/SONYEMDV.c create mode 100755 Mini vMac/mnvm_core/SONYEMDV.h create mode 100755 Mini vMac/mnvm_core/STRCONST.h create mode 100755 Mini vMac/mnvm_core/SYSDEPNS.h create mode 100755 Mini vMac/mnvm_core/VIAEMDEV.c create mode 100755 Mini vMac/mnvm_core/VIAEMDEV.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..5e710d7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,58 @@ +--- +Language: Cpp +AccessModifierOffset: -1 +ConstructorInitializerIndentWidth: 4 +AlignEscapedNewlinesLeft: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AlwaysBreakTemplateDeclarations: true +AlwaysBreakBeforeMultilineStrings: true +BreakBeforeBinaryOperators: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BinPackParameters: false +ColumnLimit: 0 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +IndentWrappedFunctionNames: false +IndentFunctionDeclarationAfterType: false +MaxEmptyLinesToKeep: 1 +KeepEmptyLinesAtTheStartOfBlocks: false +NamespaceIndentation: None +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +ObjCBlockIndentWidth: 4 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakString: 1000 +PenaltyBreakFirstLessLess: 120 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +SpacesBeforeTrailingComments: 2 +Cpp11BracedListStyle: true +Standard: Cpp03 +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +BreakBeforeBraces: Attach +SpacesInParentheses: false +SpacesInAngles: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpaceBeforeAssignmentOperators: true +ContinuationIndentWidth: 4 +CommentPragmas: '^ IWYU pragma:' +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +SpaceBeforeParens: ControlStatements +DisableFormat: false +SortIncludes: false +... + diff --git a/Mini vMac.xcodeproj/project.pbxproj b/Mini vMac.xcodeproj/project.pbxproj index fa21f0c..88d3f89 100644 --- a/Mini vMac.xcodeproj/project.pbxproj +++ b/Mini vMac.xcodeproj/project.pbxproj @@ -7,6 +7,23 @@ objects = { /* Begin PBXBuildFile section */ + 28CE8EB51CD4C3B200FE25A8 /* GLOBGLUE.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8E931CD4C3B200FE25A8 /* GLOBGLUE.c */; }; + 28CE8EB61CD4C3B200FE25A8 /* IWMEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8E961CD4C3B200FE25A8 /* IWMEMDEV.c */; }; + 28CE8EB71CD4C3B200FE25A8 /* KBRDEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8E981CD4C3B200FE25A8 /* KBRDEMDV.c */; }; + 28CE8EB81CD4C3B200FE25A8 /* M68KITAB.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8E9A1CD4C3B200FE25A8 /* M68KITAB.c */; }; + 28CE8EB91CD4C3B200FE25A8 /* MINEM68K.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8E9C1CD4C3B200FE25A8 /* MINEM68K.c */; }; + 28CE8EBA1CD4C3B200FE25A8 /* MOUSEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8E9E1CD4C3B200FE25A8 /* MOUSEMDV.c */; }; + 28CE8EBB1CD4C3B200FE25A8 /* PROGMAIN.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EA11CD4C3B200FE25A8 /* PROGMAIN.c */; }; + 28CE8EBC1CD4C3B200FE25A8 /* ROMEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EA31CD4C3B200FE25A8 /* ROMEMDEV.c */; }; + 28CE8EBD1CD4C3B200FE25A8 /* RTCEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EA51CD4C3B200FE25A8 /* RTCEMDEV.c */; }; + 28CE8EBE1CD4C3B200FE25A8 /* SCCEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EA71CD4C3B200FE25A8 /* SCCEMDEV.c */; }; + 28CE8EBF1CD4C3B200FE25A8 /* SCRNEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EA91CD4C3B200FE25A8 /* SCRNEMDV.c */; }; + 28CE8EC01CD4C3B200FE25A8 /* SCSIEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EAC1CD4C3B200FE25A8 /* SCSIEMDV.c */; }; + 28CE8EC11CD4C3B200FE25A8 /* SNDEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EAE1CD4C3B200FE25A8 /* SNDEMDEV.c */; }; + 28CE8EC21CD4C3B200FE25A8 /* SONYEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EB01CD4C3B200FE25A8 /* SONYEMDV.c */; }; + 28CE8EC31CD4C3B200FE25A8 /* VIAEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EB31CD4C3B200FE25A8 /* VIAEMDEV.c */; }; + 28CE8ECC1CD4CDC500FE25A8 /* MYOSGLUE.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */; }; 28F676C21CD15E0B00FC6FA6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F676C11CD15E0B00FC6FA6 /* main.m */; }; 28F676C51CD15E0B00FC6FA6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F676C41CD15E0B00FC6FA6 /* AppDelegate.m */; }; 28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F676C71CD15E0B00FC6FA6 /* ViewController.m */; }; @@ -16,6 +33,50 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 28CE8E881CD4C33E00FE25A8 /* CNFGGLOB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNFGGLOB.h; sourceTree = ""; }; + 28CE8E891CD4C33E00FE25A8 /* CNFGRAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNFGRAPI.h; sourceTree = ""; }; + 28CE8E8A1CD4C33E00FE25A8 /* EMCONFIG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EMCONFIG.h; sourceTree = ""; }; + 28CE8E8F1CD4C3B200FE25A8 /* COMOSGLU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = COMOSGLU.h; sourceTree = ""; }; + 28CE8E911CD4C3B200FE25A8 /* DATE2SEC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DATE2SEC.h; sourceTree = ""; }; + 28CE8E921CD4C3B200FE25A8 /* ENDIANAC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ENDIANAC.h; sourceTree = ""; }; + 28CE8E931CD4C3B200FE25A8 /* GLOBGLUE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GLOBGLUE.c; sourceTree = ""; }; + 28CE8E941CD4C3B200FE25A8 /* GLOBGLUE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLOBGLUE.h; sourceTree = ""; }; + 28CE8E961CD4C3B200FE25A8 /* IWMEMDEV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = IWMEMDEV.c; sourceTree = ""; }; + 28CE8E971CD4C3B200FE25A8 /* IWMEMDEV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWMEMDEV.h; sourceTree = ""; }; + 28CE8E981CD4C3B200FE25A8 /* KBRDEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = KBRDEMDV.c; sourceTree = ""; }; + 28CE8E991CD4C3B200FE25A8 /* KBRDEMDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KBRDEMDV.h; sourceTree = ""; }; + 28CE8E9A1CD4C3B200FE25A8 /* M68KITAB.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = M68KITAB.c; sourceTree = ""; }; + 28CE8E9B1CD4C3B200FE25A8 /* M68KITAB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = M68KITAB.h; sourceTree = ""; }; + 28CE8E9C1CD4C3B200FE25A8 /* MINEM68K.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MINEM68K.c; sourceTree = ""; }; + 28CE8E9D1CD4C3B200FE25A8 /* MINEM68K.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MINEM68K.h; sourceTree = ""; }; + 28CE8E9E1CD4C3B200FE25A8 /* MOUSEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MOUSEMDV.c; sourceTree = ""; }; + 28CE8E9F1CD4C3B200FE25A8 /* MOUSEMDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOUSEMDV.h; sourceTree = ""; }; + 28CE8EA01CD4C3B200FE25A8 /* MYOSGLUE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYOSGLUE.h; sourceTree = ""; }; + 28CE8EA11CD4C3B200FE25A8 /* PROGMAIN.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PROGMAIN.c; sourceTree = ""; }; + 28CE8EA21CD4C3B200FE25A8 /* PROGMAIN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PROGMAIN.h; sourceTree = ""; }; + 28CE8EA31CD4C3B200FE25A8 /* ROMEMDEV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ROMEMDEV.c; sourceTree = ""; }; + 28CE8EA41CD4C3B200FE25A8 /* ROMEMDEV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ROMEMDEV.h; sourceTree = ""; }; + 28CE8EA51CD4C3B200FE25A8 /* RTCEMDEV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RTCEMDEV.c; sourceTree = ""; }; + 28CE8EA61CD4C3B200FE25A8 /* RTCEMDEV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCEMDEV.h; sourceTree = ""; }; + 28CE8EA71CD4C3B200FE25A8 /* SCCEMDEV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SCCEMDEV.c; sourceTree = ""; }; + 28CE8EA81CD4C3B200FE25A8 /* SCCEMDEV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCCEMDEV.h; sourceTree = ""; }; + 28CE8EA91CD4C3B200FE25A8 /* SCRNEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SCRNEMDV.c; sourceTree = ""; }; + 28CE8EAA1CD4C3B200FE25A8 /* SCRNEMDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCRNEMDV.h; sourceTree = ""; }; + 28CE8EAB1CD4C3B200FE25A8 /* SCRNMAPR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCRNMAPR.h; sourceTree = ""; }; + 28CE8EAC1CD4C3B200FE25A8 /* SCSIEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SCSIEMDV.c; sourceTree = ""; }; + 28CE8EAD1CD4C3B200FE25A8 /* SCSIEMDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCSIEMDV.h; sourceTree = ""; }; + 28CE8EAE1CD4C3B200FE25A8 /* SNDEMDEV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SNDEMDEV.c; sourceTree = ""; }; + 28CE8EAF1CD4C3B200FE25A8 /* SNDEMDEV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNDEMDEV.h; sourceTree = ""; }; + 28CE8EB01CD4C3B200FE25A8 /* SONYEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SONYEMDV.c; sourceTree = ""; }; + 28CE8EB11CD4C3B200FE25A8 /* SONYEMDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SONYEMDV.h; sourceTree = ""; }; + 28CE8EB21CD4C3B200FE25A8 /* SYSDEPNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SYSDEPNS.h; sourceTree = ""; }; + 28CE8EB31CD4C3B200FE25A8 /* VIAEMDEV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VIAEMDEV.c; sourceTree = ""; }; + 28CE8EB41CD4C3B200FE25A8 /* VIAEMDEV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VIAEMDEV.h; sourceTree = ""; }; + 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOSGLUE.m; sourceTree = ""; }; + 28CE8ECD1CD4D1A100FE25A8 /* STRCONST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STRCONST.h; sourceTree = ""; }; + 28CE8ECF1CD4D5B900FE25A8 /* INTLCHAR.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = INTLCHAR.h; sourceTree = ""; }; + 28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenView.h; sourceTree = ""; }; + 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenView.m; sourceTree = ""; }; 28F676BD1CD15E0B00FC6FA6 /* Mini vMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mini vMac.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 28F676C11CD15E0B00FC6FA6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28F676C31CD15E0B00FC6FA6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -39,6 +100,61 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 28CE8E871CD4C33E00FE25A8 /* mnvm_cfg */ = { + isa = PBXGroup; + children = ( + 28CE8E881CD4C33E00FE25A8 /* CNFGGLOB.h */, + 28CE8E891CD4C33E00FE25A8 /* CNFGRAPI.h */, + 28CE8E8A1CD4C33E00FE25A8 /* EMCONFIG.h */, + ); + path = mnvm_cfg; + sourceTree = ""; + }; + 28CE8E8E1CD4C3B200FE25A8 /* mnvm_core */ = { + isa = PBXGroup; + children = ( + 28CE8ECF1CD4D5B900FE25A8 /* INTLCHAR.h */, + 28CE8ECD1CD4D1A100FE25A8 /* STRCONST.h */, + 28CE8E8F1CD4C3B200FE25A8 /* COMOSGLU.h */, + 28CE8E911CD4C3B200FE25A8 /* DATE2SEC.h */, + 28CE8E921CD4C3B200FE25A8 /* ENDIANAC.h */, + 28CE8E931CD4C3B200FE25A8 /* GLOBGLUE.c */, + 28CE8E941CD4C3B200FE25A8 /* GLOBGLUE.h */, + 28CE8E961CD4C3B200FE25A8 /* IWMEMDEV.c */, + 28CE8E971CD4C3B200FE25A8 /* IWMEMDEV.h */, + 28CE8E981CD4C3B200FE25A8 /* KBRDEMDV.c */, + 28CE8E991CD4C3B200FE25A8 /* KBRDEMDV.h */, + 28CE8E9A1CD4C3B200FE25A8 /* M68KITAB.c */, + 28CE8E9B1CD4C3B200FE25A8 /* M68KITAB.h */, + 28CE8E9C1CD4C3B200FE25A8 /* MINEM68K.c */, + 28CE8E9D1CD4C3B200FE25A8 /* MINEM68K.h */, + 28CE8E9E1CD4C3B200FE25A8 /* MOUSEMDV.c */, + 28CE8E9F1CD4C3B200FE25A8 /* MOUSEMDV.h */, + 28CE8EA01CD4C3B200FE25A8 /* MYOSGLUE.h */, + 28CE8EA11CD4C3B200FE25A8 /* PROGMAIN.c */, + 28CE8EA21CD4C3B200FE25A8 /* PROGMAIN.h */, + 28CE8EA31CD4C3B200FE25A8 /* ROMEMDEV.c */, + 28CE8EA41CD4C3B200FE25A8 /* ROMEMDEV.h */, + 28CE8EA51CD4C3B200FE25A8 /* RTCEMDEV.c */, + 28CE8EA61CD4C3B200FE25A8 /* RTCEMDEV.h */, + 28CE8EA71CD4C3B200FE25A8 /* SCCEMDEV.c */, + 28CE8EA81CD4C3B200FE25A8 /* SCCEMDEV.h */, + 28CE8EA91CD4C3B200FE25A8 /* SCRNEMDV.c */, + 28CE8EAA1CD4C3B200FE25A8 /* SCRNEMDV.h */, + 28CE8EAB1CD4C3B200FE25A8 /* SCRNMAPR.h */, + 28CE8EAC1CD4C3B200FE25A8 /* SCSIEMDV.c */, + 28CE8EAD1CD4C3B200FE25A8 /* SCSIEMDV.h */, + 28CE8EAE1CD4C3B200FE25A8 /* SNDEMDEV.c */, + 28CE8EAF1CD4C3B200FE25A8 /* SNDEMDEV.h */, + 28CE8EB01CD4C3B200FE25A8 /* SONYEMDV.c */, + 28CE8EB11CD4C3B200FE25A8 /* SONYEMDV.h */, + 28CE8EB21CD4C3B200FE25A8 /* SYSDEPNS.h */, + 28CE8EB31CD4C3B200FE25A8 /* VIAEMDEV.c */, + 28CE8EB41CD4C3B200FE25A8 /* VIAEMDEV.h */, + ); + path = mnvm_core; + sourceTree = ""; + }; 28F676B41CD15E0B00FC6FA6 = { isa = PBXGroup; children = ( @@ -60,12 +176,17 @@ children = ( 28F676C31CD15E0B00FC6FA6 /* AppDelegate.h */, 28F676C41CD15E0B00FC6FA6 /* AppDelegate.m */, + 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */, + 28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */, + 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */, 28F676C61CD15E0B00FC6FA6 /* ViewController.h */, 28F676C71CD15E0B00FC6FA6 /* ViewController.m */, 28F676C91CD15E0B00FC6FA6 /* Main.storyboard */, 28F676CC1CD15E0B00FC6FA6 /* Assets.xcassets */, 28F676CE1CD15E0B00FC6FA6 /* LaunchScreen.storyboard */, 28F676D11CD15E0B00FC6FA6 /* Info.plist */, + 28CE8E8E1CD4C3B200FE25A8 /* mnvm_core */, + 28CE8E871CD4C33E00FE25A8 /* mnvm_cfg */, 28F676C01CD15E0B00FC6FA6 /* Supporting Files */, ); path = "Mini vMac"; @@ -149,8 +270,25 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 28CE8EC01CD4C3B200FE25A8 /* SCSIEMDV.c in Sources */, + 28CE8EC11CD4C3B200FE25A8 /* SNDEMDEV.c in Sources */, + 28CE8EB51CD4C3B200FE25A8 /* GLOBGLUE.c in Sources */, + 28CE8EBF1CD4C3B200FE25A8 /* SCRNEMDV.c in Sources */, + 28CE8EBD1CD4C3B200FE25A8 /* RTCEMDEV.c in Sources */, + 28CE8EB61CD4C3B200FE25A8 /* IWMEMDEV.c in Sources */, + 28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */, + 28CE8EB91CD4C3B200FE25A8 /* MINEM68K.c in Sources */, + 28CE8EBA1CD4C3B200FE25A8 /* MOUSEMDV.c in Sources */, + 28CE8EC31CD4C3B200FE25A8 /* VIAEMDEV.c in Sources */, + 28CE8EB81CD4C3B200FE25A8 /* M68KITAB.c in Sources */, + 28CE8EB71CD4C3B200FE25A8 /* KBRDEMDV.c in Sources */, + 28CE8EBC1CD4C3B200FE25A8 /* ROMEMDEV.c in Sources */, + 28CE8EBB1CD4C3B200FE25A8 /* PROGMAIN.c in Sources */, 28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */, + 28CE8EC21CD4C3B200FE25A8 /* SONYEMDV.c in Sources */, 28F676C51CD15E0B00FC6FA6 /* AppDelegate.m in Sources */, + 28CE8EBE1CD4C3B200FE25A8 /* SCCEMDEV.c in Sources */, + 28CE8ECC1CD4CDC500FE25A8 /* MYOSGLUE.m in Sources */, 28F676C21CD15E0B00FC6FA6 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -267,7 +405,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = "Mini vMac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.Mini-vMac"; + PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -278,7 +416,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = "Mini vMac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.Mini-vMac"; + PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -302,6 +440,7 @@ 28F676D61CD15E0B00FC6FA6 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Mini vMac/AppDelegate.h b/Mini vMac/AppDelegate.h index bf1b6c6..9f595e3 100644 --- a/Mini vMac/AppDelegate.h +++ b/Mini vMac/AppDelegate.h @@ -12,6 +12,7 @@ @property (strong, nonatomic) UIWindow *window; ++ (instancetype)sharedInstance; @end diff --git a/Mini vMac/AppDelegate.m b/Mini vMac/AppDelegate.m index 7f22cf4..ecc81e3 100644 --- a/Mini vMac/AppDelegate.m +++ b/Mini vMac/AppDelegate.m @@ -7,6 +7,14 @@ // #import "AppDelegate.h" +#include "CNFGRAPI.h" +#include "SYSDEPNS.h" +#include "MYOSGLUE.h" + +IMPORTPROC RunEmulator(void); +IMPORTPROC SetSpeedStopped(blnr stopped); + +static AppDelegate *sharedAppDelegate = nil; @interface AppDelegate () @@ -14,32 +22,25 @@ @implementation AppDelegate ++ (instancetype)sharedInstance { + return sharedAppDelegate; +} - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. + [self performSelector:@selector(runEmulator) withObject:nil afterDelay:1.0]; return YES; } -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - - (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + SetSpeedStopped(trueblnr); } - (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + SetSpeedStopped(falseblnr); } -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +- (void)runEmulator { + RunEmulator(); } @end diff --git a/Mini vMac/Base.lproj/Main.storyboard b/Mini vMac/Base.lproj/Main.storyboard index f56d2f3..6cbf3f8 100644 --- a/Mini vMac/Base.lproj/Main.storyboard +++ b/Mini vMac/Base.lproj/Main.storyboard @@ -1,13 +1,14 @@ - + - + + - + @@ -15,11 +16,24 @@ + + + + + + + + + + + + + diff --git a/Mini vMac/Info.plist b/Mini vMac/Info.plist index 40c6215..315ea65 100644 --- a/Mini vMac/Info.plist +++ b/Mini vMac/Info.plist @@ -15,13 +15,15 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 2.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS + UIFileSharingEnabled + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -30,6 +32,10 @@ armv7 + UIRequiresFullScreen + + UIStatusBarHidden + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/Mini vMac/MYOSGLUE.m b/Mini vMac/MYOSGLUE.m new file mode 100644 index 0000000..62dd8c1 --- /dev/null +++ b/Mini vMac/MYOSGLUE.m @@ -0,0 +1,1709 @@ +/* + MYOSGLUE.m + + Copyright (C) 2012 Paul C. Pratt, SDL by Sam Lantinga and others + + You can redistribute this file and/or modify it under the terms + of version 2 of the GNU General Public License as published by + the Free Software Foundation. You should have received a copy + of the license along with this file; see the file COPYING. + + This file 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 + license for more details. + */ + +/* + MY Operating System GLUE. (for iOS) + + All operating system dependent code for the + iOS should go here. + + Originally derived from Cocoa port of SDL Library + by Sam Lantinga (but little trace of that remains). + */ + +@import UIKit; +@import AudioUnit; +@import AudioToolbox; +#include "CNFGRAPI.h" +#include "SYSDEPNS.h" +#include "ENDIANAC.h" +#include "MYOSGLUE.h" +#include "STRCONST.h" +#import "ScreenView.h" + +#pragma mark - some simple utilities + +GLOBALPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount) { + (void)memcpy((char *)destPtr, (char *)srcPtr, byteCount); +} + +#pragma mark - control mode and internationalization + +#define NeedCell2UnicodeMap 1 + +#include "INTLCHAR.h" + +#pragma mark - sending debugging info to file + +#if dbglog_HAVE + +#define dbglog_ToStdErr 0 + +#if !dbglog_ToStdErr +LOCALVAR FILE *dbglog_File = NULL; +#endif + +LOCALFUNC blnr dbglog_open0(void) { +#if dbglog_ToStdErr + return trueblnr; +#else + NSString *myLogPath = [MyDataPath stringByAppendingPathComponent:@"dbglog.txt"]; + const char *path = [myLogPath fileSystemRepresentation]; + + dbglog_File = fopen(path, "w"); + return (NULL != dbglog_File); +#endif +} + +LOCALPROC dbglog_write0(char *s, uimr L) { +#if dbglog_ToStdErr + (void)fwrite(s, 1, L, stderr); +#else + if (NULL != dbglog_File) { + (void)fwrite(s, 1, L, dbglog_File); + } +#endif +} + +LOCALPROC dbglog_close0(void) { +#if !dbglog_ToStdErr + if (NULL != dbglog_File) { + fclose(dbglog_File); + dbglog_File = NULL; + } +#endif +} + +#endif + +#pragma mark - information about the environment + +#define WantColorTransValid 1 + +#include "COMOSGLU.h" + +#pragma mark - Cocoa Stuff + +LOCALFUNC blnr FindNamedChildFilePath(NSString *parentPath, char *ChildName, NSString **childPath) { + NSFileManager *fm = [NSFileManager defaultManager]; + BOOL isDirectory; + if ([fm fileExistsAtPath:parentPath isDirectory:&isDirectory] && isDirectory) { + *childPath = [parentPath stringByAppendingPathComponent:@(ChildName)]; + return trueblnr; + } else { + return falseblnr; + } +} + +LOCALVAR CGDataProviderRef screenDataProvider = NULL; +LOCALVAR CGColorSpaceRef screenColorSpace = NULL; + +LOCALFUNC blnr Screen_Init(void) { + screenDataProvider = CGDataProviderCreateWithData(NULL, screencomparebuff, vMacScreenNumBytes, NULL); + CGColorSpaceRef baseColorSpace = CGColorSpaceCreateDeviceRGB(); + uint8_t clut[] = {255, 255, 255, 0, 0, 0}; + screenColorSpace = CGColorSpaceCreateIndexed(baseColorSpace, 1, clut); + CGColorSpaceRelease(baseColorSpace); + return trueblnr; +} + +LOCALPROC Screen_UnInit(void) { + if (screenDataProvider) { + CGDataProviderRelease(screenDataProvider); + screenDataProvider = NULL; + } + if (screenColorSpace) { + CGColorSpaceRelease(screenColorSpace); + screenColorSpace = NULL; + } +} + +LOCALVAR NSString *MyDataPath = nil; + +LOCALFUNC blnr InitCocoaStuff(void) { + MyDataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; + if (MyDataPath) { + [MyDataPath retain]; + } + + Screen_Init(); + return trueblnr; +} + +LOCALPROC UnInitCocoaStuff(void) { + [MyDataPath release]; + MyDataPath = nil; + Screen_UnInit(); +} + +#pragma mark - Parameter Buffers + +#if IncludePbufs +LOCALVAR void *PbufDat[NumPbufs]; +#endif + +#if IncludePbufs +LOCALFUNC tMacErr PbufNewFromPtr(void *p, ui5b count, tPbuf *r) { + tPbuf i; + tMacErr err; + + if (!FirstFreePbuf(&i)) { + free(p); + err = mnvm_miscErr; + } else { + *r = i; + PbufDat[i] = p; + PbufNewNotify(i, count); + err = mnvm_noErr; + } + + return err; +} +#endif + +#if IncludePbufs +GLOBALFUNC tMacErr PbufNew(ui5b count, tPbuf *r) { + tMacErr err = mnvm_miscErr; + + void *p = calloc(1, count); + if (NULL != p) { + err = PbufNewFromPtr(p, count, r); + } + + return err; +} +#endif + +#if IncludePbufs +GLOBALPROC PbufDispose(tPbuf i) { + free(PbufDat[i]); + PbufDisposeNotify(i); +} +#endif + +#if IncludePbufs +LOCALPROC UnInitPbufs(void) { + tPbuf i; + + for (i = 0; i < NumPbufs; ++i) { + if (PbufIsAllocated(i)) { + PbufDispose(i); + } + } +} +#endif + +#if IncludePbufs +GLOBALPROC PbufTransfer(ui3p Buffer, + tPbuf i, + ui5r offset, + ui5r count, + blnr IsWrite) { + void *p = ((ui3p)PbufDat[i]) + offset; + if (IsWrite) { + (void)memcpy(p, Buffer, count); + } else { + (void)memcpy(Buffer, p, count); + } +} +#endif + +#pragma mark - Text Translation + +LOCALPROC UniCharStrFromSubstCStr(int *L, unichar *x, char *s, blnr AddEllipsis) { + int i; + int L0; + ui3b ps[ClStrMaxLength]; + + ClStrFromSubstCStr(&L0, ps, s); + if (AddEllipsis) { + ClStrAppendChar(&L0, ps, kCellEllipsis); + } + + for (i = 0; i < L0; ++i) { + x[i] = Cell2UnicodeMap[ps[i]]; + } + + *L = L0; +} + +LOCALFUNC NSString *NSStringCreateFromSubstCStr(char *s, + blnr AddEllipsis) { + int L; + unichar x[ClStrMaxLength]; + + UniCharStrFromSubstCStr(&L, x, s, AddEllipsis); + + return [NSString stringWithCharacters:x length:L]; +} + +#if IncludeSonyNameNew +LOCALFUNC blnr MacRomanFileNameToNSString(tPbuf i, + NSString **r) { + ui3p p; + void *Buffer = PbufDat[i]; + ui5b L = PbufSize[i]; + + p = (ui3p)malloc(L /* + 1 */); + if (p != NULL) { + NSData *d; + ui3b *p0 = (ui3b *)Buffer; + ui3b *p1 = (ui3b *)p; + + if (L > 0) { + ui5b j = L; + + do { + ui3b x = *p0++; + if (x < 32) { + x = '-'; + } else if (x >= 128) { + } else { + switch (x) { + case '/': + case '<': + case '>': + case '|': + case ':': + x = '-'; + default: + break; + } + } + *p1++ = x; + } while (--j > 0); + + if ('.' == p[0]) { + p[0] = '-'; + } + } + +#if 0 + *p1 = 0; + *r = [NSString stringWithCString:(char *)p + encoding:NSMacOSRomanStringEncoding]; + /* only as of OS X 10.4 */ + free(p); +#endif + + d = [[NSData alloc] initWithBytesNoCopy:p length:L]; + + *r = [[[NSString alloc] + initWithData:d + encoding:NSMacOSRomanStringEncoding] + autorelease]; + + [d release]; + + return trueblnr; + } + + return falseblnr; +} +#endif + +#if IncludeSonyGetName || IncludeHostTextClipExchange +LOCALFUNC tMacErr CopyBytesToPbuf(const char *x, ui5r L, tPbuf *r) { + if (NULL == x) { + return mnvm_miscErr; + } else { + ui3p p = (ui3p)malloc(L); + + if (NULL == p) { + return mnvm_miscErr; + } else { + memcpy((char *)p, x, L); + + return PbufNewFromPtr(p, L, r); + } + } +} +#endif + +#if IncludeSonyGetName || IncludeHostTextClipExchange +LOCALFUNC tMacErr NSStringToRomanPbuf(NSString *string, tPbuf *r) { + tMacErr v = mnvm_miscErr; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSData *d0 = [string dataUsingEncoding:NSMacOSRomanStringEncoding]; + const void *s = [d0 bytes]; + NSUInteger L = [d0 length]; + + v = CopyBytesToPbuf(s, (ui5r)L, r); + + [pool release]; + + return v; +} +#endif + +#pragma mark - Drives + +#define NotAfileRef NULL +LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */ +#if IncludeSonyGetName || IncludeSonyNew +LOCALVAR NSString *DriveNames[NumDrives]; +#endif + +LOCALPROC InitDrives(void) { + /* + This isn't really needed, Drives[i] and DriveNames[i] + need not have valid values when not vSonyIsInserted[i]. + */ + tDrive i; + + for (i = 0; i < NumDrives; ++i) { + Drives[i] = NotAfileRef; +#if IncludeSonyGetName || IncludeSonyNew + DriveNames[i] = nil; +#endif + } +} + +GLOBALFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { + tMacErr err = mnvm_miscErr; + FILE *refnum = Drives[Drive_No]; + ui5r NewSony_Count = 0; + + if (0 == fseek(refnum, Sony_Start, SEEK_SET)) { + if (IsWrite) { + NewSony_Count = (ui5r)fwrite(Buffer, 1, Sony_Count, refnum); + } else { + NewSony_Count = (ui5r)fread(Buffer, 1, Sony_Count, refnum); + } + + if (NewSony_Count == Sony_Count) { + err = mnvm_noErr; + } + } + + if (nullpr != Sony_ActCount) { + *Sony_ActCount = NewSony_Count; + } + + return err; /*& figure out what really to return &*/ +} + +GLOBALFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count) { + tMacErr err = mnvm_miscErr; + FILE *refnum = Drives[Drive_No]; + long v; + + if (0 == fseek(refnum, 0, SEEK_END)) { + v = ftell(refnum); + if (v >= 0) { + *Sony_Count = (ui5r)v; + err = mnvm_noErr; + } + } + + return err; /*& figure out what really to return &*/ +} + +#ifndef HaveAdvisoryLocks +#define HaveAdvisoryLocks 1 +#endif + +/* + What is the difference between fcntl(fd, F_SETLK ... + and flock(fd ... ? + */ + +#if HaveAdvisoryLocks +LOCALFUNC blnr MyLockFile(FILE *refnum) { + blnr IsOk = falseblnr; + +#if 0 + struct flock fl; + int fd = fileno(refnum); + + fl.l_start = 0; /* starting offset */ + fl.l_len = 0; /* len = 0 means until end of file */ + /* fl.pid_t l_pid; */ /* lock owner, don't need to set */ + fl.l_type = F_WRLCK; /* lock type: read/write, etc. */ + fl.l_whence = SEEK_SET; /* type of l_start */ + if (-1 == fcntl(fd, F_SETLK, &fl)) { + MacMsg(kStrImageInUseTitle, kStrImageInUseMessage, + falseblnr); + } else { + IsOk = trueblnr; + } +#else + int fd = fileno(refnum); + + if (-1 == flock(fd, LOCK_EX | LOCK_NB)) { + if (EWOULDBLOCK == errno) { + /* already locked */ + MacMsg(kStrImageInUseTitle, kStrImageInUseMessage, + falseblnr); + } else { + /* + Failed for other reasons, such as unsupported + for this volume. + Don't prevent opening. + */ + IsOk = trueblnr; + } + } else { + IsOk = trueblnr; + } +#endif + + return IsOk; +} +#endif + +#if HaveAdvisoryLocks +LOCALPROC MyUnlockFile(FILE *refnum) { +#if 0 + struct flock fl; + int fd = fileno(refnum); + + fl.l_start = 0; /* starting offset */ + fl.l_len = 0; /* len = 0 means until end of file */ + /* fl.pid_t l_pid; */ /* lock owner, don't need to set */ + fl.l_type = F_UNLCK; /* lock type: read/write, etc. */ + fl.l_whence = SEEK_SET; /* type of l_start */ + if (-1 == fcntl(fd, F_SETLK, &fl)) { + /* an error occurred */ + } +#else + int fd = fileno(refnum); + + if (-1 == flock(fd, LOCK_UN)) { + } +#endif +} +#endif + +LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit) { + FILE *refnum = Drives[Drive_No]; + + DiskEjectedNotify(Drive_No); + +#if HaveAdvisoryLocks + MyUnlockFile(refnum); +#endif + + fclose(refnum); + Drives[Drive_No] = NotAfileRef; /* not really needed */ + +#if IncludeSonyGetName || IncludeSonyNew + { + NSString *filePath = DriveNames[Drive_No]; + if (NULL != filePath) { + if (deleteit) { + NSAutoreleasePool *pool = + [[NSAutoreleasePool alloc] init]; + const char *s = [filePath fileSystemRepresentation]; + remove(s); + [pool release]; + } + [filePath release]; + DriveNames[Drive_No] = NULL; /* not really needed */ + } + } +#endif + + return mnvm_noErr; +} + +GLOBALFUNC tMacErr vSonyEject(tDrive Drive_No) { + return vSonyEject0(Drive_No, falseblnr); +} + +#if IncludeSonyNew +GLOBALFUNC tMacErr vSonyEjectDelete(tDrive Drive_No) { + return vSonyEject0(Drive_No, trueblnr); +} +#endif + +LOCALPROC UnInitDrives(void) { + tDrive i; + + for (i = 0; i < NumDrives; ++i) { + if (vSonyIsInserted(i)) { + (void)vSonyEject(i); + } + } +} + +#if IncludeSonyGetName +GLOBALFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r) { + tMacErr v = mnvm_miscErr; + NSString *filePath = DriveNames[Drive_No]; + if (NULL != filePath) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSString *s0 = [filePath lastPathComponent]; + v = NSStringToRomanPbuf(s0, r); + + [pool release]; + } + + return v; +} +#endif + +LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked, NSString *filePath) { + tDrive Drive_No; + blnr IsOk = falseblnr; + + if (!FirstFreeDisk(&Drive_No)) { + MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage, + falseblnr); + } else { +/* printf("Sony_Insert0 %d\n", (int)Drive_No); */ + +#if HaveAdvisoryLocks + if (locked || MyLockFile(refnum)) +#endif + { + Drives[Drive_No] = refnum; + DiskInsertNotify(Drive_No, locked); + +#if IncludeSonyGetName || IncludeSonyNew + DriveNames[Drive_No] = [filePath retain]; +#endif + + IsOk = trueblnr; + } + } + + if (!IsOk) { + fclose(refnum); + } + + return IsOk; +} + +LOCALFUNC blnr Sony_Insert1(NSString *filePath, blnr silentfail) { + /* const char *drivepath = [filePath UTF8String]; */ + const char *drivepath = [filePath fileSystemRepresentation]; + blnr locked = falseblnr; + /* printf("Sony_Insert1 %s\n", drivepath); */ + FILE *refnum = fopen(drivepath, "rb+"); + if (NULL == refnum) { + locked = trueblnr; + refnum = fopen(drivepath, "rb"); + } + if (NULL == refnum) { + if (!silentfail) { + MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr); + } + } else { + return Sony_Insert0(refnum, locked, filePath); + } + return falseblnr; +} + +LOCALFUNC blnr Sony_Insert2(char *s) { + NSString *sPath; + + if (!FindNamedChildFilePath(MyDataPath, s, &sPath)) { + return falseblnr; + } else { + return Sony_Insert1(sPath, trueblnr); + } +} + +LOCALFUNC blnr LoadInitialImages(void) { + if (!AnyDiskInserted()) { + int n = NumDrives > 9 ? 9 : NumDrives; + int i; + char s[] = "disk?.dsk"; + + for (i = 1; i <= n; ++i) { + s[4] = '0' + i; + if (!Sony_Insert2(s)) { + /* stop on first error (including file not found) */ + return trueblnr; + } + } + } + + return trueblnr; +} + +#if IncludeSonyNew +LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L) { +#define ZeroBufferSize 2048 + ui5b i; + ui3b buffer[ZeroBufferSize]; + + memset(&buffer, 0, ZeroBufferSize); + + while (L > 0) { + i = (L > ZeroBufferSize) ? ZeroBufferSize : L; + if (fwrite(buffer, 1, i, refnum) != i) { + return falseblnr; + } + L -= i; + } + return trueblnr; +} +#endif + +#if IncludeSonyNew +LOCALPROC MakeNewDisk0(ui5b L, NSString *sPath) { + blnr IsOk = falseblnr; + const char *drivepath = [sPath fileSystemRepresentation]; + FILE *refnum = fopen(drivepath, "wb+"); + if (NULL == refnum) { + MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr); + } else { + if (WriteZero(refnum, L)) { + IsOk = Sony_Insert0(refnum, falseblnr, sPath); + refnum = NULL; + } + if (refnum != NULL) { + fclose(refnum); + } + if (!IsOk) { + (void)remove(drivepath); + } + } +} +#endif + +#pragma mark - ROM + +/* --- ROM --- */ + +LOCALFUNC tMacErr LoadMacRomFrom(NSString *parentPath) { + FILE *ROM_File; + size_t File_Size; + NSString *RomPath; + tMacErr err = mnvm_fnfErr; + + if (FindNamedChildFilePath(parentPath, RomFileName, &RomPath)) { + const char *path = [RomPath fileSystemRepresentation]; + + ROM_File = fopen(path, "rb"); + if (NULL != ROM_File) { + File_Size = fread(ROM, 1, kROM_Size, ROM_File); + if (kROM_Size != File_Size) { + if (feof(ROM_File)) { + err = mnvm_eofErr; + } else { + err = mnvm_miscErr; + } + } else { + err = mnvm_noErr; + } + fclose(ROM_File); + } + } + + return err; +} + +LOCALFUNC blnr LoadMacRom(void) { + tMacErr err; + + if (mnvm_fnfErr == (err = LoadMacRomFrom(MyDataPath))) { + } + + if (mnvm_noErr != err) { + if (mnvm_fnfErr == err) { + MacMsg(kStrNoROMTitle, kStrNoROMMessage, trueblnr); + } else if (mnvm_eofErr == err) { + MacMsg(kStrShortROMTitle, kStrShortROMMessage, + trueblnr); + } else { + MacMsg(kStrNoReadROMTitle, kStrNoReadROMMessage, + trueblnr); + } + + SpeedStopped = trueblnr; + } + + return trueblnr; /* keep launching Mini vMac, regardless */ +} + +#if IncludeHostTextClipExchange +GLOBALFUNC tMacErr HTCEexport(tPbuf i) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSData *d = [NSData dataWithBytes:PbufDat[i] length:PbufSize[i]]; + NSString *ss = [[[NSString alloc] + initWithData:d + encoding:NSMacOSRomanStringEncoding] + autorelease]; + UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; + pasteboard.string = ss; + + PbufDispose(i); + + [pool release]; + + return mnvm_noErr; +} +#endif + +#if IncludeHostTextClipExchange +GLOBALFUNC tMacErr HTCEimport(tPbuf *r) { + tMacErr err = mnvm_miscErr; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; + if (pasteboard.string != nil) { + err = NSStringToRomanPbuf(pasteboard.string, r); + } + [pool release]; + + return err; +} +#endif + +#if EmLocalTalk + +#include "BPFILTER.h" + +#endif + +#pragma mark - time, date, location + +#define dbglog_TimeStuff (0 && dbglog_HAVE) + +LOCALVAR ui5b TrueEmulatedTime = 0; + +LOCALVAR NSTimeInterval LatestTime; +LOCALVAR NSTimeInterval NextTickChangeTime; + +#define MyTickDuration (1.0 / 60.14742) + +LOCALVAR ui5b NewMacDateInSeconds; + +LOCALPROC UpdateTrueEmulatedTime(void) { + NSTimeInterval TimeDiff; + + LatestTime = [NSDate timeIntervalSinceReferenceDate]; + TimeDiff = LatestTime - NextTickChangeTime; + + if (TimeDiff >= 0.0) { + if (TimeDiff > 16 * MyTickDuration) { + /* emulation interrupted, forget it */ + ++TrueEmulatedTime; + NextTickChangeTime = LatestTime + MyTickDuration; + +#if dbglog_TimeStuff + dbglog_writelnNum("emulation interrupted", + TrueEmulatedTime); +#endif + } else { + do { +#if 0 && dbglog_TimeStuff + dbglog_writeln("got next tick"); +#endif + ++TrueEmulatedTime; + TimeDiff -= MyTickDuration; + NextTickChangeTime += MyTickDuration; + } while (TimeDiff >= 0.0); + } + } else if (TimeDiff < (-16 * MyTickDuration)) { +/* clock set back, reset */ +#if dbglog_TimeStuff + dbglog_writeln("clock set back"); +#endif + + NextTickChangeTime = LatestTime + MyTickDuration; + } +} + +LOCALVAR ui5b MyDateDelta; + +LOCALFUNC blnr CheckDateTime(void) { + NewMacDateInSeconds = ((ui5b)LatestTime) + MyDateDelta; + if (CurMacDateInSeconds != NewMacDateInSeconds) { + CurMacDateInSeconds = NewMacDateInSeconds; + return trueblnr; + } else { + return falseblnr; + } +} + +LOCALPROC StartUpTimeAdjust(void) { + LatestTime = [NSDate timeIntervalSinceReferenceDate]; + NextTickChangeTime = LatestTime; +} + +LOCALFUNC blnr InitLocationDat(void) { + NSTimeZone *MyZone = [NSTimeZone localTimeZone]; + ui5b TzOffSet = (ui5b)[MyZone secondsFromGMT]; + BOOL isdst = [MyZone isDaylightSavingTime]; + + MyDateDelta = TzOffSet - 1233815296; + LatestTime = [NSDate timeIntervalSinceReferenceDate]; + NewMacDateInSeconds = ((ui5b)LatestTime) + MyDateDelta; + CurMacDateInSeconds = NewMacDateInSeconds; + CurMacDelta = (TzOffSet & 0x00FFFFFF) | ((isdst ? 0x80 : 0) << 24); + + return trueblnr; +} + +#pragma mark - Mouse + +LOCALFUNC blnr MyMoveMouse(si4b h, si4b v) { + // TODO: move mouse + return trueblnr; +} + +#pragma mark - video out + +LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left, ui4r bottom, ui4r right) { + size_t bitsPerPixel = 1 << vMacScreenDepth; + size_t bitsPerComponent = vMacScreenDepth <= 4 ? 1 << vMacScreenDepth : vMacScreenDepth == 5 ? 5 : 8; + CGBitmapInfo options = 0; + + CGImageRef screenImage = CGImageCreate(vMacScreenWidth, vMacScreenHeight, bitsPerComponent, bitsPerPixel, vMacScreenByteWidth, screenColorSpace, options, screenDataProvider, NULL, false, kCGRenderingIntentDefault); + [[ScreenView sharedScreenView] updateScreen:screenImage]; + CGImageRelease(screenImage); +} + +LOCALPROC MyDrawChangesAndClear(void) { + if (ScreenChangedBottom > ScreenChangedTop) { + HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft, + ScreenChangedBottom, ScreenChangedRight); + ScreenClearChanges(); + } +} + +GLOBALPROC DoneWithDrawingForTick(void) { +#if EnableMouseMotion && MayFullScreen + if (HaveMouseMotion) { + AutoScrollScreen(); + } +#endif + MyDrawChangesAndClear(); +} + +#pragma mark - Sound + +#if MySoundEnabled + +#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */ +#define kSoundBuffers (1 << kLn2SoundBuffers) +#define kSoundBuffMask (kSoundBuffers - 1) + +#define DesiredMinFilledSoundBuffs 3 +/* + if too big then sound lags behind emulation. + if too small then sound will have pauses. + */ + +#define kLnOneBuffLen 9 +#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen) +#define kOneBuffLen (1UL << kLnOneBuffLen) +#define kAllBuffLen (1UL << kLnAllBuffLen) +#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3) +#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3) +#define kOneBuffSz (1UL << kLnOneBuffSz) +#define kAllBuffSz (1UL << kLnAllBuffSz) +#define kOneBuffMask (kOneBuffLen - 1) +#define kAllBuffMask (kAllBuffLen - 1) +#define dbhBufferSize (kAllBuffSz + kOneBuffSz) + +#define dbglog_SoundStuff (0 && dbglog_HAVE) +#define dbglog_SoundBuffStats (0 && dbglog_HAVE) + +LOCALVAR tpSoundSamp TheSoundBuffer = nullpr; +volatile static ui4b ThePlayOffset; +volatile static ui4b TheFillOffset; +volatile static ui4b MinFilledSoundBuffs; +#if dbglog_SoundBuffStats +LOCALVAR ui4b MaxFilledSoundBuffs; +#endif +LOCALVAR ui4b TheWriteOffset; + +LOCALPROC MySound_Start0(void) { + /* Reset variables */ + ThePlayOffset = 0; + TheFillOffset = 0; + TheWriteOffset = 0; + MinFilledSoundBuffs = kSoundBuffers + 1; +#if dbglog_SoundBuffStats + MaxFilledSoundBuffs = 0; +#endif +} + +GLOBALFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL) { + ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset); + ui4b WriteBuffContig = + kOneBuffLen - (TheWriteOffset & kOneBuffMask); + + if (WriteBuffContig < n) { + n = WriteBuffContig; + } + if (ToFillLen < n) { +/* overwrite previous buffer */ +#if dbglog_SoundStuff + dbglog_writeln("sound buffer over flow"); +#endif + TheWriteOffset -= kOneBuffLen; + } + + *actL = n; + return TheSoundBuffer + (TheWriteOffset & kAllBuffMask); +} + +#if 4 == kLn2SoundSampSz +LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p) { + int i; + + for (i = kOneBuffLen; --i >= 0;) { + *p++ -= 0x8000; + } +} +#else +#define ConvertSoundBlockToNative(p) +#endif + +LOCALPROC MySound_WroteABlock(void) { +#if (4 == kLn2SoundSampSz) + ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen; + tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask); +#endif + +#if dbglog_SoundStuff + dbglog_writeln("enter MySound_WroteABlock"); +#endif + + ConvertSoundBlockToNative(p); + + TheFillOffset = TheWriteOffset; + +#if dbglog_SoundBuffStats + { + ui4b ToPlayLen = TheFillOffset - ThePlayOffset; + ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen; + + if (ToPlayBuffs > MaxFilledSoundBuffs) { + MaxFilledSoundBuffs = ToPlayBuffs; + } + } +#endif +} + +LOCALFUNC blnr MySound_EndWrite0(ui4r actL) { + blnr v; + + TheWriteOffset += actL; + + if (0 != (TheWriteOffset & kOneBuffMask)) { + v = falseblnr; + } else { + /* just finished a block */ + + MySound_WroteABlock(); + + v = trueblnr; + } + + return v; +} + +LOCALPROC MySound_SecondNotify0(void) { + if (MinFilledSoundBuffs <= kSoundBuffers) { + if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) { +#if dbglog_SoundStuff + dbglog_writeln("MinFilledSoundBuffs too high"); +#endif + NextTickChangeTime += MyTickDuration; + } else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) { +#if dbglog_SoundStuff + dbglog_writeln("MinFilledSoundBuffs too low"); +#endif + ++TrueEmulatedTime; + } +#if dbglog_SoundBuffStats + dbglog_writelnNum("MinFilledSoundBuffs", + MinFilledSoundBuffs); + dbglog_writelnNum("MaxFilledSoundBuffs", + MaxFilledSoundBuffs); + MaxFilledSoundBuffs = 0; +#endif + MinFilledSoundBuffs = kSoundBuffers + 1; + } +} + +typedef ui4r trSoundTemp; + +#define kCenterTempSound 0x8000 + +#define AudioStepVal 0x0040 + +#if 3 == kLn2SoundSampSz +#define ConvertTempSoundSampleFromNative(v) ((v) << 8) +#elif 4 == kLn2SoundSampSz +#define ConvertTempSoundSampleFromNative(v) ((v) + kCenterSound) +#else +#error "unsupported kLn2SoundSampSz" +#endif + +#if 3 == kLn2SoundSampSz +#define ConvertTempSoundSampleToNative(v) ((v) >> 8) +#elif 4 == kLn2SoundSampSz +#define ConvertTempSoundSampleToNative(v) ((v)-kCenterSound) +#else +#error "unsupported kLn2SoundSampSz" +#endif + +LOCALPROC SoundRampTo(trSoundTemp *last_val, trSoundTemp dst_val, tpSoundSamp *stream, int *len) { + trSoundTemp diff; + tpSoundSamp p = *stream; + int n = *len; + trSoundTemp v1 = *last_val; + + while ((v1 != dst_val) && (0 != n)) { + if (v1 > dst_val) { + diff = v1 - dst_val; + if (diff > AudioStepVal) { + v1 -= AudioStepVal; + } else { + v1 = dst_val; + } + } else { + diff = dst_val - v1; + if (diff > AudioStepVal) { + v1 += AudioStepVal; + } else { + v1 = dst_val; + } + } + + --n; + *p++ = ConvertTempSoundSampleToNative(v1); + } + + *stream = p; + *len = n; + *last_val = v1; +} + +struct MySoundR { + tpSoundSamp fTheSoundBuffer; + volatile ui4b(*fPlayOffset); + volatile ui4b(*fFillOffset); + volatile ui4b(*fMinFilledSoundBuffs); + + volatile trSoundTemp lastv; + + blnr enabled; + blnr wantplaying; + blnr HaveStartedPlaying; + + AudioUnit outputAudioUnit; +}; +typedef struct MySoundR MySoundR; + +LOCALPROC my_audio_callback(void *udata, void *stream, int len) { + ui4b ToPlayLen; + ui4b FilledSoundBuffs; + int i; + MySoundR *datp = (MySoundR *)udata; + tpSoundSamp CurSoundBuffer = datp->fTheSoundBuffer; + ui4b CurPlayOffset = *datp->fPlayOffset; + trSoundTemp v0 = datp->lastv; + trSoundTemp v1 = v0; + tpSoundSamp dst = (tpSoundSamp)stream; + +#if kLn2SoundSampSz > 3 + len >>= (kLn2SoundSampSz - 3); +#endif + +#if dbglog_SoundStuff + dbglog_writeln("Enter my_audio_callback"); + dbglog_writelnNum("len", len); +#endif + +label_retry: + ToPlayLen = *datp->fFillOffset - CurPlayOffset; + FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen; + + if (!datp->wantplaying) { +#if dbglog_SoundStuff + dbglog_writeln("playing end transistion"); +#endif + + SoundRampTo(&v1, kCenterTempSound, &dst, &len); + + ToPlayLen = 0; + } else if (!datp->HaveStartedPlaying) { +#if dbglog_SoundStuff + dbglog_writeln("playing start block"); +#endif + + if ((ToPlayLen >> kLnOneBuffLen) < 8) { + ToPlayLen = 0; + } else { + tpSoundSamp p = datp->fTheSoundBuffer + (CurPlayOffset & kAllBuffMask); + trSoundTemp v2 = ConvertTempSoundSampleFromNative(*p); + +#if dbglog_SoundStuff + dbglog_writeln("have enough samples to start"); +#endif + + SoundRampTo(&v1, v2, &dst, &len); + + if (v1 == v2) { +#if dbglog_SoundStuff + dbglog_writeln("finished start transition"); +#endif + + datp->HaveStartedPlaying = trueblnr; + } + } + } + + if (0 == len) { + /* done */ + + if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) { + *datp->fMinFilledSoundBuffs = FilledSoundBuffs; + } + } else if (0 == ToPlayLen) { +#if dbglog_SoundStuff + dbglog_writeln("under run"); +#endif + + for (i = 0; i < len; ++i) { + *dst++ = ConvertTempSoundSampleToNative(v1); + } + *datp->fMinFilledSoundBuffs = 0; + } else { + ui4b PlayBuffContig = kAllBuffLen - (CurPlayOffset & kAllBuffMask); + tpSoundSamp p = CurSoundBuffer + (CurPlayOffset & kAllBuffMask); + + if (ToPlayLen > PlayBuffContig) { + ToPlayLen = PlayBuffContig; + } + if (ToPlayLen > len) { + ToPlayLen = len; + } + + for (i = 0; i < ToPlayLen; ++i) { + *dst++ = *p++; + } + v1 = ConvertTempSoundSampleFromNative(p[-1]); + + CurPlayOffset += ToPlayLen; + len -= ToPlayLen; + + *datp->fPlayOffset = CurPlayOffset; + + goto label_retry; + } + + datp->lastv = v1; +} + +LOCALFUNC OSStatus audioCallback(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { + AudioBuffer *abuf; + UInt32 i; + UInt32 n = ioData->mNumberBuffers; + +#if dbglog_SoundStuff + dbglog_writeln("Enter audioCallback"); + dbglog_writelnNum("mNumberBuffers", n); +#endif + + for (i = 0; i < n; i++) { + abuf = &ioData->mBuffers[i]; + my_audio_callback(inRefCon, + abuf->mData, abuf->mDataByteSize); + } + + return 0; +} + +LOCALVAR MySoundR cur_audio; + +LOCALPROC ZapAudioVars(void) { + memset(&cur_audio, 0, sizeof(MySoundR)); +} + +LOCALPROC MySound_Stop(void) { +#if dbglog_SoundStuff + dbglog_writeln("enter MySound_Stop"); +#endif + + if (cur_audio.wantplaying) { + OSStatus result; + ui4r retry_limit = 50; /* half of a second */ + + cur_audio.wantplaying = falseblnr; + + label_retry: + if (kCenterTempSound == cur_audio.lastv) { +#if dbglog_SoundStuff + dbglog_writeln("reached kCenterTempSound"); +#endif + + /* done */ + } else if (0 == --retry_limit) { +#if dbglog_SoundStuff + dbglog_writeln("retry limit reached"); +#endif + /* done */ + } else { + /* + give time back, particularly important + if got here on a suspend event. + */ + struct timespec rqt; + struct timespec rmt; + +#if dbglog_SoundStuff + dbglog_writeln("busy, so sleep"); +#endif + + rqt.tv_sec = 0; + rqt.tv_nsec = 10000000; + (void)nanosleep(&rqt, &rmt); + + goto label_retry; + } + + if (noErr != (result = AudioOutputUnitStop(cur_audio.outputAudioUnit))) { +#if dbglog_HAVE + dbglog_writeln("AudioOutputUnitStop fails"); +#endif + } + } + +#if dbglog_SoundStuff + dbglog_writeln("leave MySound_Stop"); +#endif +} + +LOCALPROC MySound_Start(void) { + OSStatus result; + + if ((!cur_audio.wantplaying) && cur_audio.enabled) { +#if dbglog_SoundStuff + dbglog_writeln("enter MySound_Start"); +#endif + + MySound_Start0(); + cur_audio.lastv = kCenterTempSound; + cur_audio.HaveStartedPlaying = falseblnr; + cur_audio.wantplaying = trueblnr; + + if (noErr != (result = AudioOutputUnitStart(cur_audio.outputAudioUnit))) { +#if dbglog_HAVE + dbglog_writeln("AudioOutputUnitStart fails"); +#endif + cur_audio.wantplaying = falseblnr; + } + +#if dbglog_SoundStuff + dbglog_writeln("leave MySound_Start"); +#endif + } +} + +LOCALPROC MySound_UnInit(void) { + if (cur_audio.enabled) { + OSStatus result; + struct AURenderCallbackStruct callback; + + cur_audio.enabled = falseblnr; + + /* Remove the input callback */ + callback.inputProc = 0; + callback.inputProcRefCon = 0; + + if (noErr != (result = AudioUnitSetProperty(cur_audio.outputAudioUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)))) { +#if dbglog_HAVE + dbglog_writeln( + "AudioUnitSetProperty fails" + "(kAudioUnitProperty_SetRenderCallback)"); +#endif + } + + if (noErr != (result = AudioComponentInstanceDispose(cur_audio.outputAudioUnit))) { +#if dbglog_HAVE + dbglog_writeln("AudioComponentInstanceDispose fails in MySound_UnInit"); +#endif + } + } +} + +#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */ + +LOCALFUNC blnr MySound_Init(void) { + OSStatus result = noErr; + AudioComponent comp; + AudioComponentDescription desc; + struct AURenderCallbackStruct callback; + AudioStreamBasicDescription requestedDesc; + + cur_audio.fTheSoundBuffer = TheSoundBuffer; + cur_audio.fPlayOffset = &ThePlayOffset; + cur_audio.fFillOffset = &TheFillOffset; + cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs; + cur_audio.wantplaying = falseblnr; + + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_RemoteIO; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + requestedDesc.mFormatID = kAudioFormatLinearPCM; + requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked +#if 3 != kLn2SoundSampSz + | kLinearPCMFormatFlagIsSignedInteger +#endif + ; + requestedDesc.mChannelsPerFrame = 1; + requestedDesc.mSampleRate = SOUND_SAMPLERATE; + + requestedDesc.mBitsPerChannel = (1 << kLn2SoundSampSz); +#if 0 + requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; +#endif +#if 0 + requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; +#endif + + requestedDesc.mFramesPerPacket = 1; + requestedDesc.mBytesPerFrame = (requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame) >> 3; + requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket; + + callback.inputProc = audioCallback; + callback.inputProcRefCon = &cur_audio; + + if (NULL == (comp = AudioComponentFindNext(NULL, &desc))) { +#if dbglog_HAVE + dbglog_writeln( + "Failed to start CoreAudio: " + "FindNextComponent returned NULL"); +#endif + } else + + if (noErr != (result = AudioComponentInstanceNew(comp, &cur_audio.outputAudioUnit))) { +#if dbglog_HAVE + dbglog_writeln("Failed to start CoreAudio: AudioComponentInstanceNew"); +#endif + } else + + if (noErr != (result = AudioUnitInitialize(cur_audio.outputAudioUnit))) { +#if dbglog_HAVE + dbglog_writeln("Failed to start CoreAudio: AudioUnitInitialize"); +#endif + } else + + if (noErr != (result = AudioUnitSetProperty(cur_audio.outputAudioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &requestedDesc, + sizeof(requestedDesc)))) { +#if dbglog_HAVE + dbglog_writeln( + "Failed to start CoreAudio: " + "AudioUnitSetProperty(kAudioUnitProperty_StreamFormat)"); +#endif + } else + + if (noErr != (result = AudioUnitSetProperty(cur_audio.outputAudioUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)))) { +#if dbglog_HAVE + dbglog_writeln( + "Failed to start CoreAudio: " + "AudioUnitSetProperty(kAudioUnitProperty_SetInputCallback)"); +#endif + } else + + { + cur_audio.enabled = trueblnr; + + MySound_Start(); + /* + This should be taken care of by LeaveSpeedStopped, + but since takes a while to get going properly, + start early. + */ + } + + return trueblnr; /* keep going, even if no sound */ +} + +GLOBALPROC MySound_EndWrite(ui4r actL) { + if (MySound_EndWrite0(actL)) { + } +} + +LOCALPROC MySound_SecondNotify(void) { + if (cur_audio.enabled) { + MySound_SecondNotify0(); + } +} + +#endif + +#pragma mark - platform independent code can be thought of as going here + +#include "PROGMAIN.h" + +LOCALPROC ZapOSGLUVars(void) { + InitDrives(); +#if MySoundEnabled + ZapAudioVars(); +#endif +} + +LOCALPROC ReserveAllocAll(void) { +#if dbglog_HAVE + dbglog_ReserveAlloc(); +#endif + ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr); + + ReserveAllocOneBlock(&screencomparebuff, + vMacScreenNumBytes, 5, trueblnr); + +#if UseControlKeys + ReserveAllocOneBlock(&CntrlDisplayBuff, + vMacScreenNumBytes, 5, falseblnr); +#endif + +#if MySoundEnabled + ReserveAllocOneBlock((ui3p *)&TheSoundBuffer, + dbhBufferSize, 5, falseblnr); +#endif + + EmulationReserveAlloc(); +} + +LOCALFUNC blnr AllocMyMemory(void) { +#if 0 /* for testing start up error reporting */ + MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr); + return falseblnr; +#else + uimr n; + blnr IsOk = falseblnr; + + ReserveAllocOffset = 0; + ReserveAllocBigBlock = nullpr; + ReserveAllocAll(); + n = ReserveAllocOffset; + ReserveAllocBigBlock = (ui3p)calloc(1, n); + if (NULL == ReserveAllocBigBlock) { + MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr); + } else { + ReserveAllocOffset = 0; + ReserveAllocAll(); + if (n != ReserveAllocOffset) { + /* oops, program error */ + } else { + IsOk = trueblnr; + } + } + + return IsOk; +#endif +} + +LOCALPROC UnallocMyMemory(void) { + if (nullpr != ReserveAllocBigBlock) { + free((char *)ReserveAllocBigBlock); + } +} + +LOCALVAR blnr CurSpeedStopped = trueblnr; + +LOCALPROC LeaveSpeedStopped(void) { +#if MySoundEnabled + MySound_Start(); +#endif + + StartUpTimeAdjust(); +} + +LOCALPROC EnterSpeedStopped(void) { +#if MySoundEnabled + MySound_Stop(); +#endif +} + +GLOBALPROC SetSpeedStopped(blnr stopped) { + CurSpeedStopped = stopped; +} + +LOCALPROC MacMsgDisplayOn() { + if (SavedBriefMsg != nullpr) { + NSString *title = NSStringCreateFromSubstCStr(SavedBriefMsg, falseblnr); + NSString *message = NSStringCreateFromSubstCStr(SavedLongMsg, falseblnr); + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; + blnr wasStopped = CurSpeedStopped; + [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + SetSpeedStopped(wasStopped); + }]]; + SetSpeedStopped(trueblnr); + [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil]; + SavedBriefMsg = nullpr; + SavedLongMsg = nullpr; + } +} + +LOCALFUNC blnr InitOSGLU(void) { + blnr IsOk = falseblnr; + @autoreleasepool { + if (AllocMyMemory()) + if (InitCocoaStuff()) +#if dbglog_HAVE + if (dbglog_open()) +#endif +#if MySoundEnabled + if (MySound_Init()) +/* takes a while to stabilize, do as soon as possible */ +#endif + if (LoadInitialImages()) + if (LoadMacRom()) +#if UseActvCode + if (ActvCodeInit()) +#endif +#if EmLocalTalk + if (InitLocalTalk()) +#endif + if (InitLocationDat()) { + InitKeyCodes(); + IsOk = trueblnr; + } + } + + return IsOk; +} + +LOCALPROC CheckSavedMacMsg(void) { + if (nullpr != SavedBriefMsg) { + MacMsgDisplayOn(); + } +} + +LOCALPROC UnInitOSGLU(void) { +#if MySoundEnabled + MySound_Stop(); +#endif +#if MySoundEnabled + MySound_UnInit(); +#endif +#if IncludePbufs + UnInitPbufs(); +#endif + UnInitDrives(); + +#if dbglog_HAVE + dbglog_close(); +#endif + + CheckSavedMacMsg(); + UnInitCocoaStuff(); + + UnallocMyMemory(); +} + +LOCALPROC CheckForSavedTasks(void) { + if (MyEvtQNeedRecover) { + MyEvtQNeedRecover = falseblnr; + + /* attempt cleanup, MyEvtQNeedRecover may get set again */ + MyEvtQTryRecoverFromFull(); + } + + if (RequestMacOff) { + RequestMacOff = falseblnr; + ForceMacOff = trueblnr; + } + + if (ForceMacOff) { + return; + } + + if (CurSpeedStopped != SpeedStopped) { + CurSpeedStopped = !CurSpeedStopped; + if (CurSpeedStopped) { + EnterSpeedStopped(); + } else { + LeaveSpeedStopped(); + } + } + + if ((nullpr != SavedBriefMsg)) { + MacMsgDisplayOn(); + } +} + +GLOBALFUNC blnr ExtraTimeNotOver(void) { + UpdateTrueEmulatedTime(); + return TrueEmulatedTime == OnTrueTime; +} + +GLOBALPROC WaitForNextTick(void) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSDate *nextTickDate = [NSDate dateWithTimeIntervalSinceNow:1 / 60.0]; +label_retry: + [[NSRunLoop mainRunLoop] runUntilDate:nextTickDate]; + + CheckForSavedTasks(); + + if (ForceMacOff) { + goto label_exit; + } + + if (CurSpeedStopped) { + DoneWithDrawingForTick(); + } + + if (CheckDateTime()) { +#if MySoundEnabled + MySound_SecondNotify(); +#endif +#if EnableDemoMsg + DemoModeSecondNotify(); +#endif + } + + OnTrueTime = TrueEmulatedTime; + +#if dbglog_TimeStuff + dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime); +#endif + +label_exit: + [pool release]; +} + +GLOBALPROC RunEmulator(void) { + ZapOSGLUVars(); + + if (InitOSGLU()) { + ProgramMain(); + } + UnInitOSGLU(); +} diff --git a/Mini vMac/ScreenView.h b/Mini vMac/ScreenView.h new file mode 100644 index 0000000..a249212 --- /dev/null +++ b/Mini vMac/ScreenView.h @@ -0,0 +1,16 @@ +// +// ScreenView.h +// Mini vMac +// +// Created by Jesús A. Álvarez on 30/04/2016. +// Copyright © 2016 namedfork. All rights reserved. +// + +#import + +@interface ScreenView : UIView + ++ (instancetype)sharedScreenView; +- (void)updateScreen:(CGImageRef)screenImage; + +@end diff --git a/Mini vMac/ScreenView.m b/Mini vMac/ScreenView.m new file mode 100644 index 0000000..94d1101 --- /dev/null +++ b/Mini vMac/ScreenView.m @@ -0,0 +1,57 @@ +// +// ScreenView.m +// Mini vMac +// +// Created by Jesús A. Álvarez on 30/04/2016. +// Copyright © 2016 namedfork. All rights reserved. +// + +#import "ScreenView.h" +#import "CNFGGLOB.h" + +static ScreenView *sharedScreenView = nil; + +@implementation ScreenView +{ + CGImageRef screenImage; + CGRect screenBounds; +} + +- (void)awakeFromNib { + [super awakeFromNib]; + sharedScreenView = self; +} + ++ (instancetype)sharedScreenView { + return sharedScreenView; +} + +- (void)updateScreen:(CGImageRef)newScreenImage { + CGImageRelease(screenImage); + screenImage = CGImageRetain(newScreenImage); + [self setNeedsDisplay]; +} + +- (void)layoutSubviews { + CGSize screenSize = CGSizeMake(vMacScreenWidth, vMacScreenHeight); + CGRect viewBounds = self.bounds; + CGFloat screenScale = MAX(screenSize.width / viewBounds.size.width, screenSize.height / viewBounds.size.height); + screenBounds = CGRectMake(0, 0, screenSize.width / screenScale, screenSize.height / screenScale); + screenBounds.origin.x = (viewBounds.size.width - screenBounds.size.width)/2; + screenBounds = CGRectIntegral(screenBounds); + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + // Draw screenImage + CGImageRef imageRef = CGImageRetain(screenImage); + if (imageRef) { + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextTranslateCTM(ctx, 0, screenBounds.size.height); + CGContextScaleCTM(ctx, 1.0, -1.0); + CGContextDrawImage(ctx, screenBounds, imageRef); + CGImageRelease(imageRef); + } +} + +@end diff --git a/Mini vMac/ViewController.m b/Mini vMac/ViewController.m index 0717860..058f670 100644 --- a/Mini vMac/ViewController.m +++ b/Mini vMac/ViewController.m @@ -14,14 +14,8 @@ @implementation ViewController -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view, typically from a nib. -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. +- (BOOL)prefersStatusBarHidden { + return YES; } @end diff --git a/Mini vMac/mnvm_cfg/CNFGGLOB.h b/Mini vMac/mnvm_cfg/CNFGGLOB.h new file mode 100644 index 0000000..fa4ca3d --- /dev/null +++ b/Mini vMac/mnvm_cfg/CNFGGLOB.h @@ -0,0 +1,92 @@ +/* + Configuration options used by both platform specific + and platform independent code. + + This file is automatically generated by the build system, + which tries to know what options are valid in what + combinations. Avoid changing this file manually unless + you know what you're doing. +*/ + +#include + +#define BigEndianUnaligned 0 +#define LittleEndianUnaligned 1 +#define MayInline inline +#define MayNotInline __attribute__((noinline)) +#define SmallGlobals 0 +#define cIncludeUnused 0 +#define UnusedParam(p) (void) p + +/* --- integer types ---- */ + +typedef uint8_t ui3b; +#define HaveRealui3b 1 + +typedef int8_t si3b; +#define HaveRealsi3b 1 + +typedef uint16_t ui4b; +#define HaveRealui4b 1 + +typedef int16_t si4b; +#define HaveRealsi4b 1 + +typedef uint32_t ui5b; +#define HaveRealui5b 1 + +typedef int32_t si5b; +#define HaveRealsi5b 1 + +#define HaveRealui6b 0 +#define HaveRealsi6b 0 + +/* --- integer representation types ---- */ + +typedef ui3b ui3r; +#define ui3beqr 1 + +typedef si3b si3r; +#define si3beqr 1 + +typedef ui4b ui4r; +#define ui4beqr 1 + +typedef si4b si4r; +#define si4beqr 1 + +typedef ui5b ui5r; +#define ui5beqr 1 + +typedef si5b si5r; +#define si5beqr 1 + +/* capabilities provided by platform specific code */ + +#define MySoundEnabled 1 + +#define MySoundRecenterSilence 0 +#define kLn2SoundSampSz 4 + +#define dbglog_HAVE 0 + +#define NumDrives 16 +#define IncludeSonyRawMode 1 +#define IncludeSonyGetName 1 +#define IncludeSonyNew 0 +#define IncludeSonyNameNew 0 + +#define vMacScreenHeight 342 +#define vMacScreenWidth 512 +#define vMacScreenDepth 0 + +#define kROM_Size 0x00020000 + +#define IncludePbufs 1 +#define NumPbufs 4 + +#define EnableMouseMotion 1 + +#define IncludeHostTextClipExchange 1 +#define EnableAutoSlow 1 +#define EmLocalTalk 0 diff --git a/Mini vMac/mnvm_cfg/CNFGRAPI.h b/Mini vMac/mnvm_cfg/CNFGRAPI.h new file mode 100644 index 0000000..273e980 --- /dev/null +++ b/Mini vMac/mnvm_cfg/CNFGRAPI.h @@ -0,0 +1,35 @@ +//#include +//#include +#include + +#define MyAppIsBundle 1 +#define kMacCreatorSig 'MnvM' + +#define RomFileName "vMac.ROM" +#define EnableDragDrop 1 +#define EnableAltKeysMode 0 +#define SwapCommandControl 0 +#define VarFullScreen 1 +#define WantInitFullScreen 0 +#define MayFullScreen 1 +#define MayNotFullScreen 1 +#define WantInitMagnify 0 +#define EnableMagnify 0 +#define WantInitRunInBackground 0 +#define WantInitNotAutoSlow 0 +#define WantInitSpeedValue 3 +#define NeedRequestInsertDisk 1 +#define NeedDoMoreCommandsMsg 1 +#define NeedDoAboutMsg 1 +#define UseControlKeys 0 +#define UseActvCode 0 +#define EnableDemoMsg 0 + +/* version and other info to display to user */ + +#define NeedIntlChars 1 +#define kStrAppName "Mini vMac" +#define kAppVariationStr "minivmac-3.4.0-ios" +#define kStrCopyrightYear "2008-2016" +#define kMaintainerName "Jesús A. Álvarez" +#define kStrHomePage "http://www.namedfork.net/minivmac/" diff --git a/Mini vMac/mnvm_cfg/EMCONFIG.h b/Mini vMac/mnvm_cfg/EMCONFIG.h new file mode 100644 index 0000000..fff44e3 --- /dev/null +++ b/Mini vMac/mnvm_cfg/EMCONFIG.h @@ -0,0 +1,172 @@ +/* + Configuration options used by platform independent code. + + This file is automatically generated by the build system, + which tries to know what options are valid in what + combinations. Avoid changing this file manually unless + you know what you're doing. +*/ + +#define EmClassicKbrd 1 +#define EmADB 0 +#define EmRTC 1 +#define EmPMU 0 +#define EmVIA2 0 +#define Use68020 0 +#define EmFPU 0 +#define EmMMU 0 +#define EmASC 0 + +#define CurEmMd kEmMd_Plus + +#define kMyClockMult 1 + +#define WantCycByPriOp 1 +#define WantCloserCyc 0 + +#define kRAMa_Size 0x00200000 +#define kRAMb_Size 0x00200000 + +#define IncludeVidMem 0 + +#define EmVidCard 0 + +#define MaxATTListN 16 +#define IncludeExtnPbufs 1 +#define IncludeExtnHostTextClipExchange 1 + +#define Sony_SupportDC42 1 +#define Sony_SupportTags 1 +#define Sony_WantChecksumsUpdated 1 +#define Sony_VerifyChecksums 0 +#define CaretBlinkTime 0x03 +#define SpeakerVol 0x07 +#define DoubleClickTime 0x05 +#define MenuBlink 0x03 +#define AutoKeyThresh 0x06 +#define AutoKeyRate 0x03 + + +/* the Wire variables are 1/0, not true/false */ + +enum { + + Wire_VIA1_iA0_SoundVolb0, +#define SoundVolb0 (Wires[Wire_VIA1_iA0_SoundVolb0]) +#define VIA1_iA0 (Wires[Wire_VIA1_iA0_SoundVolb0]) + + Wire_VIA1_iA1_SoundVolb1, +#define SoundVolb1 (Wires[Wire_VIA1_iA1_SoundVolb1]) +#define VIA1_iA1 (Wires[Wire_VIA1_iA1_SoundVolb1]) + + Wire_VIA1_iA2_SoundVolb2, +#define SoundVolb2 (Wires[Wire_VIA1_iA2_SoundVolb2]) +#define VIA1_iA2 (Wires[Wire_VIA1_iA2_SoundVolb2]) + + Wire_VIA1_iA4_MemOverlay, +#define MemOverlay (Wires[Wire_VIA1_iA4_MemOverlay]) +#define VIA1_iA4 (Wires[Wire_VIA1_iA4_MemOverlay]) +#define VIA1_iA4_ChangeNtfy MemOverlay_ChangeNtfy + + Wire_VIA1_iA6_SCRNvPage2, +#define SCRNvPage2 (Wires[Wire_VIA1_iA6_SCRNvPage2]) +#define VIA1_iA6 (Wires[Wire_VIA1_iA6_SCRNvPage2]) + + Wire_VIA1_iA5_IWMvSel, +#define IWMvSel (Wires[Wire_VIA1_iA5_IWMvSel]) +#define VIA1_iA5 (Wires[Wire_VIA1_iA5_IWMvSel]) + + Wire_VIA1_iA7_SCCwaitrq, +#define SCCwaitrq (Wires[Wire_VIA1_iA7_SCCwaitrq]) +#define VIA1_iA7 (Wires[Wire_VIA1_iA7_SCCwaitrq]) + + Wire_VIA1_iB0_RTCdataLine, +#define RTCdataLine (Wires[Wire_VIA1_iB0_RTCdataLine]) +#define VIA1_iB0 (Wires[Wire_VIA1_iB0_RTCdataLine]) +#define VIA1_iB0_ChangeNtfy RTCdataLine_ChangeNtfy + + Wire_VIA1_iB1_RTCclock, +#define RTCclock (Wires[Wire_VIA1_iB1_RTCclock]) +#define VIA1_iB1 (Wires[Wire_VIA1_iB1_RTCclock]) +#define VIA1_iB1_ChangeNtfy RTCclock_ChangeNtfy + + Wire_VIA1_iB2_RTCunEnabled, +#define RTCunEnabled (Wires[Wire_VIA1_iB2_RTCunEnabled]) +#define VIA1_iB2 (Wires[Wire_VIA1_iB2_RTCunEnabled]) +#define VIA1_iB2_ChangeNtfy RTCunEnabled_ChangeNtfy + + Wire_VIA1_iA3_SoundBuffer, +#define SoundBuffer (Wires[Wire_VIA1_iA3_SoundBuffer]) +#define VIA1_iA3 (Wires[Wire_VIA1_iA3_SoundBuffer]) + + Wire_VIA1_iB3_MouseBtnUp, +#define MouseBtnUp (Wires[Wire_VIA1_iB3_MouseBtnUp]) +#define VIA1_iB3 (Wires[Wire_VIA1_iB3_MouseBtnUp]) + + Wire_VIA1_iB4_MouseX2, +#define MouseX2 (Wires[Wire_VIA1_iB4_MouseX2]) +#define VIA1_iB4 (Wires[Wire_VIA1_iB4_MouseX2]) + + Wire_VIA1_iB5_MouseY2, +#define MouseY2 (Wires[Wire_VIA1_iB5_MouseY2]) +#define VIA1_iB5 (Wires[Wire_VIA1_iB5_MouseY2]) + + Wire_VIA1_iCB2_KybdDat, +#define VIA1_iCB2 (Wires[Wire_VIA1_iCB2_KybdDat]) +#define VIA1_iCB2_ChangeNtfy Kybd_DataLineChngNtfy + + Wire_VIA1_iB6_SCRNbeamInVid, +#define SCRNbeamInVid (Wires[Wire_VIA1_iB6_SCRNbeamInVid]) +#define VIA1_iB6 (Wires[Wire_VIA1_iB6_SCRNbeamInVid]) + + Wire_VIA1_iB7_SoundDisable, +#define SoundDisable (Wires[Wire_VIA1_iB7_SoundDisable]) +#define VIA1_iB7 (Wires[Wire_VIA1_iB7_SoundDisable]) + + Wire_VIA1_InterruptRequest, +#define VIA1_InterruptRequest (Wires[Wire_VIA1_InterruptRequest]) +#define VIA1_interruptChngNtfy VIAorSCCinterruptChngNtfy + + Wire_SCCInterruptRequest, +#define SCCInterruptRequest (Wires[Wire_SCCInterruptRequest]) +#define SCCinterruptChngNtfy VIAorSCCinterruptChngNtfy + + kNumWires +}; + + +/* VIA configuration */ +#define VIA1_ORA_FloatVal 0xFF +#define VIA1_ORB_FloatVal 0xFF +#define VIA1_ORA_CanIn 0x80 +#define VIA1_ORA_CanOut 0x7F +#define VIA1_ORB_CanIn 0x79 +#define VIA1_ORB_CanOut 0x87 +#define VIA1_IER_Never0 (1 << 1) +#define VIA1_IER_Never1 ((1 << 3) | (1 << 4)) +#define VIA1_CB2modesAllowed 0x01 +#define VIA1_CA2modesAllowed 0x01 + +#define Mouse_Enabled SCC_InterruptsEnabled + +#define VIA1_iCA1_PulseNtfy VIA1_iCA1_Sixtieth_PulseNtfy +#define Sixtieth_PulseNtfy VIA1_iCA1_Sixtieth_PulseNtfy + +#define VIA1_iCA2_PulseNtfy VIA1_iCA2_RTC_OneSecond_PulseNtfy +#define RTC_OneSecond_PulseNtfy VIA1_iCA2_RTC_OneSecond_PulseNtfy + +#define GetSoundInvertTime VIA1_GetT1InvertTime + +#define KYBD_ShiftInData VIA1_ShiftOutData +#define KYBD_ShiftOutData VIA1_ShiftInData + +#define kCheckSumRom_Size kROM_Size + +#define kExtn_Block_Base 0x00F40000 +#define kExtn_ln2Spc 5 + +#define kROM_Base 0x00400000 +#define kROM_ln2Spc 20 + +#define WantDisasm 0 +#define ExtraAbnormalReports 0 diff --git a/Mini vMac/mnvm_core/COMOSGLU.h b/Mini vMac/mnvm_core/COMOSGLU.h new file mode 100755 index 0000000..c07fb85 --- /dev/null +++ b/Mini vMac/mnvm_core/COMOSGLU.h @@ -0,0 +1 @@ +/* COMOSGLU.h Copyright (C) 2009 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* COMmon code for Operating System GLUe */ GLOBALVAR ui3p ROM = nullpr; GLOBALVAR ui5b vSonyWritableMask = 0; GLOBALVAR ui5b vSonyInsertedMask = 0; #if IncludeSonyRawMode GLOBALVAR blnr vSonyRawMode = falseblnr; #endif #if IncludeSonyNew GLOBALVAR blnr vSonyNewDiskWanted = falseblnr; GLOBALVAR ui5b vSonyNewDiskSize; #endif #if IncludeSonyNameNew GLOBALVAR tPbuf vSonyNewDiskName = NotAPbuf; #endif GLOBALVAR ui5b CurMacDateInSeconds = 0; GLOBALVAR ui5b CurMacLatitude = 0; GLOBALVAR ui5b CurMacLongitude = 0; GLOBALVAR ui5b CurMacDelta = 0; #if 0 != vMacScreenDepth GLOBALVAR blnr UseColorMode = falseblnr; GLOBALVAR blnr ColorModeWorks = falseblnr; #endif #if 0 != vMacScreenDepth GLOBALVAR blnr ColorMappingChanged = falseblnr; #endif #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) GLOBALVAR ui4r CLUT_reds[CLUT_size]; GLOBALVAR ui4r CLUT_greens[CLUT_size]; GLOBALVAR ui4r CLUT_blues[CLUT_size]; #endif LOCALVAR blnr RequestMacOff = falseblnr; GLOBALVAR blnr ForceMacOff = falseblnr; GLOBALVAR blnr WantMacInterrupt = falseblnr; GLOBALVAR blnr WantMacReset = falseblnr; GLOBALVAR ui3b SpeedValue = WantInitSpeedValue; #if EnableAutoSlow GLOBALVAR blnr WantNotAutoSlow = (WantInitNotAutoSlow != 0); #endif GLOBALVAR ui4b CurMouseV = 0; GLOBALVAR ui4b CurMouseH = 0; #if EnableMouseMotion && MayFullScreen LOCALVAR blnr HaveMouseMotion = falseblnr; #endif #if EnableAutoSlow GLOBALVAR ui5r QuietTime = 0; GLOBALVAR ui5r QuietSubTicks = 0; #endif #if IncludePbufs LOCALVAR ui5b PbufAllocatedMask; LOCALVAR ui5b PbufSize[NumPbufs]; #endif #if IncludePbufs #define PbufIsAllocated(i) ((PbufAllocatedMask & ((ui5b)1 << (i))) != 0) #endif #if IncludePbufs LOCALFUNC blnr FirstFreePbuf(tPbuf *r) { tPbuf i; for (i = 0; i < NumPbufs; ++i) { if (! PbufIsAllocated(i)) { *r = i; return trueblnr; } } return falseblnr; } #endif #if IncludePbufs LOCALPROC PbufNewNotify(tPbuf Pbuf_No, ui5b count) { PbufSize[Pbuf_No] = count; PbufAllocatedMask |= ((ui5b)1 << Pbuf_No); } #endif #if IncludePbufs LOCALPROC PbufDisposeNotify(tPbuf Pbuf_No) { PbufAllocatedMask &= ~ ((ui5b)1 << Pbuf_No); } #endif #if IncludePbufs GLOBALFUNC tMacErr CheckPbuf(tPbuf Pbuf_No) { tMacErr result; if (Pbuf_No >= NumPbufs) { result = mnvm_nsDrvErr; } else if (! PbufIsAllocated(Pbuf_No)) { result = mnvm_offLinErr; } else { result = mnvm_noErr; } return result; } #endif #if IncludePbufs GLOBALFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count) { tMacErr result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { *Count = PbufSize[Pbuf_No]; } return result; } #endif LOCALFUNC blnr FirstFreeDisk(tDrive *Drive_No) { tDrive i; for (i = 0; i < NumDrives; ++i) { if (! vSonyIsInserted(i)) { *Drive_No = i; return trueblnr; } } return falseblnr; } GLOBALFUNC blnr AnyDiskInserted(void) { #if 0 tDrive i; for (i = 0; i < NumDrives; ++i) { if (vSonyIsInserted(i)) { return trueblnr; } } return falseblnr; #endif return 0 != vSonyInsertedMask; } GLOBALPROC DiskRevokeWritable(tDrive Drive_No) { vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); } LOCALPROC DiskInsertNotify(tDrive Drive_No, blnr locked) { vSonyInsertedMask |= ((ui5b)1 << Drive_No); if (! locked) { vSonyWritableMask |= ((ui5b)1 << Drive_No); } QuietEnds(); } LOCALPROC DiskEjectedNotify(tDrive Drive_No) { vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); vSonyInsertedMask &= ~ ((ui5b)1 << Drive_No); } /* block type - for operating on multiple ui3b elements at a time. */ #if LittleEndianUnaligned || BigEndianUnaligned #define uibb ui5b #define uibr ui5r #define ln2uiblockn 2 #if 0 #define uibb long long #define uibr long long #define ln2uiblockn 3 #endif #else #define uibb ui3b #define uibr ui3r #define ln2uiblockn 0 #endif #define uiblockn (1 << ln2uiblockn) #define ln2uiblockbitsn (3 + ln2uiblockn) #define uiblockbitsn (8 * uiblockn) LOCALFUNC blnr FindFirstChangeInLVecs(uibb *ptr1, uibb *ptr2, uimr L, uimr *j) { /* find index of first difference */ uibb *p1 = ptr1; uibb *p2 = ptr2; uimr i; for (i = L; i != 0; --i) { if (*p1++ != *p2++) { --p1; *j = p1 - ptr1; return trueblnr; } } return falseblnr; } LOCALPROC FindLastChangeInLVecs(uibb *ptr1, uibb *ptr2, uimr L, uimr *j) { /* find index of last difference, assuming there is one */ uibb *p1 = ptr1 + L; uibb *p2 = ptr2 + L; while (*--p1 == *--p2) { } *j = p1 - ptr1; } LOCALPROC FindLeftRightChangeInLMat(uibb *ptr1, uibb *ptr2, uimr width, uimr top, uimr bottom, uimr *LeftMin0, uibr *LeftMask0, uimr *RightMax0, uibr *RightMask0) { uimr i; uimr j; uibb *p1; uibb *p2; uibr x; ui5r offset = top * width; uibb *p10 = (uibb *)ptr1 + offset; uibb *p20 = (uibb *)ptr2 + offset; uimr LeftMin = *LeftMin0; uimr RightMax = *RightMax0; uibr LeftMask = 0; uibr RightMask = 0; for (i = top; i < bottom; ++i) { p1 = p10; p2 = p20; for (j = 0; j < LeftMin; ++j) { x = *p1++ ^ *p2++; if (0 != x) { LeftMin = j; LeftMask = x; goto Label_3; } } LeftMask |= (*p1 ^ *p2); Label_3: p1 = p10 + RightMax; p2 = p20 + RightMax; RightMask |= (*p1++ ^ *p2++); for (j = RightMax + 1; j < width; ++j) { x = *p1++ ^ *p2++; if (0 != x) { RightMax = j; RightMask = x; } } p10 += width; p20 += width; } *LeftMin0 = LeftMin; *RightMax0 = RightMax; *LeftMask0 = LeftMask; *RightMask0 = RightMask; } LOCALVAR ui3p screencomparebuff = nullpr; LOCALVAR uimr NextDrawRow = 0; #if BigEndianUnaligned #define FlipCheckMonoBits (uiblockbitsn - 1) #else #define FlipCheckMonoBits 7 #endif #define FlipCheckBits (FlipCheckMonoBits >> vMacScreenDepth) #ifndef WantColorTransValid #define WantColorTransValid 0 #endif #if WantColorTransValid LOCALVAR blnr ColorTransValid = falseblnr; #endif LOCALFUNC blnr ScreenFindChanges(ui3p screencurrentbuff, si3b TimeAdjust, si4b *top, si4b *left, si4b *bottom, si4b *right) { uimr j0; uimr j1; uimr j0h; uimr j1h; uimr j0v; uimr j1v; uimr copysize; uimr copyoffset; uimr copyrows; uimr LimitDrawRow; uimr MaxRowsDrawnPerTick; uimr LeftMin; uimr RightMax; uibr LeftMask; uibr RightMask; int j; if (TimeAdjust < 4) { MaxRowsDrawnPerTick = vMacScreenHeight; } else if (TimeAdjust < 6) { MaxRowsDrawnPerTick = vMacScreenHeight / 2; } else { MaxRowsDrawnPerTick = vMacScreenHeight / 4; } #if 0 != vMacScreenDepth if (UseColorMode) { if (ColorMappingChanged) { ColorMappingChanged = falseblnr; j0h = 0; j1h = vMacScreenWidth; j0v = 0; j1v = vMacScreenHeight; #if WantColorTransValid ColorTransValid = falseblnr; #endif } else { if (! FindFirstChangeInLVecs( (uibb *)screencurrentbuff + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), (uibb *)screencomparebuff + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), ((uimr)(vMacScreenHeight - NextDrawRow) * (uimr)vMacScreenBitWidth) / uiblockbitsn, &j0)) { NextDrawRow = 0; return falseblnr; } j0v = j0 / (vMacScreenBitWidth / uiblockbitsn); j0h = j0 - j0v * (vMacScreenBitWidth / uiblockbitsn); j0v += NextDrawRow; LimitDrawRow = j0v + MaxRowsDrawnPerTick; if (LimitDrawRow >= vMacScreenHeight) { LimitDrawRow = vMacScreenHeight; NextDrawRow = 0; } else { NextDrawRow = LimitDrawRow; } FindLastChangeInLVecs((uibb *)screencurrentbuff, (uibb *)screencomparebuff, ((uimr)LimitDrawRow * (uimr)vMacScreenBitWidth) / uiblockbitsn, &j1); j1v = j1 / (vMacScreenBitWidth / uiblockbitsn); j1h = j1 - j1v * (vMacScreenBitWidth / uiblockbitsn); j1v++; if (j0h < j1h) { LeftMin = j0h; RightMax = j1h; } else { LeftMin = j1h; RightMax = j0h; } FindLeftRightChangeInLMat((uibb *)screencurrentbuff, (uibb *)screencomparebuff, (vMacScreenBitWidth / uiblockbitsn), j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); #if vMacScreenDepth > ln2uiblockbitsn j0h = (LeftMin >> (vMacScreenDepth - ln2uiblockbitsn)); #elif ln2uiblockbitsn > vMacScreenDepth for (j = 0; j < (1 << (ln2uiblockbitsn - vMacScreenDepth)); ++j) { if (0 != (LeftMask & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) << ((j ^ FlipCheckBits) << vMacScreenDepth)))) { goto Label_1c; } } Label_1c: j0h = (LeftMin << (ln2uiblockbitsn - vMacScreenDepth)) + j; #else j0h = LeftMin; #endif #if vMacScreenDepth > ln2uiblockbitsn j1h = (RightMax >> (vMacScreenDepth - ln2uiblockbitsn)) + 1; #elif ln2uiblockbitsn > vMacScreenDepth for (j = (uiblockbitsn >> vMacScreenDepth); --j >= 0; ) { if (0 != (RightMask & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) << ((j ^ FlipCheckBits) << vMacScreenDepth)))) { goto Label_2c; } } Label_2c: j1h = (RightMax << (ln2uiblockbitsn - vMacScreenDepth)) + j + 1; #else j1h = RightMax + 1; #endif } copyrows = j1v - j0v; copyoffset = j0v * vMacScreenByteWidth; copysize = copyrows * vMacScreenByteWidth; } else #endif { #if 0 != vMacScreenDepth if (ColorMappingChanged) { ColorMappingChanged = falseblnr; j0h = 0; j1h = vMacScreenWidth; j0v = 0; j1v = vMacScreenHeight; #if WantColorTransValid ColorTransValid = falseblnr; #endif } else #endif { if (! FindFirstChangeInLVecs( (uibb *)screencurrentbuff + NextDrawRow * (vMacScreenWidth / uiblockbitsn), (uibb *)screencomparebuff + NextDrawRow * (vMacScreenWidth / uiblockbitsn), ((uimr)(vMacScreenHeight - NextDrawRow) * (uimr)vMacScreenWidth) / uiblockbitsn, &j0)) { NextDrawRow = 0; return falseblnr; } j0v = j0 / (vMacScreenWidth / uiblockbitsn); j0h = j0 - j0v * (vMacScreenWidth / uiblockbitsn); j0v += NextDrawRow; LimitDrawRow = j0v + MaxRowsDrawnPerTick; if (LimitDrawRow >= vMacScreenHeight) { LimitDrawRow = vMacScreenHeight; NextDrawRow = 0; } else { NextDrawRow = LimitDrawRow; } FindLastChangeInLVecs((uibb *)screencurrentbuff, (uibb *)screencomparebuff, ((uimr)LimitDrawRow * (uimr)vMacScreenWidth) / uiblockbitsn, &j1); j1v = j1 / (vMacScreenWidth / uiblockbitsn); j1h = j1 - j1v * (vMacScreenWidth / uiblockbitsn); j1v++; if (j0h < j1h) { LeftMin = j0h; RightMax = j1h; } else { LeftMin = j1h; RightMax = j0h; } FindLeftRightChangeInLMat((uibb *)screencurrentbuff, (uibb *)screencomparebuff, (vMacScreenWidth / uiblockbitsn), j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); for (j = 0; j < uiblockbitsn; ++j) { if (0 != (LeftMask & (((uibr)1) << (j ^ FlipCheckMonoBits)))) { goto Label_1; } } Label_1: j0h = LeftMin * uiblockbitsn + j; for (j = uiblockbitsn; --j >= 0; ) { if (0 != (RightMask & (((uibr)1) << (j ^ FlipCheckMonoBits)))) { goto Label_2; } } Label_2: j1h = RightMax * uiblockbitsn + j + 1; } copyrows = j1v - j0v; copyoffset = j0v * vMacScreenMonoByteWidth; copysize = copyrows * vMacScreenMonoByteWidth; } MyMoveBytes((anyp)screencurrentbuff + copyoffset, (anyp)screencomparebuff + copyoffset, copysize); *top = j0v; *left = j0h; *bottom = j1v; *right = j1h; return trueblnr; } GLOBALVAR blnr EmVideoDisable = falseblnr; GLOBALVAR si3b EmLagTime = 0; GLOBALVAR ui5b OnTrueTime = 0; /* The time slice we are currently dealing with, in the same units as TrueEmulatedTime. */ LOCALVAR si4b ScreenChangedTop; LOCALVAR si4b ScreenChangedLeft; LOCALVAR si4b ScreenChangedBottom; LOCALVAR si4b ScreenChangedRight; LOCALPROC ScreenClearChanges(void) { ScreenChangedTop = vMacScreenHeight; ScreenChangedBottom = 0; ScreenChangedLeft = vMacScreenWidth; ScreenChangedRight = 0; } LOCALPROC ScreenChangedAll(void) { ScreenChangedTop = 0; ScreenChangedBottom = vMacScreenHeight; ScreenChangedLeft = 0; ScreenChangedRight = vMacScreenWidth; } #if EnableAutoSlow LOCALVAR si4b ScreenChangedQuietTop = vMacScreenHeight; LOCALVAR si4b ScreenChangedQuietLeft = vMacScreenWidth; LOCALVAR si4b ScreenChangedQuietBottom = 0; LOCALVAR si4b ScreenChangedQuietRight = 0; #endif GLOBALPROC Screen_OutputFrame(ui3p screencurrentbuff) { si4b top; si4b left; si4b bottom; si4b right; if (! EmVideoDisable) { if (ScreenFindChanges(screencurrentbuff, EmLagTime, &top, &left, &bottom, &right)) { if (top < ScreenChangedTop) { ScreenChangedTop = top; } if (bottom > ScreenChangedBottom) { ScreenChangedBottom = bottom; } if (left < ScreenChangedLeft) { ScreenChangedLeft = left; } if (right > ScreenChangedRight) { ScreenChangedRight = right; } #if EnableAutoSlow if (top < ScreenChangedQuietTop) { ScreenChangedQuietTop = top; } if (bottom > ScreenChangedQuietBottom) { ScreenChangedQuietBottom = bottom; } if (left < ScreenChangedQuietLeft) { ScreenChangedQuietLeft = left; } if (right > ScreenChangedQuietRight) { ScreenChangedQuietRight = right; } if (((ScreenChangedQuietRight - ScreenChangedQuietLeft) > 1) || ((ScreenChangedQuietBottom - ScreenChangedQuietTop) > 32)) { ScreenChangedQuietTop = vMacScreenHeight; ScreenChangedQuietLeft = vMacScreenWidth; ScreenChangedQuietBottom = 0; ScreenChangedQuietRight = 0; QuietEnds(); } #endif } } } #if MayFullScreen LOCALVAR ui4r ViewHSize; LOCALVAR ui4r ViewVSize; LOCALVAR ui4r ViewHStart = 0; LOCALVAR ui4r ViewVStart = 0; #if EnableMouseMotion LOCALVAR si4b SavedMouseH; LOCALVAR si4b SavedMouseV; #endif #endif #ifndef WantAutoScrollBorder #define WantAutoScrollBorder 0 #endif #if EnableMouseMotion && MayFullScreen LOCALPROC AutoScrollScreen(void) { si4b Shift; si4b Limit; /* Scroll in multiples of two pixels, so as to work better with the common gray pattern. ViewHSize and ViewVSize are constrained to a multiple of two. Mac OS (some versions at least) constrains the mouse position to be less than the screen height and width, not allowing equal to it. Can still scroll to see last pixel because scroll in multiples of two pixels. */ if (vMacScreenWidth != ViewHSize) { Shift = 0; Limit = ViewHStart #if WantAutoScrollBorder + (ViewHSize / 16) #endif ; if (CurMouseH < Limit) { Shift = (Limit - CurMouseH + 1) & (~ 1); Limit = ViewHStart; if (Shift >= Limit) { Shift = Limit; } Shift = - Shift; } else { Limit = ViewHStart + ViewHSize #if WantAutoScrollBorder - (ViewHSize / 16) #endif ; if (CurMouseH > Limit) { Shift = (CurMouseH - Limit + 1) & (~ 1); Limit = vMacScreenWidth - ViewHSize - ViewHStart; if (Shift >= Limit) { Shift = Limit; } } } if (Shift != 0) { ViewHStart += Shift; SavedMouseH += Shift; ScreenChangedAll(); } } if (vMacScreenHeight != ViewVSize) { Shift = 0; Limit = ViewVStart #if WantAutoScrollBorder + (ViewVSize / 16) #endif ; if (CurMouseV < Limit) { Shift = (Limit - CurMouseV + 1) & (~ 1); Limit = ViewVStart; if (Shift >= Limit) { Shift = Limit; } Shift = - Shift; } else { Limit = ViewVStart + ViewVSize #if WantAutoScrollBorder - (ViewVSize / 16) #endif ; if (CurMouseV > Limit) { Shift = (CurMouseV - Limit + 1) & (~ 1); Limit = vMacScreenHeight - ViewVSize - ViewVStart; if (Shift >= Limit) { Shift = Limit; } } } if (Shift != 0) { ViewVStart += Shift; SavedMouseV += Shift; ScreenChangedAll(); } } } #endif LOCALPROC SetLongs(ui5b *p, long n) { long i; for (i = n; --i >= 0; ) { *p++ = (ui5b) -1; } } LOCALVAR uimr ReserveAllocOffset; LOCALVAR ui3p ReserveAllocBigBlock = nullpr; #define PowOf2(p) ((uimr)1 << (p)) #define Pow2Mask(p) (PowOf2(p) - 1) #define ModPow2(i, p) ((i) & Pow2Mask(p)) #define FloorDivPow2(i, p) ((i) >> (p)) #define FloorPow2Mult(i, p) ((i) & (~ Pow2Mask(p))) #define CeilPow2Mult(i, p) FloorPow2Mult((i) + Pow2Mask(p), (p)) /* warning - CeilPow2Mult evaluates p twice */ GLOBALPROC ReserveAllocOneBlock(ui3p *p, uimr n, ui3r align, blnr FillOnes) { ReserveAllocOffset = CeilPow2Mult(ReserveAllocOffset, align); if (nullpr == ReserveAllocBigBlock) { *p = nullpr; } else { *p = ReserveAllocBigBlock + ReserveAllocOffset; if (FillOnes) { SetLongs((ui5b *)*p, n / 4); } } ReserveAllocOffset += n; } /* --- sending debugging info to file --- */ #if dbglog_HAVE #define dbglog_bufsz PowOf2(dbglog_buflnsz) LOCALVAR uimr dbglog_bufpos = 0; LOCALVAR char *dbglog_bufp = nullpr; LOCALPROC dbglog_ReserveAlloc(void) { ReserveAllocOneBlock((ui3p *)&dbglog_bufp, dbglog_bufsz, 5, falseblnr); } #define dbglog_open dbglog_open0 LOCALPROC dbglog_close(void) { uimr n = ModPow2(dbglog_bufpos, dbglog_buflnsz); if (n != 0) { dbglog_write0(dbglog_bufp, n); } dbglog_close0(); } LOCALPROC dbglog_write(char *p, uimr L) { uimr r; uimr bufposmod; uimr curbufdiv; uimr newbufpos = dbglog_bufpos + L; uimr newbufdiv = FloorDivPow2(newbufpos, dbglog_buflnsz); label_retry: curbufdiv = FloorDivPow2(dbglog_bufpos, dbglog_buflnsz); bufposmod = ModPow2(dbglog_bufpos, dbglog_buflnsz); if (newbufdiv != curbufdiv) { r = dbglog_bufsz - bufposmod; MyMoveBytes((anyp)p, (anyp)(dbglog_bufp + bufposmod), r); dbglog_write0(dbglog_bufp, dbglog_bufsz); L -= r; p += r; dbglog_bufpos += r; goto label_retry; } MyMoveBytes((anyp)p, (anyp)dbglog_bufp + bufposmod, L); dbglog_bufpos = newbufpos; } LOCALFUNC uimr CStrLength(char *s) { char *p = s; while (*p++ != 0) { } return p - s - 1; } GLOBALPROC dbglog_writeCStr(char *s) { /* fprintf(DumpFile, "%s", s); */ dbglog_write(s, CStrLength(s)); } GLOBALPROC dbglog_writeReturn(void) { dbglog_writeCStr("\n"); /* fprintf(DumpFile, "\n"); */ } GLOBALPROC dbglog_writeHex(uimr x) { ui3r v; char s[16]; char *p = s + 16; uimr n = 0; do { v = x & 0x0F; if (v < 10) { *--p = '0' + v; } else { *--p = 'A' + v - 10; } x >>= 4; ++n; } while (x != 0); dbglog_write(p, n); /* fprintf(DumpFile, "%d", (int)x); */ } GLOBALPROC dbglog_writeNum(uimr x) { uimr newx; char s[16]; char *p = s + 16; uimr n = 0; do { newx = x / (uimr)10; *--p = '0' + (x - newx * 10); x = newx; ++n; } while (x != 0); dbglog_write(p, n); /* fprintf(DumpFile, "%d", (int)x); */ } GLOBALPROC dbglog_writeMacChar(ui3r x) { char s; if ((x > 32) && (x < 127)) { s = x; } else { s = '?'; } dbglog_write(&s, 1); } LOCALPROC dbglog_writeSpace(void) { dbglog_writeCStr(" "); } GLOBALPROC dbglog_writeln(char *s) { dbglog_writeCStr(s); dbglog_writeReturn(); } GLOBALPROC dbglog_writelnNum(char *s, simr v) { dbglog_writeCStr(s); dbglog_writeSpace(); dbglog_writeNum(v); dbglog_writeReturn(); } #endif /* my event queue */ #define MyEvtQLg2Sz 4 #define MyEvtQSz (1 << MyEvtQLg2Sz) #define MyEvtQIMask (MyEvtQSz - 1) LOCALVAR MyEvtQEl MyEvtQA[MyEvtQSz]; LOCALVAR ui4r MyEvtQIn = 0; LOCALVAR ui4r MyEvtQOut = 0; GLOBALFUNC MyEvtQEl * MyEvtQOutP(void) { MyEvtQEl *p = nullpr; if (MyEvtQIn != MyEvtQOut) { p = &MyEvtQA[MyEvtQOut & MyEvtQIMask]; } return p; } GLOBALPROC MyEvtQOutDone(void) { ++MyEvtQOut; } LOCALVAR blnr MyEvtQNeedRecover = falseblnr; /* events lost because of full queue */ LOCALFUNC MyEvtQEl * MyEvtQElPreviousIn(void) { MyEvtQEl *p = NULL; if (MyEvtQIn - MyEvtQOut != 0) { p = &MyEvtQA[(MyEvtQIn - 1) & MyEvtQIMask]; } return p; } LOCALFUNC MyEvtQEl * MyEvtQElAlloc(void) { MyEvtQEl *p = NULL; if (MyEvtQIn - MyEvtQOut >= MyEvtQSz) { MyEvtQNeedRecover = trueblnr; } else { p = &MyEvtQA[MyEvtQIn & MyEvtQIMask]; ++MyEvtQIn; } return p; } LOCALVAR ui5b theKeys[4]; LOCALPROC Keyboard_UpdateKeyMap(int key, blnr down) { int k = key & 127; /* just for safety */ int bit = 1 << (k & 7); ui3b *kp = (ui3b *)theKeys; ui3b *kpi = &kp[k / 8]; blnr CurDown = ((*kpi & bit) != 0); if (CurDown != down) { MyEvtQEl *p = MyEvtQElAlloc(); if (NULL != p) { p->kind = MyEvtQElKindKey; p->u.press.key = k; p->u.press.down = down; if (down) { *kpi |= bit; } else { *kpi &= ~ bit; } } QuietEnds(); } } LOCALVAR blnr MyMouseButtonState = falseblnr; LOCALPROC MyMouseButtonSet(blnr down) { if (MyMouseButtonState != down) { MyEvtQEl *p = MyEvtQElAlloc(); if (NULL != p) { p->kind = MyEvtQElKindMouseButton; p->u.press.down = down; MyMouseButtonState = down; } QuietEnds(); } } #if EnableMouseMotion && MayFullScreen LOCALPROC MyMousePositionSetDelta(ui4r dh, ui4r dv) { if ((dh != 0) || (dv != 0)) { MyEvtQEl *p = MyEvtQElPreviousIn(); if ((NULL != p) && (MyEvtQElKindMouseDelta == p->kind)) { p->u.pos.h += dh; p->u.pos.v += dv; } else { p = MyEvtQElAlloc(); if (NULL != p) { p->kind = MyEvtQElKindMouseDelta; p->u.pos.h = dh; p->u.pos.v = dv; } } QuietEnds(); } } #endif LOCALVAR ui4b MyMousePosCurV = 0; LOCALVAR ui4b MyMousePosCurH = 0; LOCALPROC MyMousePositionSet(ui4r h, ui4r v) { if ((h != MyMousePosCurH) || (v != MyMousePosCurV)) { MyEvtQEl *p = MyEvtQElPreviousIn(); if ((NULL == p) || (MyEvtQElKindMousePos != p->kind)) { p = MyEvtQElAlloc(); } if (NULL != p) { p->kind = MyEvtQElKindMousePos; p->u.pos.h = h; p->u.pos.v = v; MyMousePosCurH = h; MyMousePosCurV = v; } QuietEnds(); } } #if 0 #define Keyboard_TestKeyMap(key) \ ((((ui3b *)theKeys)[(key) / 8] & (1 << ((key) & 7))) != 0) #endif LOCALPROC InitKeyCodes(void) { theKeys[0] = 0; theKeys[1] = 0; theKeys[2] = 0; theKeys[3] = 0; } #define kKeepMaskControl (1 << 0) #define kKeepMaskCapsLock (1 << 1) #define kKeepMaskCommand (1 << 2) #define kKeepMaskOption (1 << 3) #define kKeepMaskShift (1 << 4) LOCALPROC DisconnectKeyCodes(ui5b KeepMask) { /* Called when may miss key ups, so act is if all pressed keys have been released, except maybe for control, caps lock, command, option and shift. */ int j; int b; int key; ui5b m; for (j = 0; j < 16; ++j) { ui3b k1 = ((ui3b *)theKeys)[j]; if (0 != k1) { ui3b bit = 1; for (b = 0; b < 8; ++b) { if (0 != (k1 & bit)) { key = j * 8 + b; switch (key) { case MKC_Control: m = kKeepMaskControl; break; case MKC_CapsLock: m = kKeepMaskCapsLock; break; case MKC_Command: m = kKeepMaskCommand; break; case MKC_Option: m = kKeepMaskOption; break; case MKC_Shift: m = kKeepMaskShift; break; default: m = 0; break; } if (0 == (KeepMask & m)) { Keyboard_UpdateKeyMap(key, falseblnr); } } bit <<= 1; } } } } LOCALPROC MyEvtQTryRecoverFromFull(void) { MyMouseButtonSet(falseblnr); DisconnectKeyCodes(0); } /* MacMsg */ LOCALVAR char *SavedBriefMsg = nullpr; LOCALVAR char *SavedLongMsg; LOCALVAR blnr SavedFatalMsg; LOCALPROC MacMsg(char *briefMsg, char *longMsg, blnr fatal) { if (nullpr != SavedBriefMsg) { /* ignore the new message, only display the first error. */ } else { SavedBriefMsg = briefMsg; SavedLongMsg = longMsg; SavedFatalMsg = fatal; } } GLOBALPROC WarnMsgCorruptedROM(void) { MacMsg(kStrCorruptedROMTitle, kStrCorruptedROMMessage, falseblnr); } GLOBALPROC WarnMsgUnsupportedROM(void) { MacMsg(kStrUnsupportedROMTitle, kStrUnsupportedROMMessage, falseblnr); } GLOBALPROC WarnMsgAbnormal(void) { MacMsg(kStrReportAbnormalTitle, kStrReportAbnormalMessage, falseblnr); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/DATE2SEC.h b/Mini vMac/mnvm_core/DATE2SEC.h new file mode 100755 index 0000000..0058861 --- /dev/null +++ b/Mini vMac/mnvm_core/DATE2SEC.h @@ -0,0 +1 @@ +/* DATE2SEC.h Copyright (C) 2003 Bradford L. Barrett, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* DATE 2(to) SEConds convert year/month/day/hour/minute/second to number of seconds since the beginning of 1904, the format for storing dates on the Macintosh. The function jdate is from the program Webalizer by Bradford L. Barrett. */ #ifdef DATE2SEC_H #error "header already included" #else #define DATE2SEC_H #endif /* The function jdate was found at the end of the file webalizer.c in the program webalizer at "www.mrunix.net/webalizer/". Here is copyright info from the top of that file: webalizer - a web server log analysis program Copyright (C) 1997-2000 Bradford L. Barrett (brad@mrunix.net) This program 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 2 of the License, or (at your option) any later version, and provided that the above copyright and permission notice is included with all distributed copies of this or derived software. */ /* ************************************************************* */ /* */ /* JDATE - Julian date calculator */ /* */ /* Calculates the number of days since Jan 1, 0000. */ /* */ /* Originally written by Bradford L. Barrett (03/17/1988) */ /* Returns an unsigned long value representing the number of */ /* days since January 1, 0000. */ /* */ /* Note: Due to the changes made by Pope Gregory XIII in the */ /* 16th Centyry (Feb 24, 1582), dates before 1583 will */ /* not return a truely accurate number (will be at least */ /* 10 days off). Somehow, I don't think this will */ /* present much of a problem for most situations :) */ /* */ /* Usage: days = jdate(day, month, year) */ /* */ /* The number returned is adjusted by 5 to facilitate day of */ /* week calculations. The mod of the returned value gives the */ /* day of the week the date is. (ie: dow = days % 7) where */ /* dow will return 0=Sunday, 1=Monday, 2=Tuesday, etc... */ /* */ /* ************************************************************* */ LOCALFUNC ui5b jdate(int day, int month, int year) { ui5b days; /* value returned */ int mtable[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /* First, calculate base number including leap and Centenial year stuff */ days = (((ui5b)year * 365) + day + mtable[month - 1] + ((year + 4) / 4) - ((year / 100) - (year / 400))); /* now adjust for leap year before March 1st */ if ((year % 4 == 0) && (! ((year % 100 == 0) && (year % 400 != 0))) && (month < 3)) { --days; } /* done, return with calculated value */ return (days + 5); } LOCALFUNC ui5b Date2MacSeconds(int second, int minute, int hour, int day, int month, int year) { ui5b curjdate; ui5b basejdate; curjdate = jdate(day, month, year); basejdate = jdate(1, 1, 1904); return (((curjdate - basejdate) * 24 + hour) * 60 + minute) * 60 + second; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ENDIANAC.h b/Mini vMac/mnvm_core/ENDIANAC.h new file mode 100755 index 0000000..de8a727 --- /dev/null +++ b/Mini vMac/mnvm_core/ENDIANAC.h @@ -0,0 +1 @@ +/* ENDIANAC.h Copyright (C) 2006 Bernd Schmidt, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* ENDIAN ACcess Deals with endian issues in memory access. This code is adapted from code in the Un*x Amiga Emulator by Bernd Schmidt, as found in vMac by Philip Cummins. */ #ifdef ENDIANAC_H #ifndef AllFiles #error "header already included" #endif #else #define ENDIANAC_H #endif #if 0 /* works in GCC from Apple. others? */ static inline ui5r MySwapUi5r(ui5r _data) { __asm__ ("bswap %0" : "+r" (_data)); return _data; } #define HaveMySwapUi5r 1 #endif #ifndef HaveMySwapUi5r #define HaveMySwapUi5r 0 #endif #define do_get_mem_byte(a) ((ui3r)*((ui3b *)(a))) #if BigEndianUnaligned #define do_get_mem_word(a) ((ui4r)*((ui4b *)(a))) #else static MayInline ui4r do_get_mem_word(ui3p a) { #if LittleEndianUnaligned ui4b b = (*((ui4b *)(a))); return ((b & 0x00FF) << 8) | ((b >> 8) & 0x00FF); #else return (((ui4r)*a) << 8) | ((ui4r)*(a + 1)); #endif } #endif #if BigEndianUnaligned #define do_get_mem_long(a) ((ui5r)*((ui5b *)(a))) #elif HaveMySwapUi5r && LittleEndianUnaligned #define do_get_mem_long(a) (MySwapUi5r((ui5r)*((ui5b *)(a)))) #else static MayInline ui5r do_get_mem_long(ui3p a) { #if LittleEndianUnaligned #if 0 return ((b << 24) & 0xFF000000) | ((b << 8) & 0x00FF0000) | ((b >> 8) & 0x0000FF00) | ((b >> 24) & 0x000000FF); /* no, this doesn't do well with apple tools, instead try combining two 16 bit swaps. */ #endif ui5b b = (*((ui5b *)(a))); ui4b b1 = b; ui4b b2 = b >> 16; ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF); ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF); return (((ui5r)c1) << 16) | ((ui5r)c2); /* better, though still doesn't use BSWAP instruction with apple tools for intel. */ #else return (((ui5r)*a) << 24) | (((ui5r)*(a + 1)) << 16) | (((ui5r)*(a + 2)) << 8) | ((ui5r)*(a + 3)); #endif } #endif #define do_put_mem_byte(a, v) ((*((ui3b *)(a))) = (v)) #if BigEndianUnaligned #define do_put_mem_word(a, v) ((*((ui4b *)(a))) = (v)) #else static MayInline void do_put_mem_word(ui3p a, ui4r v) { #if LittleEndianUnaligned ui4b b = ((v & 0x00FF) << 8) | ((v >> 8) & 0x00FF); *(ui4b *)a = b; #else *a = v >> 8; *(a + 1) = v; #endif } #endif #if BigEndianUnaligned #define do_put_mem_long(a, v) ((*((ui5b *)(a))) = (v)) #elif HaveMySwapUi5r && LittleEndianUnaligned #define do_put_mem_long(a, v) ((*((ui5b *)(a))) = MySwapUi5r(v)) #else static MayInline void do_put_mem_long(ui3p a, ui5r v) { #if LittleEndianUnaligned ui4b b1 = v; ui4b b2 = v >> 16; ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF); ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF); *(ui5b *)a = (c1 << 16) | c2; #else *a = v >> 24; *(a + 1) = v >> 16; *(a + 2) = v >> 8; *(a + 3) = v; #endif } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/GLOBGLUE.c b/Mini vMac/mnvm_core/GLOBGLUE.c new file mode 100755 index 0000000..0e77612 --- /dev/null +++ b/Mini vMac/mnvm_core/GLOBGLUE.c @@ -0,0 +1 @@ +/* GLOBGLUE.c Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* GLOBal GLUE (or GLOB of GLUE) Holds the program together. Some code here adapted from "custom.c" in vMac by Philip Cummins, in turn descended from code in the Un*x Amiga Emulator by Bernd Schmidt. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #endif #include "GLOBGLUE.h" IMPORTPROC m68k_reset(void); IMPORTPROC IWM_Reset(void); IMPORTPROC SCC_Reset(void); IMPORTPROC SCSI_Reset(void); IMPORTPROC VIA1_Reset(void); #if EmVIA2 IMPORTPROC VIA2_Reset(void); #endif IMPORTPROC Sony_Reset(void); IMPORTPROC ExtnDisk_Access(CPTR p); IMPORTPROC ExtnSony_Access(CPTR p); #if EmVidCard IMPORTPROC ExtnVideo_Access(CPTR p); #endif IMPORTPROC Sony_SetQuitOnEject(void); IMPORTPROC m68k_IPLchangeNtfy(void); IMPORTPROC MINEM68K_Init( ui3b *fIPL); IMPORTFUNC ui5b GetCyclesRemaining(void); IMPORTPROC SetCyclesRemaining(ui5b n); IMPORTPROC SetHeadATTel(ATTep p); IMPORTFUNC ATTep FindATTel(CPTR addr); IMPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr); IMPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr); IMPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr); IMPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr); #if EmVIA2 IMPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr); #endif #if EmASC IMPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr); #endif IMPORTFUNC ui3r get_vm_byte(CPTR addr); IMPORTFUNC ui4r get_vm_word(CPTR addr); IMPORTFUNC ui5r get_vm_long(CPTR addr); IMPORTPROC put_vm_byte(CPTR addr, ui3r b); IMPORTPROC put_vm_word(CPTR addr, ui4r w); IMPORTPROC put_vm_long(CPTR addr, ui5r l); GLOBALVAR ui5r my_disk_icon_addr; GLOBALPROC customreset(void) { IWM_Reset(); SCC_Reset(); SCSI_Reset(); VIA1_Reset(); #if EmVIA2 VIA2_Reset(); #endif Sony_Reset(); Extn_Reset(); #if CurEmMd <= kEmMd_Plus WantMacReset = trueblnr; /* kludge, code in Finder appears to do RESET and not expect to come back. Maybe asserting the RESET somehow causes other hardware compenents to later reset the 68000. */ #endif } GLOBALVAR ui3p RAM = nullpr; #if EmVidCard GLOBALVAR ui3p VidROM = nullpr; #endif #if IncludeVidMem GLOBALVAR ui3p VidMem = nullpr; #endif GLOBALVAR ui3b Wires[kNumWires]; #if WantDisasm IMPORTPROC m68k_WantDisasmContext(void); #endif #if WantDisasm GLOBALPROC dbglog_StartLine(void) { m68k_WantDisasmContext(); dbglog_writeCStr(" "); } #endif #if dbglog_HAVE GLOBALPROC dbglog_WriteMemArrow(blnr WriteMem) { if (WriteMem) { dbglog_writeCStr(" <- "); } else { dbglog_writeCStr(" -> "); } } #endif #if dbglog_HAVE GLOBALPROC dbglog_AddrAccess(char *s, ui5r Data, blnr WriteMem, ui5r addr) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_writeCStr("["); dbglog_writeHex(addr); dbglog_writeCStr("]"); dbglog_WriteMemArrow(WriteMem); dbglog_writeHex(Data); dbglog_writeReturn(); } #endif #if dbglog_HAVE GLOBALPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_WriteMemArrow(WriteMem); dbglog_writeHex(Data); dbglog_writeReturn(); } #endif #if dbglog_HAVE GLOBALPROC dbglog_WriteNote(char *s) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_writeReturn(); } #endif #if dbglog_HAVE GLOBALPROC dbglog_WriteSetBool(char *s, blnr v) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_writeCStr(" <- "); if (v) { dbglog_writeCStr("1"); } else { dbglog_writeCStr("0"); } dbglog_writeReturn(); } #endif LOCALVAR blnr GotOneAbnormal = falseblnr; #ifndef ReportAbnormalInterrupt #define ReportAbnormalInterrupt 0 #endif #if dbglog_HAVE GLOBALPROC DoReportAbnormal(char *s) #else GLOBALPROC DoReportAbnormal(void) #endif { #if dbglog_HAVE dbglog_StartLine(); dbglog_writeCStr("*** abnormal : "); dbglog_writeCStr(s); dbglog_writeReturn(); #endif if (! GotOneAbnormal) { WarnMsgAbnormal(); #if ReportAbnormalInterrupt SetInterruptButton(trueblnr); #endif GotOneAbnormal = trueblnr; } } /* map of address space */ #define kRAM_Base 0x00000000 /* when overlay off */ #if (CurEmMd == kEmMd_PB100) #define kRAM_ln2Spc 23 #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define kRAM_ln2Spc 23 #else #define kRAM_ln2Spc 22 #endif #if IncludeVidMem #if CurEmMd == kEmMd_PB100 #define kVidMem_Base 0x00FA0000 #define kVidMem_ln2Spc 16 #else #define kVidMem_Base 0x00540000 #define kVidMem_ln2Spc 18 #endif #endif #if CurEmMd == kEmMd_PB100 #define kSCSI_Block_Base 0x00F90000 #define kSCSI_ln2Spc 16 #else #define kSCSI_Block_Base 0x00580000 #define kSCSI_ln2Spc 19 #endif #define kRAM_Overlay_Base 0x00600000 /* when overlay on */ #define kRAM_Overlay_Top 0x00800000 #if CurEmMd == kEmMd_PB100 #define kSCCRd_Block_Base 0x00FD0000 #define kSCC_ln2Spc 16 #else #define kSCCRd_Block_Base 0x00800000 #define kSCC_ln2Spc 22 #endif #if CurEmMd != kEmMd_PB100 #define kSCCWr_Block_Base 0x00A00000 #define kSCCWr_Block_Top 0x00C00000 #endif #if CurEmMd == kEmMd_PB100 #define kIWM_Block_Base 0x00F60000 #define kIWM_ln2Spc 16 #else #define kIWM_Block_Base 0x00C00000 #define kIWM_ln2Spc 21 #endif #if CurEmMd == kEmMd_PB100 #define kVIA1_Block_Base 0x00F70000 #define kVIA1_ln2Spc 16 #else #define kVIA1_Block_Base 0x00E80000 #define kVIA1_ln2Spc 19 #endif #if CurEmMd == kEmMd_PB100 #define kASC_Block_Base 0x00FB0000 #define kASC_ln2Spc 16 #endif #define kASC_Mask 0x00000FFF #if IncludeExtnPbufs LOCALFUNC tMacErr PbufTransferVM(CPTR Buffera, tPbuf i, ui5r offset, ui5r count, blnr IsWrite) { tMacErr result; ui5b contig; ui3p Buffer; label_1: if (0 == count) { result = mnvm_noErr; } else { Buffer = get_real_address0(count, ! IsWrite, Buffera, &contig); if (0 == contig) { result = mnvm_miscErr; } else { PbufTransfer(Buffer, i, offset, contig, IsWrite); offset += contig; Buffera += contig; count -= contig; goto label_1; } } return result; } #endif /* extension mechanism */ #if IncludeExtnPbufs #define kCmndPbufFeatures 1 #define kCmndPbufNew 2 #define kCmndPbufDispose 3 #define kCmndPbufGetSize 4 #define kCmndPbufTransfer 5 #endif #if IncludeExtnPbufs LOCALPROC ExtnParamBuffers_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndPbufFeatures: put_vm_long(p + ExtnDat_params + 0, 0); result = mnvm_noErr; break; case kCmndPbufNew: { tPbuf Pbuf_No; ui5b count = get_vm_long(p + ExtnDat_params + 4); /* reserved word at offset 2, should be zero */ result = PbufNew(count, &Pbuf_No); put_vm_word(p + ExtnDat_params + 0, Pbuf_No); } break; case kCmndPbufDispose: { tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { PbufDispose(Pbuf_No); } } break; case kCmndPbufGetSize: { ui5r Count; tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ result = PbufGetSize(Pbuf_No, &Count); if (mnvm_noErr == result) { put_vm_long(p + ExtnDat_params + 4, Count); } } break; case kCmndPbufTransfer: { ui5r PbufCount; tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ ui5r offset = get_vm_long(p + ExtnDat_params + 4); ui5r count = get_vm_long(p + ExtnDat_params + 8); CPTR Buffera = get_vm_long(p + ExtnDat_params + 12); blnr IsWrite = (get_vm_word(p + ExtnDat_params + 16) != 0); result = PbufGetSize(Pbuf_No, &PbufCount); if (mnvm_noErr == result) { ui5r endoff = offset + count; if ((endoff < offset) /* overflow */ || (endoff > PbufCount)) { result = mnvm_eofErr; } else { result = PbufTransferVM(Buffera, Pbuf_No, offset, count, IsWrite); } } } break; } put_vm_word(p + ExtnDat_result, result); } #endif #if IncludeExtnHostTextClipExchange #define kCmndHTCEFeatures 1 #define kCmndHTCEExport 2 #define kCmndHTCEImport 3 #endif #if IncludeExtnHostTextClipExchange LOCALPROC ExtnHostTextClipExchange_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndHTCEFeatures: put_vm_long(p + ExtnDat_params + 0, 0); result = mnvm_noErr; break; case kCmndHTCEExport: { tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { result = HTCEexport(Pbuf_No); } } break; case kCmndHTCEImport: { tPbuf Pbuf_No; result = HTCEimport(&Pbuf_No); put_vm_word(p + ExtnDat_params + 0, Pbuf_No); } break; } put_vm_word(p + ExtnDat_result, result); } #endif #define kFindExtnExtension 0x64E1F58A #define kDiskDriverExtension 0x4C9219E6 #if IncludeExtnPbufs #define kHostParamBuffersExtension 0x314C87BF #endif #if IncludeExtnHostTextClipExchange #define kHostClipExchangeExtension 0x27B130CA #endif #define kCmndFindExtnFind 1 #define kCmndFindExtnId2Code 2 #define kCmndFindExtnCount 3 #define kParamFindExtnTheExtn 8 #define kParamFindExtnTheId 12 LOCALPROC ExtnFind_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndFindExtnFind: { ui5b extn = get_vm_long(p + kParamFindExtnTheExtn); if (extn == kDiskDriverExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnDisk); result = mnvm_noErr; } else #if IncludeExtnPbufs if (extn == kHostParamBuffersExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnParamBuffers); result = mnvm_noErr; } else #endif #if IncludeExtnHostTextClipExchange if (extn == kHostClipExchangeExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnHostTextClipExchange); result = mnvm_noErr; } else #endif if (extn == kFindExtnExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnFindExtn); result = mnvm_noErr; } else { /* not found */ } } break; case kCmndFindExtnId2Code: { ui4r extn = get_vm_word(p + kParamFindExtnTheId); if (extn == kExtnDisk) { put_vm_long(p + kParamFindExtnTheExtn, kDiskDriverExtension); result = mnvm_noErr; } else #if IncludeExtnPbufs if (extn == kExtnParamBuffers) { put_vm_long(p + kParamFindExtnTheExtn, kHostParamBuffersExtension); result = mnvm_noErr; } else #endif #if IncludeExtnHostTextClipExchange if (extn == kExtnHostTextClipExchange) { put_vm_long(p + kParamFindExtnTheExtn, kHostClipExchangeExtension); result = mnvm_noErr; } else #endif if (extn == kExtnFindExtn) { put_vm_long(p + kParamFindExtnTheExtn, kFindExtnExtension); result = mnvm_noErr; } else { /* not found */ } } break; case kCmndFindExtnCount: put_vm_word(p + kParamFindExtnTheId, kNumExtns); result = mnvm_noErr; break; } put_vm_word(p + ExtnDat_result, result); } #define kDSK_Params_Hi 0 #define kDSK_Params_Lo 1 #define kDSK_QuitOnEject 3 /* obsolete */ LOCALVAR ui4b ParamAddrHi; LOCALPROC Extn_Access(ui5b Data, CPTR addr) { switch (addr) { case kDSK_Params_Hi: ParamAddrHi = Data; break; case kDSK_Params_Lo: { CPTR p = ParamAddrHi << 16 | Data; ParamAddrHi = (ui4b) - 1; if (kcom_callcheck == get_vm_word(p + ExtnDat_checkval)) { put_vm_word(p + ExtnDat_checkval, 0); switch (get_vm_word(p + ExtnDat_extension)) { case kExtnFindExtn: ExtnFind_Access(p); break; #if EmVidCard case kExtnVideo: ExtnVideo_Access(p); break; #endif #if IncludeExtnPbufs case kExtnParamBuffers: ExtnParamBuffers_Access(p); break; #endif #if IncludeExtnHostTextClipExchange case kExtnHostTextClipExchange: ExtnHostTextClipExchange_Access(p); break; #endif case kExtnDisk: ExtnDisk_Access(p); break; case kExtnSony: ExtnSony_Access(p); break; default: put_vm_word(p + ExtnDat_result, mnvm_controlErr); break; } } } break; case kDSK_QuitOnEject: /* obsolete, kept for compatibility */ Sony_SetQuitOnEject(); break; } } GLOBALPROC Extn_Reset(void) { ParamAddrHi = (ui4b) - 1; } /* implementation of read/write for everything but RAM and ROM */ #define kSCC_Mask 0x03 #define kVIA1_Mask 0x00000F #if EmVIA2 #define kVIA2_Mask 0x00000F #endif #define kIWM_Mask 0x00000F /* Allocated Memory Bandwidth for IWM */ #if CurEmMd <= kEmMd_512Ke #define ROM_CmpZeroMask 0 #elif CurEmMd <= kEmMd_Plus #define ROM_CmpZeroMask 0x00020000 #elif CurEmMd <= kEmMd_PB100 #define ROM_CmpZeroMask 0 #elif CurEmMd <= kEmMd_IIx #define ROM_CmpZeroMask 0 #else #error "ROM_CmpZeroMask not defined" #endif #define kROM_cmpmask (0x00F00000 | ROM_CmpZeroMask) #if CurEmMd <= kEmMd_512Ke #define Overlay_ROM_CmpZeroMask 0x00100000 #elif CurEmMd <= kEmMd_Plus #define Overlay_ROM_CmpZeroMask 0x00020000 #elif CurEmMd <= kEmMd_Classic #define Overlay_ROM_CmpZeroMask 0x00300000 #elif CurEmMd <= kEmMd_PB100 #define Overlay_ROM_CmpZeroMask 0 #elif CurEmMd <= kEmMd_IIx #define Overlay_ROM_CmpZeroMask 0 #else #error "Overlay_ROM_CmpZeroMask not defined" #endif enum { kMMDV_VIA1, #if EmVIA2 kMMDV_VIA2, #endif kMMDV_SCC, kMMDV_Extn, #if EmASC kMMDV_ASC, #endif kMMDV_SCSI, kMMDV_IWM, kNumMMDVs }; enum { #if CurEmMd >= kEmMd_SE kMAN_OverlayOff, #endif kNumMANs }; LOCALVAR ATTer ATTListA[MaxATTListN]; LOCALVAR ui4r LastATTel; LOCALPROC AddToATTList(ATTep p) { ui4r NewLast = LastATTel + 1; if (NewLast >= MaxATTListN) { ReportAbnormal("MaxATTListN not big enough"); } else { ATTListA[LastATTel] = *p; LastATTel = NewLast; } } LOCALPROC InitATTList(void) { LastATTel = 0; } LOCALPROC FinishATTList(void) { { /* add guard */ ATTer r; r.cmpmask = 0; r.cmpvalu = 0; r.usemask = 0; r.usebase = nullpr; r.Access = 0; AddToATTList(&r); } { ui4r i = LastATTel; ATTep p = &ATTListA[LastATTel]; ATTep h = nullpr; while (0 != i) { --i; --p; p->Next = h; h = p; } #if 0 /* verify list. not for final version */ { ATTep q1; ATTep q2; for (q1 = h; nullpr != q1->Next; q1 = q1->Next) { if ((q1->cmpvalu & ~ q1->cmpmask) != 0) { ReportAbnormal("ATTListA bad entry"); } for (q2 = q1->Next; nullpr != q2->Next; q2 = q2->Next) { ui5r common_mask = (q1->cmpmask) & (q2->cmpmask); if ((q1->cmpvalu & common_mask) == (q2->cmpvalu & common_mask)) { ReportAbnormal("ATTListA Conflict"); } } } } #endif SetHeadATTel(h); } } #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_RAM24(void) { ATTer r; ui5r bankbit = 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1); #if kRAMa_Size == kRAMb_Size if (kRAMa_Size == bankbit) { /* properly set up balanced RAM */ r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1); r.cmpvalu = 0; r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAM_Size - 1); r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } else #endif { bankbit &= 0x00FFFFFF; /* if too large, always use RAMa */ if (0 != bankbit) { #if kRAMb_Size != 0 r.cmpmask = bankbit | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = bankbit; r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMb_Size - 1); r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif } { r.cmpmask = bankbit | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = 0; r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMa_Size - 1); r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } } } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_io(void) { ATTer r; if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_VIA1; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x2000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x2000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_VIA2; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x4000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x4000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCC; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x0C000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x0C000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_Extn; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x10000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x10000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCSI; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x14000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x14000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_ASC; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x16000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x16000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_IWM; AddToATTList(&r); #if 0 case 14: /* fail, nothing supposed to be here, but rom accesses it anyway */ { ui5r addr2 = addr & 0x1FFFF; if ((addr2 != 0x1DA00) && (addr2 != 0x1DC00)) { ReportAbnormal("another unknown access"); } } get_fail_realblock(p); break; #endif } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_address24(void) { ATTer r; if (MemOverlay) { ReportAbnormal("Overlay with 24 bit addressing"); } if (MemOverlay) { r.cmpmask = Overlay_ROM_CmpZeroMask | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); } else { SetUp_RAM24(); } r.cmpmask = kROM_cmpmask; r.cmpvalu = kROM_Base; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0x900000; r.usemask = (kVidMemRAM_Size - 1) & (0x100000 - 1); r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #if kVidMemRAM_Size >= 0x00200000 r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0xA00000; r.usemask = (0x100000 - 1); r.usebase = VidMem + (1 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif #if kVidMemRAM_Size >= 0x00400000 r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0xB00000; r.usemask = (0x100000 - 1); r.usebase = VidMem + (2 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0xC00000; r.usemask = (0x100000 - 1); r.usebase = VidMem + (3 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif SetUp_io(); } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_address32(void) { ATTer r; if (MemOverlay) { r.cmpmask = ~ ((1 << 30) - 1); r.cmpvalu = 0; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); } else { ui5r bankbit = 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1); #if kRAMa_Size == kRAMb_Size if (kRAMa_Size == bankbit) { /* properly set up balanced RAM */ r.cmpmask = ~ ((1 << 30) - 1); r.cmpvalu = 0; r.usemask = kRAM_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } else #endif { #if kRAMb_Size != 0 r.cmpmask = bankbit | ~ ((1 << 30) - 1); r.cmpvalu = bankbit; r.usemask = kRAMb_Size - 1; r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = bankbit | ~ ((1 << 30) - 1); r.cmpvalu = 0; r.usemask = kRAMa_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } } r.cmpmask = ~ ((1 << 28) - 1); r.cmpvalu = 0x40000000; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); #if 0 /* haven't persuaded emulated computer to look here yet. */ /* NuBus super space */ r.cmpmask = ~ ((1 << 28) - 1); r.cmpvalu = 0x90000000; r.usemask = kVidMemRAM_Size - 1; r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif /* Standard NuBus space */ r.cmpmask = ~ ((1 << 20) - 1); r.cmpvalu = 0xF9F00000; r.usemask = kVidROM_Size - 1; r.usebase = VidROM; r.Access = kATTA_readreadymask; AddToATTList(&r); #if 0 r.cmpmask = ~ 0x007FFFFF; r.cmpvalu = 0xF9000000; r.usemask = 0x007FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9900000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); /* kludge to allow more than 1M of Video Memory */ #if kVidMemRAM_Size >= 0x00200000 r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9A00000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem + (1 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif #if kVidMemRAM_Size >= 0x00400000 r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9B00000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem + (2 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9C00000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem + (3 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif SetUp_io(); #if 0 if ((addr >= 0x58000000) && (addr < 0x58000004)) { /* test hardware. fail */ } #endif } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_address(void) { if (Addr32) { SetUp_address32(); } else { SetUp_address24(); } } #endif /* unlike in the real Mac Plus, Mini vMac will allow misaligned memory access, since it is easier to allow it than it is to correctly simulate a bus error and back out of the current instruction. */ #if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx) LOCALPROC SetUp_RAM24(void) { ATTer r; #if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size) r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1); r.cmpvalu = kRAM_Base; r.usemask = kRAM_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #else /* unbalanced memory */ #if 0 != (0x00FFFFFF & kRAMa_Size) /* condition should always be true if configuration file right */ r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base + kRAMa_Size; r.usemask = kRAMb_Size - 1; r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base; r.usemask = kRAMa_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif } #endif #if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx) LOCALPROC SetUp_address(void) { ATTer r; if (MemOverlay) { r.cmpmask = Overlay_ROM_CmpZeroMask | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); } else { SetUp_RAM24(); } r.cmpmask = kROM_cmpmask; r.cmpvalu = kROM_Base; #if (CurEmMd >= kEmMd_SE) if (MemOverlay) { r.usebase = nullpr; r.Access = kATTA_ntfymask; r.Ntfy = kMAN_OverlayOff; } else #endif { r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; } AddToATTList(&r); if (MemOverlay) { r.cmpmask = 0x00E00000; r.cmpvalu = kRAM_Overlay_Base; #if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size) r.usemask = kRAM_Size - 1; /* note that cmpmask and usemask overlap for 4M */ r.usebase = RAM; r.Access = kATTA_readwritereadymask; #else /* unbalanced memory */ r.usemask = kRAMb_Size - 1; r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; #endif AddToATTList(&r); } #if IncludeVidMem r.cmpmask = 0x00FFFFFF & ~ ((1 << kVidMem_ln2Spc) - 1); r.cmpvalu = kVidMem_Base; r.usemask = kVidMemRAM_Size - 1; r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = 0x00FFFFFF & ~ ((1 << kVIA1_ln2Spc) - 1); r.cmpvalu = kVIA1_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_VIA1; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCC_ln2Spc) - 1); r.cmpvalu = kSCCRd_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCC; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ ((1 << kExtn_ln2Spc) - 1); r.cmpvalu = kExtn_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_Extn; AddToATTList(&r); #if CurEmMd == kEmMd_PB100 r.cmpmask = 0x00FFFFFF & ~ ((1 << kASC_ln2Spc) - 1); r.cmpvalu = kASC_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_ASC; AddToATTList(&r); #endif r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCSI_ln2Spc) - 1); r.cmpvalu = kSCSI_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCSI; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ ((1 << kIWM_ln2Spc) - 1); r.cmpvalu = kIWM_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_IWM; AddToATTList(&r); } #endif LOCALPROC SetUpMemBanks(void) { InitATTList(); SetUp_address(); FinishATTList(); } #if 0 LOCALPROC get_fail_realblock(ATTep p) { p->cmpmask = 0; p->cmpvalu = 0xFFFFFFFF; p->usemask = 0; p->usebase = nullpr; p->Access = 0; } #endif GLOBALFUNC ui5b MMDV_Access(ATTep p, ui5b Data, blnr WriteMem, blnr ByteSize, CPTR addr) { switch (p->MMDV) { case kMMDV_VIA1: if (! ByteSize) { ReportAbnormal("access VIA1 word"); } else if ((addr & 1) != 0) { ReportAbnormal("access VIA1 odd"); } else { #if CurEmMd != kEmMd_PB100 #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 0x000001FE) != 0x00000000) #else if ((addr & 0x000FE1FE) != 0x000FE1FE) #endif { ReportAbnormal("access VIA1 nonstandard address"); } #endif Data = VIA1_Access(Data, WriteMem, (addr >> 9) & kVIA1_Mask); } break; #if EmVIA2 case kMMDV_VIA2: if (! ByteSize) { if ((! WriteMem) && ((0x3e00 == (addr & 0x1FFFF)) || (0x3e02 == (addr & 0x1FFFF)))) { /* for weirdness at offset 0x71E in ROM */ Data = (VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask) << 8) | VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask); } else { ReportAbnormal("access VIA2 word"); } } else if ((addr & 1) != 0) { if (0x3FFF == (addr & 0x1FFFF)) { /* for weirdness at offset 0x7C4 in ROM. looks like bug. */ Data = VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask); } else { ReportAbnormal("access VIA2 odd"); } } else { if ((addr & 0x000001FE) != 0x00000000) { ReportAbnormal("access VIA2 nonstandard address"); } Data = VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask); } break; #endif case kMMDV_SCC: #if (CurEmMd >= kEmMd_SE) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if ((addr & 0x00100000) == 0) { ReportAbnormal("access SCC unassigned address"); } else #endif if (! ByteSize) { ReportAbnormal("Attemped Phase Adjust"); } else #if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if (WriteMem != ((addr & 1) != 0)) { if (WriteMem) { #if CurEmMd >= kEmMd_512Ke #if CurEmMd != kEmMd_PB100 ReportAbnormal("access SCC even/odd"); /* This happens on boot with 64k ROM. */ #endif #endif } else { SCC_Reset(); } } else #endif #if (CurEmMd != kEmMd_PB100) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if (WriteMem != (addr >= kSCCWr_Block_Base)) { ReportAbnormal("access SCC wr/rd base wrong"); } else #endif { #if CurEmMd != kEmMd_PB100 #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 0x1FF9) != 0x00000000) #else if ((addr & 0x001FFFF8) != 0x001FFFF8) #endif { ReportAbnormal("access SCC nonstandard address"); } #endif Data = SCC_Access(Data, WriteMem, (addr >> 1) & kSCC_Mask); } break; case kMMDV_Extn: if (ByteSize) { ReportAbnormal("access Sony byte"); } else if ((addr & 1) != 0) { ReportAbnormal("access Sony odd"); } else if (! WriteMem) { ReportAbnormal("access Sony read"); } else { Extn_Access(Data, (addr >> 1) & 0x0F); } break; #if EmASC case kMMDV_ASC: if (! ByteSize) { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if (WriteMem) { (void) ASC_Access((Data >> 8) & 0x00FF, WriteMem, addr & kASC_Mask); Data = ASC_Access((Data) & 0x00FF, WriteMem, (addr + 1) & kASC_Mask); } else { Data = (ASC_Access((Data >> 8) & 0x00FF, WriteMem, addr & kASC_Mask) << 8) | ASC_Access((Data) & 0x00FF, WriteMem, (addr + 1) & kASC_Mask); } #else ReportAbnormal("access ASC word"); #endif } else { Data = ASC_Access(Data, WriteMem, addr & kASC_Mask); } break; #endif case kMMDV_SCSI: if (! ByteSize) { ReportAbnormal("access SCSI word"); } else #if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if (WriteMem != ((addr & 1) != 0)) { ReportAbnormal("access SCSI even/odd"); } else #endif { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 0x1F8F) != 0x00000000) { ReportAbnormal("access SCSI nonstandard address"); } #endif Data = SCSI_Access(Data, WriteMem, (addr >> 4) & 0x07); } break; case kMMDV_IWM: #if (CurEmMd >= kEmMd_SE) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if ((addr & 0x00100000) == 0) { ReportAbnormal("access IWM unassigned address"); } else #endif if (! ByteSize) { #if ExtraAbnormalReports ReportAbnormal("access IWM word"); /* This happens when quitting 'Glider 3.1.2'. perhaps a bad handle is being disposed of. */ #endif } else #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 1) != 0) { ReportAbnormal("access IWM odd"); } else #else if ((addr & 1) == 0) { ReportAbnormal("access IWM even"); } else #endif { #if (CurEmMd != kEmMd_PB100) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if ((addr & 0x001FE1FF) != 0x001FE1FF) { ReportAbnormal("access IWM nonstandard address"); } #endif Data = IWM_Access(Data, WriteMem, (addr >> 9) & kIWM_Mask); } break; } return Data; } GLOBALFUNC blnr MemAccessNtfy(ATTep pT) { blnr v = falseblnr; switch (pT->Ntfy) { #if CurEmMd >= kEmMd_SE case kMAN_OverlayOff: pT->Access = kATTA_readreadymask; MemOverlay = 0; SetUpMemBanks(); v = trueblnr; break; #endif } return v; } GLOBALPROC MemOverlay_ChangeNtfy(void) { #if CurEmMd <= kEmMd_Plus SetUpMemBanks(); #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) SetUpMemBanks(); #endif } #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) GLOBALPROC Addr32_ChangeNtfy(void) { SetUpMemBanks(); } #endif LOCALFUNC ATTep get_address_realblock1(blnr WriteMem, CPTR addr) { ATTep p; Label_Retry: p = FindATTel(addr); if (0 != (p->Access & (WriteMem ? kATTA_writereadymask : kATTA_readreadymask))) { /* ok */ } else { if (0 != (p->Access & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } } p = nullpr; /* fail */ } return p; } GLOBALFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr, ui5b *actL) { ui5b RealSize; ui5b bankleft; ui3p p; ATTep q; q = get_address_realblock1(WritableMem, addr); if (nullpr == q) { *actL = 0; p = nullpr; } else { ui5b bankoffset = addr & q->usemask; RealSize = q->usemask + 1; bankleft = RealSize - bankoffset; p = bankoffset + q->usebase; if (bankleft >= L) { /* this block is big enough (by far the most common case) */ *actL = L; } else { /* not big enough, look if following block is contiguous in real memory. */ ui3p bankend; ui5b n = L; label_1: addr += bankleft; n -= bankleft; bankend = RealSize + q->usebase; q = get_address_realblock1(WritableMem, addr); if ((nullpr == q) || (q->usebase != bankend)) { /* following block not contiguous */ *actL = L - n; } else { RealSize = q->usemask + 1; if (RealSize >= n) { /* following block is contiguous and big enough */ *actL = L; /* ok */ } else { bankoffset = addr & q->usemask; if (bankoffset != 0) { ReportAbnormal( "problem with get_address_realblock1"); } bankleft = RealSize; goto label_1; } } } } return p; } GLOBALVAR blnr InterruptButton = falseblnr; GLOBALPROC SetInterruptButton(blnr v) { if (InterruptButton != v) { InterruptButton = v; VIAorSCCinterruptChngNtfy(); } } LOCALVAR ui3b CurIPL = 0; GLOBALPROC VIAorSCCinterruptChngNtfy(void) { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) ui3b NewIPL; if (InterruptButton) { NewIPL = 7; } else if (SCCInterruptRequest) { NewIPL = 4; } else if (VIA2_InterruptRequest) { NewIPL = 2; } else if (VIA1_InterruptRequest) { NewIPL = 1; } else { NewIPL = 0; } #else ui3b VIAandNotSCC = VIA1_InterruptRequest & ~ SCCInterruptRequest; ui3b NewIPL = VIAandNotSCC | (SCCInterruptRequest << 1) | (InterruptButton << 2); #endif if (NewIPL != CurIPL) { CurIPL = NewIPL; m68k_IPLchangeNtfy(); } } GLOBALFUNC blnr AddrSpac_Init(void) { int i; for (i = 0; i < kNumWires; i++) { Wires[i] = 1; } MINEM68K_Init( &CurIPL); return trueblnr; } GLOBALPROC Memory_Reset(void) { MemOverlay = 1; SetUpMemBanks(); } #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) EXPORTPROC PowerOff_ChangeNtfy(void); GLOBALPROC PowerOff_ChangeNtfy(void) { if (! VIA2_iB2) { ForceMacOff = trueblnr; } } #endif /* user event queue utilities */ #if HaveMasterMyEvtQLock GLOBALVAR ui4r MasterMyEvtQLock = 0; /* Takes a few ticks to process button event because of debounce code of Mac. So have this mechanism to prevent processing further events meanwhile. */ #endif GLOBALFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown) { MyEvtQEl *p; if ( #if HaveMasterMyEvtQLock (0 == MasterMyEvtQLock) && #endif (nullpr != (p = MyEvtQOutP()))) { if (MyEvtQElKindKey == p->kind) { *VirtualKey = p->u.press.key; *KeyDown = p->u.press.down; MyEvtQOutDone(); return trueblnr; } } return falseblnr; } /* task management */ #ifdef _VIA_Debug #include #endif GLOBALVAR uimr ICTactive; GLOBALVAR iCountt ICTwhen[kNumICTs]; GLOBALPROC ICT_Zap(void) { ICTactive = 0; } LOCALPROC InsertICT(int taskid, iCountt when) { ICTwhen[taskid] = when; ICTactive |= (1 << taskid); } GLOBALVAR iCountt NextiCount = 0; GLOBALFUNC iCountt GetCuriCount(void) { return NextiCount - GetCyclesRemaining(); } GLOBALPROC ICT_add(int taskid, ui5b n) { /* n must be > 0 */ si5r x = GetCyclesRemaining(); ui5b when = NextiCount - x + n; #ifdef _VIA_Debug fprintf(stderr, "ICT_add: %d, %d, %d\n", when, taskid, n); #endif InsertICT(taskid, when); if (x > (si5r)n) { SetCyclesRemaining(n); NextiCount = when; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/GLOBGLUE.h b/Mini vMac/mnvm_core/GLOBGLUE.h new file mode 100755 index 0000000..ba0d537 --- /dev/null +++ b/Mini vMac/mnvm_core/GLOBGLUE.h @@ -0,0 +1 @@ +/* GLOBGLUE.h Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef GLOBGLUE_H #error "header already included" #else #define GLOBGLUE_H #endif #define kEmMd_128K 0 #define kEmMd_512Ke 1 #define kEmMd_Plus 2 #define kEmMd_SE 3 #define kEmMd_SEFDHD 4 #define kEmMd_Classic 5 #define kEmMd_PB100 6 #define kEmMd_II 7 #define kEmMd_IIx 8 #define RAMSafetyMarginFudge 4 #define kRAM_Size (kRAMa_Size + kRAMb_Size) EXPORTVAR(ui3p, RAM) /* allocated by MYOSGLUE to be at least kRAM_Size + RAMSafetyMarginFudge bytes. Because of shortcuts taken in GLOBGLUE.c, it is in theory possible for the emulator to write up to 3 bytes past kRAM_Size. */ #if EmVidCard EXPORTVAR(ui3p, VidROM) #endif #if IncludeVidMem EXPORTVAR(ui3p, VidMem) #endif EXPORTPROC MemOverlay_ChangeNtfy(void); #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) EXPORTPROC Addr32_ChangeNtfy(void); #endif /* representation of pointer into memory of emulated computer. */ typedef ui5b CPTR; /* mapping of address space to real memory */ EXPORTFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr, ui5b *actL); /* memory access routines that can use when have address that is known to be in RAM (and that is in the first copy of the ram, not the duplicates, i.e. < kRAM_Size). */ #define get_ram_byte(addr) do_get_mem_byte((addr) + RAM) #define get_ram_word(addr) do_get_mem_word((addr) + RAM) #define get_ram_long(addr) do_get_mem_long((addr) + RAM) #define put_ram_byte(addr, b) do_put_mem_byte((addr) + RAM, (b)) #define put_ram_word(addr, w) do_put_mem_word((addr) + RAM, (w)) #define put_ram_long(addr, l) do_put_mem_long((addr) + RAM, (l)) #define get_ram_address(addr) ((addr) + RAM) /* accessing addresses that don't map to real memory, i.e. memory mapped devices */ EXPORTFUNC blnr AddrSpac_Init(void); #define ui5r_FromSByte(x) ((ui5r)(si5r)(si3b)(ui3b)(x)) #define ui5r_FromSWord(x) ((ui5r)(si5r)(si4b)(ui4b)(x)) #define ui5r_FromSLong(x) ((ui5r)(si5r)(si5b)(ui5b)(x)) #define ui5r_FromUByte(x) ((ui5r)(ui3b)(x)) #define ui5r_FromUWord(x) ((ui5r)(ui4b)(x)) #define ui5r_FromULong(x) ((ui5r)(ui5b)(x)) #define LOCALPROCUSEDONCE LOCALFUNC MayInline void #if WantDisasm EXPORTPROC dbglog_StartLine(void); #else #define dbglog_StartLine() #endif #if dbglog_HAVE EXPORTPROC dbglog_WriteMemArrow(blnr WriteMem); EXPORTPROC dbglog_WriteNote(char *s); EXPORTPROC dbglog_WriteSetBool(char *s, blnr v); EXPORTPROC dbglog_AddrAccess(char *s, ui5r Data, blnr WriteMem, ui5r addr); EXPORTPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem); #endif #if dbglog_HAVE #define ReportAbnormal DoReportAbnormal EXPORTPROC DoReportAbnormal(char *s); #else #define ReportAbnormal(s) DoReportAbnormal() EXPORTPROC DoReportAbnormal(void); #endif EXPORTPROC VIAorSCCinterruptChngNtfy(void); EXPORTVAR(blnr, InterruptButton) EXPORTPROC SetInterruptButton(blnr v); enum { kICT_SubTick, #if EmClassicKbrd kICT_Kybd_ReceiveCommand, kICT_Kybd_ReceiveEndCommand, #endif #if EmADB kICT_ADB_NewState, #endif #if EmPMU kICT_PMU_Task, #endif kICT_VIA1_Timer1Check, kICT_VIA1_Timer2Check, #if EmVIA2 kICT_VIA2_Timer1Check, kICT_VIA2_Timer2Check, #endif kNumICTs }; EXPORTPROC ICT_add(int taskid, ui5b n); #define iCountt ui5b EXPORTFUNC iCountt GetCuriCount(void); EXPORTPROC ICT_Zap(void); EXPORTVAR(uimr, ICTactive) EXPORTVAR(iCountt, ICTwhen[kNumICTs]) EXPORTVAR(iCountt, NextiCount) EXPORTVAR(ui3b, Wires[kNumWires]) #define kLn2CycleScale 6 #define kCycleScale (1 << kLn2CycleScale) #if WantCycByPriOp #define RdAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4) #define WrAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4) #endif #define kNumSubTicks 16 #define HaveMasterMyEvtQLock EmClassicKbrd #if HaveMasterMyEvtQLock EXPORTVAR(ui4r, MasterMyEvtQLock) #endif EXPORTFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown); /* minivmac extensions */ #define ExtnDat_checkval 0 #define ExtnDat_extension 2 #define ExtnDat_commnd 4 #define ExtnDat_result 6 #define ExtnDat_params 8 #define kCmndVersion 0 #define ExtnDat_version 8 enum { kExtnFindExtn, /* must be first */ kExtnDisk, kExtnSony, #if EmVidCard kExtnVideo, #endif #if IncludeExtnPbufs kExtnParamBuffers, #endif #if IncludeExtnHostTextClipExchange kExtnHostTextClipExchange, #endif kNumExtns }; #define kcom_callcheck 0x5B17 EXPORTVAR(ui5r, my_disk_icon_addr) EXPORTPROC Memory_Reset(void); EXPORTPROC Extn_Reset(void); EXPORTPROC customreset(void); struct ATTer { struct ATTer *Next; ui5r cmpmask; ui5r cmpvalu; ui5r Access; ui5r usemask; ui3p usebase; ui3r MMDV; ui3r Ntfy; ui4r Pad0; ui5r Pad1; /* make 32 byte structure, on 32 bit systems */ }; typedef struct ATTer ATTer; typedef ATTer *ATTep; #define kATTA_readreadybit 0 #define kATTA_writereadybit 1 #define kATTA_mmdvbit 2 #define kATTA_ntfybit 3 #define kATTA_readwritereadymask \ ((1 << kATTA_readreadybit) | (1 << kATTA_writereadybit)) #define kATTA_readreadymask (1 << kATTA_readreadybit) #define kATTA_writereadymask (1 << kATTA_writereadybit) #define kATTA_mmdvmask (1 << kATTA_mmdvbit) #define kATTA_ntfymask (1 << kATTA_ntfybit) EXPORTFUNC ui5b MMDV_Access(ATTep p, ui5b Data, blnr WriteMem, blnr ByteSize, CPTR addr); EXPORTFUNC blnr MemAccessNtfy(ATTep pT); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/INTLCHAR.h b/Mini vMac/mnvm_core/INTLCHAR.h new file mode 100755 index 0000000..cfd5826 --- /dev/null +++ b/Mini vMac/mnvm_core/INTLCHAR.h @@ -0,0 +1 @@ +/* INTLCHAR.h Copyright (C) 2010 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* InterNaTionAL CHARacters */ /* master copy of private font data */ /* Data in commments: Mini vMac Cell name Mac Roman windows-1252 code page Unicode plain ascii ClStrAppendSubstCStr encoding HTML character entity */ LOCALVAR const ui3b CellData[] = { /* kCellUpA 101 0x41 0x0041 'A' 'A' A */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpB 102 0x42 0x0042 'B' 'B' B */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, /* kCellUpC 103 0x43 0x0043 'C' 'C' C */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpD 104 0x44 0x0044 'D' 'D' D */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, /* kCellUpE 105 0x45 0x0045 'E' 'E' E */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpF 106 0x46 0x0046 'F' 'F' F */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellUpG 107 0x47 0x0047 'G' 'G' G */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x4E, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpH 110 0x48 0x0048 'H' 'H' H */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpI 111 0x49 0x0049 'I' 'I' I */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpJ 112 0x4A 0x004A 'J' 'J' J */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpK 113 0x4B 0x004B 'K' 'K' K */ 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpL 114 0x4C 0x004C 'L' 'L' L */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpM 115 0x4D 0x004D 'M' 'M' M */ 0x00, 0x00, 0x00, 0x82, 0xC6, 0xAA, 0x92, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, /* kCellUpN 116 0x4E 0x004E 'N' 'N' N */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpO 117 0x4F 0x004F 'O' 'O' O */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpP 120 0x50 0x0050 'P' 'P' P */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellUpQ 121 0x51 0x0051 'Q' 'Q' Q */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x10, 0x0C, 0x00, 0x00, /* kCellUpR 122 0x52 0x0052 'R' 'R' R */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpS 123 0x53 0x0053 'S' 'S' S */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpT 124 0x54 0x0054 'T' 'T' T */ 0x00, 0x00, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpU 125 0x55 0x0055 'U' 'U' U */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpV 126 0x56 0x0056 'V' 'V' V */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x44, 0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellUpW 127 0x57 0x0057 'W' 'W' W */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x5A, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpX 130 0x58 0x0058 'X' 'X' X */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpY 131 0x59 0x0059 'Y' 'Y' Y */ 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpZ 132 0x5A 0x005A 'Z' 'Z' Z */ 0x00, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoA 141 0x61 0x0061 'a' 'a' a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoB 142 0x62 0x0062 'b' 'b' b */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, /* kCellLoC 143 0x63 0x0063 'c' 'c' c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoD 144 0x64 0x0064 'd' 'd' d */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellLoE 145 0x65 0x0065 'e' 'e' e */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoF 146 0x66 0x0066 'f' 'f' f */ 0x00, 0x00, 0x00, 0x0E, 0x10, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoG 147 0x67 0x0067 'g' 'g' g */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, /* kCellLoH 150 0x68 0x0068 'h' 'h' h */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoI 151 0x69 0x0069 'i' 'i' i */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoJ 152 0x6A 0x006A 'j' 'j' j */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, /* kCellLoK 153 0x6B 0x006B 'k' 'k' k */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoL 154 0x6C 0x006C 'l' 'l' l */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellLoM 155 0x6D 0x006D 'm' 'm' m */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, /* kCellLoN 156 0x6E 0x006E 'n' 'n' n */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoO 157 0x6F 0x006F 'o' 'o' o */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoP 160 0x70 0x0070 'p' 'p' p */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x00, 0x00, /* kCellLoQ 161 0x71 0x0071 'q' 'q' q */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x00, 0x00, /* kCellLoR 162 0x72 0x0072 'r' 'r' r */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x62, 0x42, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellLoS 163 0x73 0x0073 's' 's' s */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoT 164 0x74 0x0074 't' 't' t */ 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00, 0x00, 0x00, /* kCellLoU 165 0x75 0x0075 'u' 'u' u */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoV 166 0x76 0x0076 'v' 'v' v */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellLoW 167 0x77 0x0077 'w' 'w' w */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x92, 0x92, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00, /* kCellLoX 170 0x78 0x0078 'x' 'x' x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoY 171 0x79 0x0079 'y' 'y' y */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, /* kCellLoZ 172 0x7A 0x007A 'z' 'z' z */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellDigit0 060 0x30 0x0030 '0' '0' 0 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit1 061 0x31 0x0031 '1' '1' 1 */ 0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellDigit2 062 0x32 0x0032 '2' '2' 2 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellDigit3 063 0x33 0x0033 '3' '3' 3 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x0C, 0x02, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit4 064 0x34 0x0034 '4' '4' 4 */ 0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x24, 0x7E, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* kCellDigit5 065 0x35 0x0035 '5' '5' 5 */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x7C, 0x02, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit6 066 0x36 0x0036 '6' '6' 6 */ 0x00, 0x00, 0x00, 0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit7 067 0x37 0x0037 '7' '7' 7 */ 0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellDigit8 070 0x38 0x0038 '8' '8' 8 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit9 071 0x39 0x0039 '9' '9' 9 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* kCellExclamation 041 0x21 0x0021 '!' '!' ! */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellAmpersand 046 0x26 0x0026 '&' '&' amp */ 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x50, 0x20, 0x50, 0x4A, 0x44, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellApostrophe 047 0x27 0x0027 '\047' ';la' apos */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellLeftParen 050 0x28 0x0028 '(' '(' ( */ 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, /* kCellRightParen 051 0x29 0x0029 ')' ')' ) */ 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, /* kCellComma 054 0x2C 0x002C ',' ',' , */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, /* kCellHyphen 055 0x2D 0x002D '-' '-' - */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellPeriod 056 0x2E 0x002E '.' '.' . */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellSlash 057 0x2F 0x002F '/' '/' / */ 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00, 0x00, /* kCellColon 072 0x3A 0x003A ':' ':' : */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellSemicolon 073 0x3B 0x003B ';' ';ls' #59 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, /* kCellQuestion 077 0x3F 0x003F '?' '?' ? */ 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellEllipsis 311 0x85 0x2026 '_' ';ll' #8230 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, /* kCellUnderscore 137 0x5F 0x005F '_' '_' _ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, /* kCellLeftDQuote 322 0x93 0x201C '"' ';[' ldquo */ 0x00, 0x00, 0x00, 0x24, 0x48, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellRightDQuote 323 0x94 0x201D '"' ';{' rdquo */ 0x00, 0x00, 0x00, 0x36, 0x12, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellLeftSQuote 324 0x91 0x2018 '\047' ';]' lsquo */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellRightSQuote 325 0x92 0x2019 '\047' ';}' rsquo */ 0x00, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellCopyright 251 0xA9 0x00A9 'c' ';g' copy */ 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x9A, 0xA2, 0xA2, 0x9A, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, /* kCellSpace 040 0x20 0x0020 '\040' '' #32 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #if NeedIntlChars /* kCellUpADiaeresis 200 0xC4 0x00C4 'A' ';uA' Auml */ 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpARing 201 0xC5 0x00C5 'A' ';A' Aring */ 0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpCCedilla 202 0xC7 0x00C7 'C' ';C' Ccedil */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00, /* kCellUpEAcute 203 0xC9 0x00C9 'E' ';eE' Eacute */ 0x08, 0x10, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpNTilde 204 0xD1 0x00D1 'N' ';nN' Ntilde */ 0x32, 0x4C, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpODiaeresis 205 0xD6 0x00D6 'O' ';uO' Ouml */ 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUDiaeresis 206 0xDC 0x00DC 'U' ';uU' Uuml */ 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoAAcute 207 0xE1 0x00E1 'a' ';ea' aacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoAGrave 210 0xE0 0x00E0 'a' ';`a' agrave */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoACircumflex 211 0xE2 0x00E2 'a' ';ia' acirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoADiaeresis 212 0xE4 0x00E4 'a' ';ua' auml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoATilde 213 0xE3 0x00E3 'a' ';na' atilde */ 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoARing 214 0xE5 0x00E5 'a' ';a' aring */ 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoCCedilla 215 0xE7 0x00E7 'c' ';c' ccedil */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00, /* kCellLoEAcute 216 0xE9 0x00E9 'e' ';ee' eacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoEGrave 217 0xE8 0x00E8 'e' ';`e' egrave */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoECircumflex 220 0xEA 0x00EA 'e' ';ie' ecirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoEDiaeresis 221 0xEB 0x00EB 'e' ';ue' euml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoIAcute 222 0xED 0x00ED 'i' ';ei' iacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoIGrave 223 0xEC 0x00EC 'i' ';`i' igrave */ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoICircumflex 224 0xEE 0x00EE 'i' ';ii' icirc */ 0x00, 0x00, 0x00, 0x10, 0x28, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoIDiaeresis 225 0xEF 0x00EF 'i' ';ui' iuml */ 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoNTilde 226 0xF1 0x00F1 'n' ';nn' ntilde */ 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoOAcute 227 0xF3 0x00F3 'o' ';eo' oacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOGrave 230 0xF2 0x00F2 'o' ';`o' ograve */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOCircumflex 231 0xF4 0x00F4 'o' ';io' ocirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoODiaeresis 232 0xF6 0x00F6 'o' ';uo' ouml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOTilde 233 0xF5 0x00F5 'o' ';no' otilde */ 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoUAcute 234 0xFA 0x00FA 'u' ';eu' uacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoUGrave 235 0xF9 0x00F9 'u' ';`u' ugrave */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoUCircumflex 236 0xFB 0x00FB 'u' ';iu' ucirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoUDiaeresis 237 0xFC 0x00FC 'u' ';uu' uuml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellUpAE 256 0xC6 0x00C6 '?' ';lE' AElig */ 0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x7C, 0x48, 0x48, 0x48, 0x4E, 0x00, 0x00, 0x00, 0x00, /* kCellUpOStroke 257 0xD8 0x00D8 'O' ';O' Oslash */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x46, 0x5A, 0x62, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoAE 276 0xE6 0x00E6 '?' ';le' aelig */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52, 0x5E, 0x50, 0x52, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOStroke 277 0xF8 0x00F8 'o' ';o' oslash */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x46, 0x5A, 0x62, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellInvQuestion 300 0xBF 0x00BF '?' ';?' iquest */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, /* kCellInvExclam 301 0xA1 0x00A1 '!' ';1' iexcl */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpAGrave 313 0xC0 0x00C0 'A' ';`A' Agrave */ 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpATilde 314 0xC3 0x00C3 'A' ';nA' Atilde */ 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpOTilde 315 0xD5 0x00D5 'O' ';nO' Otilde */ 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpLigatureOE 316 0x8C 0x0152 '?' ';Q' OElig */ 0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x4E, 0x48, 0x48, 0x48, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellLoLigatureOE 317 0x9C 0x0153 '?' ';q' oelig */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x52, 0x5E, 0x50, 0x52, 0x2C, 0x00, 0x00, 0x00, 0x00, /* kCellLoYDiaeresis 330 0xFF 0x00FF 'y' ';uy' yuml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, /* kCellUpYDiaeresis 331 0x9F 0x0178 'Y' ';uY' Yuml */ 0x00, 0x14, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpACircumflex 345 0xC2 0x00C2 'A' ';iA' Acirc */ 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpECircumflex 346 0xCA 0x00CA 'E' ';iE' Ecirc */ 0x18, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpAAcute 347 0xC1 0x00C1 'A' ';eA' Aacute */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpEDiaeresis 350 0xCB 0x00CB 'E' ';uE' Euml */ 0x00, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpEGrave 351 0xC8 0x00C8 'E' ';`E' Egrave */ 0x10, 0x08, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpIAcute 352 0xCD 0x00CD 'A' ';eI' Iacute */ 0x04, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpICircumflex 353 0xCE 0x00CE 'I' ';iI' Icirc */ 0x08, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpIDiaeresis 354 0xCF 0x00CF 'I' ';uI' Iuml */ 0x00, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpIGrave 355 0xCC 0x00CC 'I' ';`I' Igrave */ 0x10, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpOAcute 356 0xD3 0x00D3 'O' ';eO' Oacute */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpOCircumflex 357 0xD4 0x00D4 'O' ';iO' Ocirc */ 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpOGrave 361 0xD2 0x00D2 'O' ';`O' Ograve */ 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUAcute 362 0xDA 0x00DA 'U' ';eU' Uacute */ 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUCircumflex 363 0xDB 0x00DB 'U' ';iU' Ucirc */ 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUGrave 364 0xD9 0x00D9 'U' ';`U' Ugrave */ 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellSharpS 247 0xDF 0x00DF 'B' ';s' szlig */ 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x44, 0x44, 0x42, 0x42, 0x42, 0x5C, 0x40, 0x00, 0x00, 0x00, /* kCellUpACedille 260 ? 0x0104 'A' ';dA' #260 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x04, 0x04, 0x02, 0x00, /* kCellLoACedille 261 ? 0x0105 'a' ';da' #261 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x04, 0x04, 0x02, 0x00, /* kCellUpCAcute 262 ? 0x0106 'C' ';eC' #262 */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoCAcute 263 ? 0x0107 'c' ';ec' #263 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpECedille 264 ? 0x0118 'E' ';dE' #280 */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x04, 0x04, 0x02, 0x00, /* kCellLoECedille 265 ? 0x0119 'e' ';de' #281 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x04, 0x00, /* kCellUpLBar 266 ? 0x0141 'L' ';dL' #321 */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x60, 0x40, 0xC0, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoLBar 267 ? 0x0142 'l' ';dl' #322 */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x0C, 0x08, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpNAcute 270 ? 0x0143 'N' ';eN' #323 */ 0x08, 0x10, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoNAcute 271 ? 0x0144 'n' ';en' #324 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpSAcute 272 ? 0x015A 'S' ';eS' #346 */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoSAcute 273 ? 0x015B 's' ';es' #347 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpZAcute 274 ? 0x0179 'Z' ';eZ' #377 */ 0x08, 0x10, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoZAcute 275 ? 0x017A 'z' ';ez' #378 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpZDot 276 ? 0x017B 'Z' ';dZ' #379 */ 0x10, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoZDot 277 ? 0x017C 'z' ';dz' #380 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, #endif /* kCellUpperLeft */ 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* kCellUpperMiddle */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellMiddleLeft */ 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* kCellMiddleLeft */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* kCellMiddleRight */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* kCellLowerLeft */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, /* kCellLowerMiddle */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, /* kCellLowerRight */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, /* kCellGraySep */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon00 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, /* kCellIcon01 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x18, /* kCellIcon02 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x30, /* kCellIcon03 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x90, 0x90, 0x90, /* kCellIcon10 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* kCellIcon11 */ 0x18, 0x18, 0x19, 0x1B, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon12 */ 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, /* kCellIcon13 */ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /* kCellIcon20 */ 0x08, 0x08, 0x08, 0x07, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon21 */ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon22 */ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon23 */ 0x10, 0x10, 0x10, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #if EnableAltKeysMode /* kInsertText00 */ 0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF, /* kInsertText01 */ 0xFF, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x19, 0x1B, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0x00, 0xFF, /* kInsertText02 */ 0xFF, 0x00, 0x00, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, /* kInsertText03 */ 0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF, /* kInsertText04 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF, #endif 0x00 /* just so last above line can end in ',' */ }; enum { kCellUpA, kCellUpB, kCellUpC, kCellUpD, kCellUpE, kCellUpF, kCellUpG, kCellUpH, kCellUpI, kCellUpJ, kCellUpK, kCellUpL, kCellUpM, kCellUpN, kCellUpO, kCellUpP, kCellUpQ, kCellUpR, kCellUpS, kCellUpT, kCellUpU, kCellUpV, kCellUpW, kCellUpX, kCellUpY, kCellUpZ, kCellLoA, kCellLoB, kCellLoC, kCellLoD, kCellLoE, kCellLoF, kCellLoG, kCellLoH, kCellLoI, kCellLoJ, kCellLoK, kCellLoL, kCellLoM, kCellLoN, kCellLoO, kCellLoP, kCellLoQ, kCellLoR, kCellLoS, kCellLoT, kCellLoU, kCellLoV, kCellLoW, kCellLoX, kCellLoY, kCellLoZ, kCellDigit0, kCellDigit1, kCellDigit2, kCellDigit3, kCellDigit4, kCellDigit5, kCellDigit6, kCellDigit7, kCellDigit8, kCellDigit9, kCellExclamation, kCellAmpersand, kCellApostrophe, kCellLeftParen, kCellRightParen, kCellComma, kCellHyphen, kCellPeriod, kCellSlash, kCellColon, kCellSemicolon, kCellQuestion, kCellEllipsis, kCellUnderscore, kCellLeftDQuote, kCellRightDQuote, kCellLeftSQuote, kCellRightSQuote, kCellCopyright, kCellSpace, #if NeedIntlChars kCellUpADiaeresis, kCellUpARing, kCellUpCCedilla, kCellUpEAcute, kCellUpNTilde, kCellUpODiaeresis, kCellUpUDiaeresis, kCellLoAAcute, kCellLoAGrave, kCellLoACircumflex, kCellLoADiaeresis, kCellLoATilde, kCellLoARing, kCellLoCCedilla, kCellLoEAcute, kCellLoEGrave, kCellLoECircumflex, kCellLoEDiaeresis, kCellLoIAcute, kCellLoIGrave, kCellLoICircumflex, kCellLoIDiaeresis, kCellLoNTilde, kCellLoOAcute, kCellLoOGrave, kCellLoOCircumflex, kCellLoODiaeresis, kCellLoOTilde, kCellLoUAcute, kCellLoUGrave, kCellLoUCircumflex, kCellLoUDiaeresis, kCellUpAE, kCellUpOStroke, kCellLoAE, kCellLoOStroke, kCellInvQuestion, kCellInvExclam, kCellUpAGrave, kCellUpATilde, kCellUpOTilde, kCellUpLigatureOE, kCellLoLigatureOE, kCellLoYDiaeresis, kCellUpYDiaeresis, kCellUpACircumflex, kCellUpECircumflex, kCellUpAAcute, kCellUpEDiaeresis, kCellUpEGrave, kCellUpIAcute, kCellUpICircumflex, kCellUpIDiaeresis, kCellUpIGrave, kCellUpOAcute, kCellUpOCircumflex, kCellUpOGrave, kCellUpUAcute, kCellUpUCircumflex, kCellUpUGrave, kCellSharpS, kCellUpACedille, kCellLoACedille, kCellUpCAcute, kCellLoCAcute, kCellUpECedille, kCellLoECedille, kCellUpLBar, kCellLoLBar, kCellUpNAcute, kCellLoNAcute, kCellUpSAcute, kCellLoSAcute, kCellUpZAcute, kCellLoZAcute, kCellUpZDot, kCellLoZDot, #endif kCellUpperLeft, kCellUpperMiddle, kCellUpperRight, kCellMiddleLeft, kCellMiddleRight, kCellLowerLeft, kCellLowerMiddle, kCellLowerRight, kCellGraySep, kCellIcon00, kCellIcon01, kCellIcon02, kCellIcon03, kCellIcon10, kCellIcon11, kCellIcon12, kCellIcon13, kCellIcon20, kCellIcon21, kCellIcon22, kCellIcon23, #if EnableAltKeysMode kInsertText00, kInsertText01, kInsertText02, kInsertText03, kInsertText04, #endif kNumCells }; #if UseActvCode && 0 #define UseActvFile 1 #else #define UseActvFile 0 #endif #ifndef NeedCell2MacAsciiMap #if UseActvCode || EnableDemoMsg #define NeedCell2MacAsciiMap 1 #else #define NeedCell2MacAsciiMap 0 #endif #endif #if NeedCell2MacAsciiMap /* Mac Roman character set */ LOCALVAR const char Cell2MacAsciiMap[] = { '\101', /* kCellUpA */ '\102', /* kCellUpB */ '\103', /* kCellUpC */ '\104', /* kCellUpD */ '\105', /* kCellUpE */ '\106', /* kCellUpF */ '\107', /* kCellUpG */ '\110', /* kCellUpH */ '\111', /* kCellUpI */ '\112', /* kCellUpJ */ '\113', /* kCellUpK */ '\114', /* kCellUpL */ '\115', /* kCellUpM */ '\116', /* kCellUpN */ '\117', /* kCellUpO */ '\120', /* kCellUpP */ '\121', /* kCellUpQ */ '\122', /* kCellUpR */ '\123', /* kCellUpS */ '\124', /* kCellUpT */ '\125', /* kCellUpU */ '\126', /* kCellUpV */ '\127', /* kCellUpW */ '\130', /* kCellUpX */ '\131', /* kCellUpY */ '\132', /* kCellUpZ */ '\141', /* kCellLoA */ '\142', /* kCellLoB */ '\143', /* kCellLoC */ '\144', /* kCellLoD */ '\145', /* kCellLoE */ '\146', /* kCellLoF */ '\147', /* kCellLoG */ '\150', /* kCellLoH */ '\151', /* kCellLoI */ '\152', /* kCellLoJ */ '\153', /* kCellLoK */ '\154', /* kCellLoL */ '\155', /* kCellLoM */ '\156', /* kCellLoN */ '\157', /* kCellLoO */ '\160', /* kCellLoP */ '\161', /* kCellLoQ */ '\162', /* kCellLoR */ '\163', /* kCellLoS */ '\164', /* kCellLoT */ '\165', /* kCellLoU */ '\166', /* kCellLoV */ '\167', /* kCellLoW */ '\170', /* kCellLoX */ '\171', /* kCellLoY */ '\172', /* kCellLoZ */ '\060', /* kCellDigit0 */ '\061', /* kCellDigit1 */ '\062', /* kCellDigit2 */ '\063', /* kCellDigit3 */ '\064', /* kCellDigit4 */ '\065', /* kCellDigit5 */ '\066', /* kCellDigit6 */ '\067', /* kCellDigit7 */ '\070', /* kCellDigit8 */ '\071', /* kCellDigit9 */ '\041', /* kCellExclamation */ '\046', /* kCellAmpersand */ '\047', /* kCellApostrophe */ '\050', /* kCellLeftParen */ '\051', /* kCellRightParen */ '\054', /* kCellComma */ '\055', /* kCellHyphen */ '\056', /* kCellPeriod */ '\057', /* kCellSlash */ '\072', /* kCellColon */ '\073', /* kCellSemicolon */ '\077', /* kCellQuestion */ '\311', /* kCellEllipsis */ '\137', /* kCellUnderscore */ '\322', /* kCellLeftDQuote */ '\323', /* kCellRightDQuote */ '\324', /* kCellLeftSQuote */ '\325', /* kCellRightSQuote */ '\251', /* kCellCopyright */ '\040', /* kCellSpace */ #if NeedIntlChars '\200', /* kCellUpADiaeresis */ '\201', /* kCellUpARing */ '\202', /* kCellUpCCedilla */ '\203', /* kCellUpEAcute */ '\204', /* kCellUpNTilde */ '\205', /* kCellUpODiaeresis */ '\206', /* kCellUpUDiaeresis */ '\207', /* kCellLoAAcute */ '\210', /* kCellLoAGrave */ '\211', /* kCellLoACircumflex */ '\212', /* kCellLoADiaeresis */ '\213', /* kCellLoATilde */ '\214', /* kCellLoARing */ '\215', /* kCellLoCCedilla */ '\216', /* kCellLoEAcute */ '\217', /* kCellLoEGrave */ '\220', /* kCellLoECircumflex */ '\221', /* kCellLoEDiaeresis */ '\222', /* kCellLoIAcute */ '\223', /* kCellLoIGrave */ '\224', /* kCellLoICircumflex */ '\225', /* kCellLoIDiaeresis */ '\226', /* kCellLoNTilde */ '\227', /* kCellLoOAcute */ '\230', /* kCellLoOGrave */ '\231', /* kCellLoOCircumflex */ '\232', /* kCellLoODiaeresis */ '\233', /* kCellLoOTilde */ '\234', /* kCellLoUAcute */ '\235', /* kCellLoUGrave */ '\236', /* kCellLoUCircumflex */ '\237', /* kCellLoUDiaeresis */ '\256', /* kCellUpAE */ '\257', /* kCellUpOStroke */ '\276', /* kCellLoAE */ '\277', /* kCellLoOStroke */ '\300', /* kCellInvQuestion */ '\301', /* kCellInvExclam */ '\313', /* kCellUpAGrave */ '\314', /* kCellUpATilde */ '\315', /* kCellUpOTilde */ '\316', /* kCellUpLigatureOE */ '\317', /* kCellLoLigatureOE */ '\330', /* kCellLoYDiaeresis */ '\331', /* kCellUpYDiaeresis */ '\345', /* kCellUpACircumflex */ '\346', /* kCellUpECircumflex */ '\347', /* kCellUpAAcute */ '\350', /* kCellUpEDiaeresis */ '\351', /* kCellUpEGrave */ '\352', /* kCellUpIAcute */ '\353', /* kCellUpICircumflex */ '\354', /* kCellUpIDiaeresis */ '\355', /* kCellUpIGrave */ '\356', /* kCellUpOAcute */ '\357', /* kCellUpOCircumflex */ '\361', /* kCellUpOGrave */ '\362', /* kCellUpUAcute */ '\363', /* kCellUpUCircumflex */ '\364', /* kCellUpUGrave */ '\247', /* kCellSharpS */ '\260', /* kCellUpACedille */ '\261', /* kCellLoACedille */ '\262', /* kCellUpCAcute */ '\263', /* kCellLoCAcute */ '\264', /* kCellUpECedille */ '\265', /* kCellLoECedille */ '\266', /* kCellUpLBar */ '\267', /* kCellLoLBar */ '\270', /* kCellUpNAcute */ '\271', /* kCellLoNAcute */ '\272', /* kCellUpSAcute */ '\273', /* kCellLoSAcute */ '\274', /* kCellUpZAcute */ '\275', /* kCellLoZAcute */ '\276', /* kCellUpZDot */ '\277', /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif #ifndef NeedCell2WinAsciiMap #define NeedCell2WinAsciiMap 0 #endif #if NeedCell2WinAsciiMap /* Windows character set (windows-1252 code page) */ LOCALVAR const ui3b Cell2WinAsciiMap[] = { 0x41, /* kCellUpA */ 0x42, /* kCellUpB */ 0x43, /* kCellUpC */ 0x44, /* kCellUpD */ 0x45, /* kCellUpE */ 0x46, /* kCellUpF */ 0x47, /* kCellUpG */ 0x48, /* kCellUpH */ 0x49, /* kCellUpI */ 0x4A, /* kCellUpJ */ 0x4B, /* kCellUpK */ 0x4C, /* kCellUpL */ 0x4D, /* kCellUpM */ 0x4E, /* kCellUpN */ 0x4F, /* kCellUpO */ 0x50, /* kCellUpP */ 0x51, /* kCellUpQ */ 0x52, /* kCellUpR */ 0x53, /* kCellUpS */ 0x54, /* kCellUpT */ 0x55, /* kCellUpU */ 0x56, /* kCellUpV */ 0x57, /* kCellUpW */ 0x58, /* kCellUpX */ 0x59, /* kCellUpY */ 0x5A, /* kCellUpZ */ 0x61, /* kCellLoA */ 0x62, /* kCellLoB */ 0x63, /* kCellLoC */ 0x64, /* kCellLoD */ 0x65, /* kCellLoE */ 0x66, /* kCellLoF */ 0x67, /* kCellLoG */ 0x68, /* kCellLoH */ 0x69, /* kCellLoI */ 0x6A, /* kCellLoJ */ 0x6B, /* kCellLoK */ 0x6C, /* kCellLoL */ 0x6D, /* kCellLoM */ 0x6E, /* kCellLoN */ 0x6F, /* kCellLoO */ 0x70, /* kCellLoP */ 0x71, /* kCellLoQ */ 0x72, /* kCellLoR */ 0x73, /* kCellLoS */ 0x74, /* kCellLoT */ 0x75, /* kCellLoU */ 0x76, /* kCellLoV */ 0x77, /* kCellLoW */ 0x78, /* kCellLoX */ 0x79, /* kCellLoY */ 0x7A, /* kCellLoZ */ 0x30, /* kCellDigit0 */ 0x31, /* kCellDigit1 */ 0x32, /* kCellDigit2 */ 0x33, /* kCellDigit3 */ 0x34, /* kCellDigit4 */ 0x35, /* kCellDigit5 */ 0x36, /* kCellDigit6 */ 0x37, /* kCellDigit7 */ 0x38, /* kCellDigit8 */ 0x39, /* kCellDigit9 */ 0x21, /* kCellExclamation */ 0x26, /* kCellAmpersand */ 0x27, /* kCellApostrophe */ 0x28, /* kCellLeftParen */ 0x29, /* kCellRightParen */ 0x2C, /* kCellComma */ 0x2D, /* kCellHyphen */ 0x2E, /* kCellPeriod */ 0x2F, /* kCellSlash */ 0x3A, /* kCellColon */ 0x3B, /* kCellSemicolon */ 0x3F, /* kCellQuestion */ 0x85, /* kCellEllipsis */ 0x5F, /* kCellUnderscore */ 0x93, /* kCellLeftDQuote */ 0x94, /* kCellRightDQuote */ 0x91, /* kCellLeftSQuote */ 0x92, /* kCellRightSQuote */ 0xA9, /* kCellCopyright */ 0x20, /* kCellSpace */ #if NeedIntlChars 0xC4, /* kCellUpADiaeresis */ 0xC5, /* kCellUpARing */ 0xC7, /* kCellUpCCedilla */ 0xC9, /* kCellUpEAcute */ 0xD1, /* kCellUpNTilde */ 0xD6, /* kCellUpODiaeresis */ 0xDC, /* kCellUpUDiaeresis */ 0xE1, /* kCellLoAAcute */ 0xE0, /* kCellLoAGrave */ 0xE2, /* kCellLoACircumflex */ 0xE4, /* kCellLoADiaeresis */ 0xE3, /* kCellLoATilde */ 0xE5, /* kCellLoARing */ 0xE7, /* kCellLoCCedilla */ 0xE9, /* kCellLoEAcute */ 0xE8, /* kCellLoEGrave */ 0xEA, /* kCellLoECircumflex */ 0xEB, /* kCellLoEDiaeresis */ 0xED, /* kCellLoIAcute */ 0xEC, /* kCellLoIGrave */ 0xEE, /* kCellLoICircumflex */ 0xEF, /* kCellLoIDiaeresis */ 0xF1, /* kCellLoNTilde */ 0xF3, /* kCellLoOAcute */ 0xF2, /* kCellLoOGrave */ 0xF4, /* kCellLoOCircumflex */ 0xF6, /* kCellLoODiaeresis */ 0xF5, /* kCellLoOTilde */ 0xFA, /* kCellLoUAcute */ 0xF9, /* kCellLoUGrave */ 0xFB, /* kCellLoUCircumflex */ 0xFC, /* kCellLoUDiaeresis */ 0xC6, /* kCellUpAE */ 0xD8, /* kCellUpOStroke */ 0xE6, /* kCellLoAE */ 0xF8, /* kCellLoOStroke */ 0xBF, /* kCellInvQuestion */ 0xA1, /* kCellInvExclam */ 0xC0, /* kCellUpAGrave */ 0xC3, /* kCellUpATilde */ 0xD5, /* kCellUpOTilde */ 0x8C, /* kCellUpLigatureOE */ 0x9C, /* kCellLoLigatureOE */ 0xFF, /* kCellLoYDiaeresis */ 0x9F, /* kCellUpYDiaeresis */ 0xC2, /* kCellUpACircumflex */ 0xCA, /* kCellUpECircumflex */ 0xC1, /* kCellUpAAcute */ 0xCB, /* kCellUpEDiaeresis */ 0xC8, /* kCellUpEGrave */ 0xCD, /* kCellUpIAcute */ 0xCE, /* kCellUpICircumflex */ 0xCF, /* kCellUpIDiaeresis */ 0xCC, /* kCellUpIGrave */ 0xD3, /* kCellUpOAcute */ 0xD4, /* kCellUpOCircumflex */ 0xD2, /* kCellUpOGrave */ 0xDA, /* kCellUpUAcute */ 0xDB, /* kCellUpUCircumflex */ 0xD9, /* kCellUpUGrave */ 0xDF, /* kCellSharpS */ 0x41, /* kCellUpACedille */ 0x61, /* kCellLoACedille */ 0x43, /* kCellUpCAcute */ 0x63, /* kCellLoCAcute */ 0x45, /* kCellUpECedille */ 0x65, /* kCellLoECedille */ 0x4C, /* kCellUpLBar */ 0x6C, /* kCellLoLBar */ 0x4E, /* kCellUpNAcute */ 0x6E, /* kCellLoNAcute */ 0x53, /* kCellUpSAcute */ 0x73, /* kCellLoSAcute */ 0x5A, /* kCellUpZAcute */ 0x7A, /* kCellLoZAcute */ 0x5A, /* kCellUpZDot */ 0x7A, /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif #ifndef NeedCell2PlainAsciiMap #define NeedCell2PlainAsciiMap 0 #endif #if NeedCell2PlainAsciiMap /* Plain ascii - remove accents when possible */ LOCALVAR const char Cell2PlainAsciiMap[] = { 'A', /* kCellUpA */ 'B', /* kCellUpB */ 'C', /* kCellUpC */ 'D', /* kCellUpD */ 'E', /* kCellUpE */ 'F', /* kCellUpF */ 'G', /* kCellUpG */ 'H', /* kCellUpH */ 'I', /* kCellUpI */ 'J', /* kCellUpJ */ 'K', /* kCellUpK */ 'L', /* kCellUpL */ 'M', /* kCellUpM */ 'N', /* kCellUpN */ 'O', /* kCellUpO */ 'P', /* kCellUpP */ 'Q', /* kCellUpQ */ 'R', /* kCellUpR */ 'S', /* kCellUpS */ 'T', /* kCellUpT */ 'U', /* kCellUpU */ 'V', /* kCellUpV */ 'W', /* kCellUpW */ 'X', /* kCellUpX */ 'Y', /* kCellUpY */ 'Z', /* kCellUpZ */ 'a', /* kCellLoA */ 'b', /* kCellLoB */ 'c', /* kCellLoC */ 'd', /* kCellLoD */ 'e', /* kCellLoE */ 'f', /* kCellLoF */ 'g', /* kCellLoG */ 'h', /* kCellLoH */ 'i', /* kCellLoI */ 'j', /* kCellLoJ */ 'k', /* kCellLoK */ 'l', /* kCellLoL */ 'm', /* kCellLoM */ 'n', /* kCellLoN */ 'o', /* kCellLoO */ 'p', /* kCellLoP */ 'q', /* kCellLoQ */ 'r', /* kCellLoR */ 's', /* kCellLoS */ 't', /* kCellLoT */ 'u', /* kCellLoU */ 'v', /* kCellLoV */ 'w', /* kCellLoW */ 'x', /* kCellLoX */ 'y', /* kCellLoY */ 'z', /* kCellLoZ */ '0', /* kCellDigit0 */ '1', /* kCellDigit1 */ '2', /* kCellDigit2 */ '3', /* kCellDigit3 */ '4', /* kCellDigit4 */ '5', /* kCellDigit5 */ '6', /* kCellDigit6 */ '7', /* kCellDigit7 */ '8', /* kCellDigit8 */ '9', /* kCellDigit9 */ '!', /* kCellExclamation */ '&', /* kCellAmpersand */ '\047', /* kCellApostrophe */ '(', /* kCellLeftParen */ ')', /* kCellRightParen */ ',', /* kCellComma */ '-', /* kCellHyphen */ '.', /* kCellPeriod */ '/', /* kCellSlash */ ':', /* kCellColon */ ';', /* kCellSemicolon */ '?', /* kCellQuestion */ '_', /* kCellEllipsis */ '_', /* kCellUnderscore */ '"', /* kCellLeftDQuote */ '"', /* kCellRightDQuote */ '\047', /* kCellLeftSQuote */ '\047', /* kCellRightSQuote */ 'c', /* kCellCopyright */ ' ', /* kCellSpace */ #if NeedIntlChars 'A', /* kCellUpADiaeresis */ 'A', /* kCellUpARing */ 'C', /* kCellUpCCedilla */ 'E', /* kCellUpEAcute */ 'N', /* kCellUpNTilde */ 'O', /* kCellUpODiaeresis */ 'U', /* kCellUpUDiaeresis */ 'a', /* kCellLoAAcute */ 'a', /* kCellLoAGrave */ 'a', /* kCellLoACircumflex */ 'a', /* kCellLoADiaeresis */ 'a', /* kCellLoATilde */ 'a', /* kCellLoARing */ 'c', /* kCellLoCCedilla */ 'e', /* kCellLoEAcute */ 'e', /* kCellLoEGrave */ 'e', /* kCellLoECircumflex */ 'e', /* kCellLoEDiaeresis */ 'i', /* kCellLoIAcute */ 'i', /* kCellLoIGrave */ 'i', /* kCellLoICircumflex */ 'i', /* kCellLoIDiaeresis */ 'n', /* kCellLoNTilde */ 'o', /* kCellLoOAcute */ 'o', /* kCellLoOGrave */ 'o', /* kCellLoOCircumflex */ 'o', /* kCellLoODiaeresis */ 'o', /* kCellLoOTilde */ 'u', /* kCellLoUAcute */ 'u', /* kCellLoUGrave */ 'u', /* kCellLoUCircumflex */ 'u', /* kCellLoUDiaeresis */ '?', /* kCellUpAE */ 'O', /* kCellUpOStroke */ '?', /* kCellLoAE */ 'o', /* kCellLoOStroke */ '?', /* kCellInvQuestion */ '!', /* kCellInvExclam */ 'A', /* kCellUpAGrave */ 'A', /* kCellUpATilde */ 'O', /* kCellUpOTilde */ '?', /* kCellUpLigatureOE */ '?', /* kCellLoLigatureOE */ 'y', /* kCellLoYDiaeresis */ 'Y', /* kCellUpYDiaeresis */ 'A', /* kCellUpACircumflex */ 'E', /* kCellUpECircumflex */ 'A', /* kCellUpAAcute */ 'E', /* kCellUpEDiaeresis */ 'E', /* kCellUpEGrave */ 'A', /* kCellUpIAcute */ 'I', /* kCellUpICircumflex */ 'I', /* kCellUpIDiaeresis */ 'I', /* kCellUpIGrave */ 'O', /* kCellUpOAcute */ 'O', /* kCellUpOCircumflex */ 'O', /* kCellUpOGrave */ 'U', /* kCellUpUAcute */ 'U', /* kCellUpUCircumflex */ 'U', /* kCellUpUGrave */ 'B', /* kCellSharpS */ 'A', /* kCellUpACedille */ 'a', /* kCellLoACedille */ 'C', /* kCellUpCAcute */ 'c', /* kCellLoCAcute */ 'E', /* kCellUpECedille */ 'e', /* kCellLoECedille */ 'L', /* kCellUpLBar */ 'l', /* kCellLoLBar */ 'N', /* kCellUpNAcute */ 'n', /* kCellLoNAcute */ 'S', /* kCellUpSAcute */ 's', /* kCellLoSAcute */ 'Z', /* kCellUpZAcute */ 'z', /* kCellLoZAcute */ 'Z', /* kCellUpZDot */ 'z', /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif #ifndef NeedCell2UnicodeMap #define NeedCell2UnicodeMap 0 #endif #if NeedCell2UnicodeMap /* Unicode character set */ LOCALVAR const ui4b Cell2UnicodeMap[] = { 0x0041, /* kCellUpA */ 0x0042, /* kCellUpB */ 0x0043, /* kCellUpC */ 0x0044, /* kCellUpD */ 0x0045, /* kCellUpE */ 0x0046, /* kCellUpF */ 0x0047, /* kCellUpG */ 0x0048, /* kCellUpH */ 0x0049, /* kCellUpI */ 0x004A, /* kCellUpJ */ 0x004B, /* kCellUpK */ 0x004C, /* kCellUpL */ 0x004D, /* kCellUpM */ 0x004E, /* kCellUpN */ 0x004F, /* kCellUpO */ 0x0050, /* kCellUpP */ 0x0051, /* kCellUpQ */ 0x0052, /* kCellUpR */ 0x0053, /* kCellUpS */ 0x0054, /* kCellUpT */ 0x0055, /* kCellUpU */ 0x0056, /* kCellUpV */ 0x0057, /* kCellUpW */ 0x0058, /* kCellUpX */ 0x0059, /* kCellUpY */ 0x005A, /* kCellUpZ */ 0x0061, /* kCellLoA */ 0x0062, /* kCellLoB */ 0x0063, /* kCellLoC */ 0x0064, /* kCellLoD */ 0x0065, /* kCellLoE */ 0x0066, /* kCellLoF */ 0x0067, /* kCellLoG */ 0x0068, /* kCellLoH */ 0x0069, /* kCellLoI */ 0x006A, /* kCellLoJ */ 0x006B, /* kCellLoK */ 0x006C, /* kCellLoL */ 0x006D, /* kCellLoM */ 0x006E, /* kCellLoN */ 0x006F, /* kCellLoO */ 0x0070, /* kCellLoP */ 0x0071, /* kCellLoQ */ 0x0072, /* kCellLoR */ 0x0073, /* kCellLoS */ 0x0074, /* kCellLoT */ 0x0075, /* kCellLoU */ 0x0076, /* kCellLoV */ 0x0077, /* kCellLoW */ 0x0078, /* kCellLoX */ 0x0079, /* kCellLoY */ 0x007A, /* kCellLoZ */ 0x0030, /* kCellDigit0 */ 0x0031, /* kCellDigit1 */ 0x0032, /* kCellDigit2 */ 0x0033, /* kCellDigit3 */ 0x0034, /* kCellDigit4 */ 0x0035, /* kCellDigit5 */ 0x0036, /* kCellDigit6 */ 0x0037, /* kCellDigit7 */ 0x0038, /* kCellDigit8 */ 0x0039, /* kCellDigit9 */ 0x0021, /* kCellExclamation */ 0x0026, /* kCellAmpersand */ 0x0027, /* kCellApostrophe */ 0x0028, /* kCellLeftParen */ 0x0029, /* kCellRightParen */ 0x002C, /* kCellComma */ 0x002D, /* kCellHyphen */ 0x002E, /* kCellPeriod */ 0x002F, /* kCellSlash */ 0x003A, /* kCellColon */ 0x003B, /* kCellSemicolon */ 0x003F, /* kCellQuestion */ 0x2026, /* kCellEllipsis */ 0x005F, /* kCellUnderscore */ 0x201C, /* kCellLeftDQuote */ 0x201D, /* kCellRightDQuote */ 0x2018, /* kCellLeftSQuote */ 0x2019, /* kCellRightSQuote */ 0x00A9, /* kCellCopyright */ 0x0020, /* kCellSpace */ #if NeedIntlChars 0x00C4, /* kCellUpADiaeresis */ 0x00C5, /* kCellUpARing */ 0x00C7, /* kCellUpCCedilla */ 0x00C9, /* kCellUpEAcute */ 0x00D1, /* kCellUpNTilde */ 0x00D6, /* kCellUpODiaeresis */ 0x00DC, /* kCellUpUDiaeresis */ 0x00E1, /* kCellLoAAcute */ 0x00E0, /* kCellLoAGrave */ 0x00E2, /* kCellLoACircumflex */ 0x00E4, /* kCellLoADiaeresis */ 0x00E3, /* kCellLoATilde */ 0x00E5, /* kCellLoARing */ 0x00E7, /* kCellLoCCedilla */ 0x00E9, /* kCellLoEAcute */ 0x00E8, /* kCellLoEGrave */ 0x00EA, /* kCellLoECircumflex */ 0x00EB, /* kCellLoEDiaeresis */ 0x00ED, /* kCellLoIAcute */ 0x00EC, /* kCellLoIGrave */ 0x00EE, /* kCellLoICircumflex */ 0x00EF, /* kCellLoIDiaeresis */ 0x00F1, /* kCellLoNTilde */ 0x00F3, /* kCellLoOAcute */ 0x00F2, /* kCellLoOGrave */ 0x00F4, /* kCellLoOCircumflex */ 0x00F6, /* kCellLoODiaeresis */ 0x00F5, /* kCellLoOTilde */ 0x00FA, /* kCellLoUAcute */ 0x00F9, /* kCellLoUGrave */ 0x00FB, /* kCellLoUCircumflex */ 0x00FC, /* kCellLoUDiaeresis */ 0x00C6, /* kCellUpAE */ 0x00D8, /* kCellUpOStroke */ 0x00E6, /* kCellLoAE */ 0x00F8, /* kCellLoOStroke */ 0x00BF, /* kCellInvQuestion */ 0x00A1, /* kCellInvExclam */ 0x00C0, /* kCellUpAGrave */ 0x00C3, /* kCellUpATilde */ 0x00D5, /* kCellUpOTilde */ 0x0152, /* kCellUpLigatureOE */ 0x0153, /* kCellLoLigatureOE */ 0x00FF, /* kCellLoYDiaeresis */ 0x0178, /* kCellUpYDiaeresis */ 0x00C2, /* kCellUpACircumflex */ 0x00CA, /* kCellUpECircumflex */ 0x00C1, /* kCellUpAAcute */ 0x00CB, /* kCellUpEDiaeresis */ 0x00C8, /* kCellUpEGrave */ 0x00CD, /* kCellUpIAcute */ 0x00CE, /* kCellUpICircumflex */ 0x00CF, /* kCellUpIDiaeresis */ 0x00CC, /* kCellUpIGrave */ 0x00D3, /* kCellUpOAcute */ 0x00D4, /* kCellUpOCircumflex */ 0x00D2, /* kCellUpOGrave */ 0x00DA, /* kCellUpUAcute */ 0x00DB, /* kCellUpUCircumflex */ 0x00D9, /* kCellUpUGrave */ 0x00DF, /* kCellSharpS */ 0x0104, /* kCellUpACedille */ 0x0105, /* kCellLoACedille */ 0x0106, /* kCellUpCAcute */ 0x0107, /* kCellLoCAcute */ 0x0118, /* kCellUpECedille */ 0x0119, /* kCellLoECedille */ 0x0141, /* kCellUpLBar */ 0x0142, /* kCellLoLBar */ 0x0143, /* kCellUpNAcute */ 0x0144, /* kCellLoNAcute */ 0x015A, /* kCellUpSAcute */ 0x015B, /* kCellLoSAcute */ 0x0179, /* kCellUpZAcute */ 0x017A, /* kCellLoZAcute */ 0x017B, /* kCellUpZDot */ 0x017C, /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif LOCALVAR blnr SpeedStopped = falseblnr; LOCALVAR blnr RunInBackground = (WantInitRunInBackground != 0); #if VarFullScreen LOCALVAR blnr WantFullScreen = (WantInitFullScreen != 0); #endif #if EnableMagnify LOCALVAR blnr WantMagnify = (WantInitMagnify != 0); #endif #if NeedRequestInsertDisk LOCALVAR blnr RequestInsertDisk = falseblnr; #endif #if UseControlKeys LOCALVAR blnr ControlKeyPressed = falseblnr; #endif LOCALFUNC char * GetSubstitutionStr(char x) { char *s; switch (x) { case 'w': s = kStrHomePage; break; case 'y': s = kStrCopyrightYear; break; case 'p': s = kStrAppName; break; case 'v': s = kAppVariationStr; break; case 'r': s = RomFileName; break; #if UseControlKeys case 'k': if (ControlKeyPressed) { s = kStrPressed; } else { s = kStrReleased; } break; #endif #if EnableMagnify case 'g': if (WantMagnify) { s = kStrOn; } else { s = kStrOff; } break; #endif #if VarFullScreen case 'f': if (WantFullScreen) { s = kStrOn; } else { s = kStrOff; } break; #endif case 'b': if (RunInBackground) { s = kStrOn; } else { s = kStrOff; } break; case 'h': if (SpeedStopped) { s = kStrStoppedOn; } else { s = kStrStoppedOff; } break; #if EnableAutoSlow case 'l': if (WantNotAutoSlow) { s = kStrStoppedOff; } else { s = kStrStoppedOn; } break; #endif case 's': switch (SpeedValue) { case 0: s = "1x"; break; case 1: s = "2x"; break; case 2: s = "4x"; break; case 3: s = "8x"; break; case 4: s = "16x"; break; case 5: s = "32x"; break; default: s = kStrSpeedValueAllOut; break; } break; default: s = "???"; break; } return s; } #define ClStrMaxLength 512 LOCALPROC ClStrAppendChar(int *L0, ui3b *r, ui3b c) { unsigned short L = *L0; if (ClStrMaxLength != L) { r[L] = c; L++; *L0 = L; } } LOCALPROC ClStrAppendSubstCStr(int *L, ui3b *r, char *s) { char *p = s; char c; ui3b x; while ((c = *p++) != 0) { if (c == '^') { if ((c = *p++) == 0) { return; /* oops, unexpected end of string, abort */ } else if (c == '^') { ClStrAppendChar(L, r, c); } else { ClStrAppendSubstCStr(L, r, GetSubstitutionStr(c)); } } else if (c == ';') { switch (*p++) { case 'g': x = kCellCopyright; break; case 'l': switch (*p++) { case 'a': x = kCellApostrophe; break; case 'l': x = kCellEllipsis; break; case 's': x = kCellSemicolon; break; #if NeedIntlChars case 'E': x = kCellUpAE; break; case 'e': x = kCellLoAE; break; #endif default: return; break; } break; case '[': x = kCellLeftDQuote; break; case '{': x = kCellRightDQuote; break; case ']': x = kCellLeftSQuote; break; case '}': x = kCellRightSQuote; break; #if NeedIntlChars case '?': x = kCellInvQuestion; break; case 'A': x = kCellUpARing; break; case 'C': x = kCellUpCCedilla; break; case 'O': x = kCellUpOStroke; break; case 'Q': x = kCellUpLigatureOE; break; case '`': switch (*p++) { case 'A': x = kCellUpAGrave; break; case 'E': x = kCellUpEGrave; break; case 'I': x = kCellUpIGrave; break; case 'O': x = kCellUpOGrave; break; case 'U': x = kCellUpUGrave; break; case 'a': x = kCellLoAGrave; break; case 'e': x = kCellLoEGrave; break; case 'i': x = kCellLoIGrave; break; case 'o': x = kCellLoOGrave; break; case 'u': x = kCellLoUGrave; break; default: return; break; } break; case 'a': x = kCellLoARing; break; case 'c': x = kCellLoCCedilla; break; case 'd': switch (*p++) { case 'A': x = kCellUpACedille; break; case 'a': x = kCellLoACedille; break; case 'E': x = kCellUpECedille; break; case 'e': x = kCellLoECedille; break; case 'L': x = kCellUpLBar; break; case 'l': x = kCellLoLBar; break; case 'Z': x = kCellUpZDot; break; case 'z': x = kCellLoZDot; break; default: return; break; } break; case 'e': switch (*p++) { case 'A': x = kCellUpAAcute; break; case 'E': x = kCellUpEAcute; break; case 'I': x = kCellUpIAcute; break; case 'O': x = kCellUpOAcute; break; case 'U': x = kCellUpUAcute; break; case 'a': x = kCellLoAAcute; break; case 'e': x = kCellLoEAcute; break; case 'i': x = kCellLoIAcute; break; case 'o': x = kCellLoOAcute; break; case 'u': x = kCellLoUAcute; break; case 'C': x = kCellUpCAcute; break; case 'c': x = kCellLoCAcute; break; case 'N': x = kCellUpNAcute; break; case 'n': x = kCellLoNAcute; break; case 'S': x = kCellUpSAcute; break; case 's': x = kCellLoSAcute; break; case 'Z': x = kCellUpZAcute; break; case 'z': x = kCellLoZAcute; break; default: return; break; } break; case 'i': switch (*p++) { case 'A': x = kCellUpACircumflex; break; case 'E': x = kCellUpECircumflex; break; case 'I': x = kCellUpICircumflex; break; case 'O': x = kCellUpOCircumflex; break; case 'U': x = kCellUpUCircumflex; break; case 'a': x = kCellLoACircumflex; break; case 'e': x = kCellLoECircumflex; break; case 'i': x = kCellLoICircumflex; break; case 'o': x = kCellLoOCircumflex; break; case 'u': x = kCellLoUCircumflex; break; default: return; break; } break; case 'n': switch (*p++) { case 'A': x = kCellUpATilde; break; case 'N': x = kCellUpNTilde; break; case 'O': x = kCellUpOTilde; break; case 'a': x = kCellLoATilde; break; case 'n': x = kCellLoNTilde; break; case 'o': x = kCellLoOTilde; break; default: return; break; } break; case 'o': x = kCellLoOStroke; break; case 'q': x = kCellLoLigatureOE; break; case 's': x = kCellSharpS; break; case 'u': switch (*p++) { case 'A': x = kCellUpADiaeresis; break; case 'E': x = kCellUpEDiaeresis; break; case 'I': x = kCellUpIDiaeresis; break; case 'O': x = kCellUpODiaeresis; break; case 'U': x = kCellUpUDiaeresis; break; case 'Y': x = kCellUpYDiaeresis; break; case 'a': x = kCellLoADiaeresis; break; case 'e': x = kCellLoEDiaeresis; break; case 'i': x = kCellLoIDiaeresis; break; case 'o': x = kCellLoODiaeresis; break; case 'u': x = kCellLoUDiaeresis; break; case 'y': x = kCellLoYDiaeresis; break; default: return; break; } break; #endif default: return; /* oops, unexpected char, maybe end of string, abort */ break; } ClStrAppendChar(L, r, x); } else { switch (c) { case 'A': x = kCellUpA; break; case 'B': x = kCellUpB; break; case 'C': x = kCellUpC; break; case 'D': x = kCellUpD; break; case 'E': x = kCellUpE; break; case 'F': x = kCellUpF; break; case 'G': x = kCellUpG; break; case 'H': x = kCellUpH; break; case 'I': x = kCellUpI; break; case 'J': x = kCellUpJ; break; case 'K': x = kCellUpK; break; case 'L': x = kCellUpL; break; case 'M': x = kCellUpM; break; case 'N': x = kCellUpN; break; case 'O': x = kCellUpO; break; case 'P': x = kCellUpP; break; case 'Q': x = kCellUpQ; break; case 'R': x = kCellUpR; break; case 'S': x = kCellUpS; break; case 'T': x = kCellUpT; break; case 'U': x = kCellUpU; break; case 'V': x = kCellUpV; break; case 'W': x = kCellUpW; break; case 'X': x = kCellUpX; break; case 'Y': x = kCellUpY; break; case 'Z': x = kCellUpZ; break; case 'a': x = kCellLoA; break; case 'b': x = kCellLoB; break; case 'c': x = kCellLoC; break; case 'd': x = kCellLoD; break; case 'e': x = kCellLoE; break; case 'f': x = kCellLoF; break; case 'g': x = kCellLoG; break; case 'h': x = kCellLoH; break; case 'i': x = kCellLoI; break; case 'j': x = kCellLoJ; break; case 'k': x = kCellLoK; break; case 'l': x = kCellLoL; break; case 'm': x = kCellLoM; break; case 'n': x = kCellLoN; break; case 'o': x = kCellLoO; break; case 'p': x = kCellLoP; break; case 'q': x = kCellLoQ; break; case 'r': x = kCellLoR; break; case 's': x = kCellLoS; break; case 't': x = kCellLoT; break; case 'u': x = kCellLoU; break; case 'v': x = kCellLoV; break; case 'w': x = kCellLoW; break; case 'x': x = kCellLoX; break; case 'y': x = kCellLoY; break; case 'z': x = kCellLoZ; break; case '0': x = kCellDigit0; break; case '1': x = kCellDigit1; break; case '2': x = kCellDigit2; break; case '3': x = kCellDigit3; break; case '4': x = kCellDigit4; break; case '5': x = kCellDigit5; break; case '6': x = kCellDigit6; break; case '7': x = kCellDigit7; break; case '8': x = kCellDigit8; break; case '9': x = kCellDigit9; break; case '!': x = kCellExclamation; break; case '&': x = kCellAmpersand; break; case '(': x = kCellLeftParen; break; case ')': x = kCellRightParen; break; case ',': x = kCellComma; break; case '-': x = kCellHyphen; break; case '.': x = kCellPeriod; break; case '/': x = kCellSlash; break; case ':': x = kCellColon; break; case ';': x = kCellSemicolon; break; case '?': x = kCellQuestion; break; case '_': x = kCellUnderscore; break; default: x = kCellSpace; break; } ClStrAppendChar(L, r, x); } } } LOCALPROC ClStrFromSubstCStr(int *L, ui3b *r, char *s) { *L = 0; ClStrAppendSubstCStr(L, r, s); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/IWMEMDEV.c b/Mini vMac/mnvm_core/IWMEMDEV.c new file mode 100755 index 0000000..5b72ea2 --- /dev/null +++ b/Mini vMac/mnvm_core/IWMEMDEV.c @@ -0,0 +1 @@ +/* IWMEVDEV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Integrated Woz Machine EMulated DEVice Emulates the IWM found in the Mac Plus. This code is adapted from "IWM.c" in vMac by Philip Cummins. */ /* This is the emulation for the IWM, the Integrated Woz Machine. It's basically a serial to parallel converter with some timing in-built into it to perform handshaking. Emulation so far just includes Status and Mode Register Accesses. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "IWMEMDEV.h" #define kph0L 0x00 /* CA0 off (0) */ #define kph0H 0x01 /* CA0 on (1) */ #define kph1L 0x02 /* CA1 off (0) */ #define kph1H 0x03 /* CA1 on (1) */ #define kph2L 0x04 /* CA2 off (0) */ #define kph2H 0x05 /* CA2 on (1) */ #define kph3L 0x06 /* LSTRB off (low) */ #define kph3H 0x07 /* LSTRB on (high) */ #define kmtrOff 0x08 /* disk enable off */ #define kmtrOn 0x09 /* disk enable on */ #define kintDrive 0x0A /* select internal drive */ #define kextDrive 0x0B /* select external drive */ #define kq6L 0x0C /* Q6 off */ #define kq6H 0x0D /* Q6 on */ #define kq7L 0x0E /* Q7 off */ #define kq7H 0x0F /* Q7 on */ #define kph0 0x01 #define kph1 0x02 #define kph2 0x04 #define kph3 0x08 #define kmtr 0x10 #define kdrv 0x20 #define kq6 0x40 #define kq7 0x80 typedef struct { ui3b DataIn; /* Read Data Register */ ui3b Handshake; /* Read Handshake Register */ ui3b Status; /* Read Status Register */ ui3b Mode; /* Drive Off : Write Mode Register */ /* Drive On : Write Data Register */ ui3b DataOut; /* Write Data Register */ ui3b Lines; /* Used to Access Disk Drive Registers */ } IWM_Ty; IWM_Ty IWM; GLOBALPROC IWM_Reset(void) { IWM.DataIn = IWM.Handshake = IWM.Status = IWM.Mode = IWM.DataOut = IWM.Lines = 0; } typedef enum {On, Off} Mode_Ty; LOCALPROC IWM_Set_Lines(ui3b line, Mode_Ty the_mode) { if (the_mode == Off) { IWM.Lines &= (0xFF - line); } else { IWM.Lines |= line; } } LOCALFUNC ui3b IWM_Read_Reg(void) { switch ((IWM.Lines & (kq6 + kq7)) >> 6) { case 0 : #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormal("IWM Data Read"); #endif #ifdef _IWM_Debug printf("IWM Data Read\n"); #endif return IWM.DataIn; break; case 1 : #ifdef _IWM_Debug printf("IWM Status Read\n"); #endif return IWM.Status; break; case 2 : ReportAbnormal("IWM Handshake Read"); #ifdef _IWM_Debug printf("IWM Handshake Read\n"); #endif return IWM.Handshake; break; case 3 : default : /* should alway be in 0-3, but compiler warnings don't know that */ return 0; break; } } LOCALPROC IWM_Write_Reg(ui3b in) { if (((IWM.Lines & kmtr) >> 4) == 0) { #ifdef _IWM_Debug printf("IWM Mode Register Write\n"); #endif IWM.Mode = in; IWM.Status = ((IWM.Status & 0xE0) + (IWM.Mode & 0x1F)); } } GLOBALFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr) { switch (addr) { case kph0L : IWM_Set_Lines(kph0, Off); break; case kph0H : IWM_Set_Lines(kph0, On); break; case kph1L : IWM_Set_Lines(kph1, Off); break; case kph1H : IWM_Set_Lines(kph1, On); break; case kph2L : IWM_Set_Lines(kph2, Off); break; case kph2H : IWM_Set_Lines(kph2, On); break; case kph3L : IWM_Set_Lines(kph3, Off); break; case kph3H : IWM_Set_Lines(kph3, On); break; case kmtrOff : IWM.Status &= 0xDF; IWM_Set_Lines(kmtr, Off); break; case kmtrOn : IWM.Status |= 0x20; IWM_Set_Lines(kmtr, On); break; case kintDrive : IWM_Set_Lines(kdrv, Off); break; case kextDrive : IWM_Set_Lines(kdrv, On); break; case kq6L : IWM_Set_Lines(kq6, Off); break; case kq6H : IWM_Set_Lines(kq6, On); break; case kq7L : if (! WriteMem) { Data = IWM_Read_Reg(); } IWM_Set_Lines(kq7, Off); break; case kq7H : if (WriteMem) { IWM_Write_Reg(Data); } IWM_Set_Lines(kq7, On); break; } return Data; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/IWMEMDEV.h b/Mini vMac/mnvm_core/IWMEMDEV.h new file mode 100755 index 0000000..7205b8c --- /dev/null +++ b/Mini vMac/mnvm_core/IWMEMDEV.h @@ -0,0 +1 @@ +/* IWMEVDEV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef IWMEVDEV_H #error "header already included" #else #define IWMEVDEV_H #endif EXPORTPROC IWM_Reset(void); EXPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/KBRDEMDV.c b/Mini vMac/mnvm_core/KBRDEMDV.c new file mode 100755 index 0000000..cc52119 --- /dev/null +++ b/Mini vMac/mnvm_core/KBRDEMDV.c @@ -0,0 +1 @@ +/* KBRDEMDV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* KeyBoaRD EMulated DeVice Emulation of the keyboard in the Mac Plus. This code adapted from "Keyboard.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "KBRDEMDV.h" #ifdef _VIA_Debug #include #endif IMPORTPROC KYBD_ShiftOutData(ui3b v); IMPORTFUNC ui3b KYBD_ShiftInData(void); enum { kKybdStateIdle, kKybdStateRecievingCommand, kKybdStateRecievedCommand, kKybdStateRecievingEndCommand, kKybdStates }; LOCALVAR int KybdState = kKybdStateIdle; LOCALVAR blnr HaveKeyBoardResult = falseblnr; LOCALVAR ui3b KeyBoardResult; LOCALPROC GotKeyBoardData(ui3b v) { if (KybdState != kKybdStateIdle) { HaveKeyBoardResult = trueblnr; KeyBoardResult = v; } else { KYBD_ShiftOutData(v); VIA1_iCB2 = 1; } } LOCALVAR ui3b InstantCommandData = 0x7B; LOCALFUNC blnr AttemptToFinishInquiry(void) { int i; blnr KeyDown; ui3b Keyboard_Data; if (FindKeyEvent(&i, &KeyDown)) { if (i < 64) { Keyboard_Data = i << 1; if (! KeyDown) { Keyboard_Data += 128; } } else { Keyboard_Data = 121; InstantCommandData = (i - 64) << 1; if (! KeyDown) { InstantCommandData += 128; } } GotKeyBoardData(Keyboard_Data); return trueblnr; } else { return falseblnr; } } #define MaxKeyboardWait 16 /* in 60ths of a second */ /* Code in the mac rom will reset the keyboard if it hasn't been heard from in 32/60th of a second. So time out and send something before that to keep connection. */ LOCALVAR int InquiryCommandTimer = 0; GLOBALPROC DoKybd_ReceiveCommand(void) { if (KybdState != kKybdStateRecievingCommand) { ReportAbnormal("KybdState != kKybdStateRecievingCommand"); } else { ui3b in = KYBD_ShiftInData(); KybdState = kKybdStateRecievedCommand; switch (in) { case 0x10 : /* Inquiry Command */ if (! AttemptToFinishInquiry()) { InquiryCommandTimer = MaxKeyboardWait; } break; case 0x14 : /* Instant Command */ GotKeyBoardData(InstantCommandData); InstantCommandData = 0x7B; break; case 0x16 : /* Model Command */ GotKeyBoardData(0x0b /* 0x01 */); /* Test value, means Model 0, no extra devices */ /* Fixed by Hoshi Takanori - it uses the proper keyboard type now */ break; case 0x36 : /* Test Command */ GotKeyBoardData(0x7D); break; case 0x00: GotKeyBoardData(0); break; default : /* Debugger(); */ GotKeyBoardData(0); break; } } } GLOBALPROC DoKybd_ReceiveEndCommand(void) { if (KybdState != kKybdStateRecievingEndCommand) { ReportAbnormal("KybdState != kKybdStateRecievingEndCommand"); } else { KybdState = kKybdStateIdle; #ifdef _VIA_Debug fprintf(stderr, "enter DoKybd_ReceiveEndCommand\n"); #endif if (HaveKeyBoardResult) { #ifdef _VIA_Debug fprintf(stderr, "HaveKeyBoardResult: %d\n", KeyBoardResult); #endif HaveKeyBoardResult = falseblnr; KYBD_ShiftOutData(KeyBoardResult); VIA1_iCB2 = 1; } } } GLOBALPROC Kybd_DataLineChngNtfy(void) { switch (KybdState) { case kKybdStateIdle: if (VIA1_iCB2 == 0) { KybdState = kKybdStateRecievingCommand; #ifdef _VIA_Debug fprintf(stderr, "posting kICT_Kybd_ReceiveCommand\n"); #endif ICT_add(kICT_Kybd_ReceiveCommand, 6800UL * kCycleScale / 64 * kMyClockMult); if (InquiryCommandTimer != 0) { InquiryCommandTimer = 0; /* abort Inquiry */ } } break; case kKybdStateRecievedCommand: if (VIA1_iCB2 == 1) { KybdState = kKybdStateRecievingEndCommand; #ifdef _VIA_Debug fprintf(stderr, "posting kICT_Kybd_ReceiveEndCommand\n"); #endif ICT_add(kICT_Kybd_ReceiveEndCommand, 6800UL * kCycleScale / 64 * kMyClockMult); } break; } } GLOBALPROC KeyBoard_Update(void) { if (InquiryCommandTimer != 0) { if (AttemptToFinishInquiry()) { InquiryCommandTimer = 0; } else { --InquiryCommandTimer; if (InquiryCommandTimer == 0) { GotKeyBoardData(0x7B); } } } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/KBRDEMDV.h b/Mini vMac/mnvm_core/KBRDEMDV.h new file mode 100755 index 0000000..f33401d --- /dev/null +++ b/Mini vMac/mnvm_core/KBRDEMDV.h @@ -0,0 +1 @@ +/* KBRDEMDV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef KBRDEMDV_H #error "header already included" #else #define KBRDEMDV_H #endif EXPORTPROC Kybd_DataLineChngNtfy(void); EXPORTPROC DoKybd_ReceiveEndCommand(void); EXPORTPROC DoKybd_ReceiveCommand(void); EXPORTPROC KeyBoard_Update(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/M68KITAB.c b/Mini vMac/mnvm_core/M68KITAB.c new file mode 100755 index 0000000..a049fab --- /dev/null +++ b/Mini vMac/mnvm_core/M68KITAB.c @@ -0,0 +1 @@ +/* M68KITAB.c Copyright (C) 2007 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Motorola 68K Instructions TABle */ #ifndef AllFiles #include "SYSDEPNS.h" #endif #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" struct WorkR { /* expected size : 8 bytes */ ui5b opcode; ui5b opsize; ui4r MainClass; #if WantCycByPriOp ui4r Cycles; #endif DecOpR DecOp; }; typedef struct WorkR WorkR; #define b76(p) ((p->opcode >> 6) & 3) #define b8(p) ((p->opcode >> 8) & 1) #define mode(p) ((p->opcode >> 3) & 7) #define reg(p) (p->opcode & 7) #define md6(p) ((p->opcode >> 6) & 7) #define rg9(p) ((p->opcode >> 9) & 7) enum { kAddrValidAny, kAddrValidData, kAddrValidDataAlt, kAddrValidControl, kAddrValidControlAlt, kAddrValidAltMem, kNumAddrValids }; #define kAddrValidMaskAny (1 << kAddrValidAny) #define kAddrValidMaskData (1 << kAddrValidData) #define kAddrValidMaskDataAlt (1 << kAddrValidDataAlt) #define kAddrValidMaskControl (1 << kAddrValidControl) #define kAddrValidMaskControlAlt (1 << kAddrValidControlAlt) #define kAddrValidMaskAltMem (1 << kAddrValidAltMem) #define CheckInSet(v, m) (0 != ((1 << (v)) & (m))) #define kMyAvgCycPerInstr (10 * kCycleScale + (40 * kCycleScale / 64)) LOCALFUNC MayNotInline ui3r GetArgkRegSz(WorkR *p) { ui3r CurArgk; switch (p->opsize) { case 1: CurArgk = kArgkRegB; break; case 2: default: /* keep compiler happy */ CurArgk = kArgkRegW; break; case 4: CurArgk = kArgkRegL; break; } return CurArgk; } LOCALFUNC MayNotInline ui3r GetArgkMemSz(WorkR *p) { ui3r CurArgk; switch (p->opsize) { case 1: CurArgk = kArgkMemB; break; case 2: default: /* keep compiler happy */ CurArgk = kArgkMemW; break; case 4: CurArgk = kArgkMemL; break; } return CurArgk; } #if WantCycByPriOp LOCALFUNC MayNotInline ui4r OpEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; switch (m) { case 0: case 1: v = 0; break; case 2: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc)); break; case 3: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc)); break; case 4: v = ((4 == p->opsize) ? (10 * kCycleScale + 2 * RdAvgXtraCyc) : (6 * kCycleScale + RdAvgXtraCyc)); break; case 5: v = ((4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 6: v = ((4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (10 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 7: switch (r) { case 0: v = ((4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 1: v = ((4 == p->opsize) ? (16 * kCycleScale + 4 * RdAvgXtraCyc) : (12 * kCycleScale + 3 * RdAvgXtraCyc)); break; case 2: v = ((4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 3: v = ((4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (10 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 4: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc)); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif #if WantCycByPriOp LOCALFUNC MayNotInline ui4r OpEADestCalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; switch (m) { case 0: case 1: v = 0; break; case 2: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * WrAvgXtraCyc) : (4 * kCycleScale + WrAvgXtraCyc)); break; case 3: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * WrAvgXtraCyc) : (4 * kCycleScale + WrAvgXtraCyc)); break; case 4: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * WrAvgXtraCyc) : (4 * kCycleScale + WrAvgXtraCyc)); break; case 5: v = ((4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); break; case 6: v = ((4 == p->opsize) ? (14 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (10 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); break; case 7: switch (r) { case 0: v = ((4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); break; case 1: v = ((4 == p->opsize) ? (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc)); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif LOCALPROC SetDcoArgFields(WorkR *p, blnr src, ui3r CurAMd, ui3r CurArgk, ui3r CurArgDat) { ui5b *pv = src ? (&p->DecOp.B) : (&p->DecOp.A); ui5r v = *pv; SetDcoFldArgDat(v, CurArgDat); SetDcoFldAMd(v, CurAMd); SetDcoFldArgk(v, CurArgk); *pv = v; } LOCALFUNC MayNotInline blnr CheckValidAddrMode(WorkR *p, ui3r m, ui3r r, ui3r v, blnr src) { ui3r CurAMd = 0; /* init to keep compiler happy */ ui3r CurArgk = 0; /* init to keep compiler happy */ ui3r CurArgDat = 0; blnr IsOk; switch (m) { case 0: CurAMd = kAMdReg; CurArgk = GetArgkRegSz(p); CurArgDat = r; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt); break; case 1: CurAMd = kAMdReg; CurArgk = GetArgkRegSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny); break; case 2: CurAMd = kAMdIndirect; CurArgk = GetArgkMemSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); break; case 3: switch (p->opsize) { case 1: if (7 == r) { CurAMd = kAMdAPosIncW; } else { CurAMd = kAMdAPosIncB; } break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAPosIncW; break; case 4: CurAMd = kAMdAPosIncL; break; } CurArgk = GetArgkMemSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskAltMem); break; case 4: switch (p->opsize) { case 1: if (7 == r) { CurAMd = kAMdAPreDecW; } else { CurAMd = kAMdAPreDecB; } break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAPreDecW; break; case 4: CurAMd = kAMdAPreDecL; break; } CurArgk = GetArgkMemSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskAltMem); break; case 5: CurAMd = kAMdADisp; CurArgk = GetArgkMemSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); break; case 6: CurAMd = kAMdAIndex; CurArgk = GetArgkMemSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); break; case 7: switch (r) { case 0: CurAMd = kAMdAbsW; CurArgk = GetArgkMemSz(p); IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); break; case 1: CurAMd = kAMdAbsL; CurArgk = GetArgkMemSz(p); IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); break; case 2: CurAMd = kAMdPCDisp; CurArgk = GetArgkMemSz(p); IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskControl); break; case 3: CurAMd = kAMdPCIndex; CurArgk = GetArgkMemSz(p); IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskControl); break; case 4: switch (p->opsize) { case 1: CurAMd = kAMdImmedB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdImmedW; break; case 4: CurAMd = kAMdImmedL; break; } CurArgk = kArgkCnst; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData); break; default: IsOk = falseblnr; break; } break; default: /* keep compiler happy */ IsOk = falseblnr; break; } if (IsOk) { SetDcoArgFields(p, src, CurAMd, CurArgk, CurArgDat); } return IsOk; } #if WantCycByPriOp LOCALFUNC MayNotInline blnr LeaPeaEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; UnusedParam(p); switch (m) { case 2: v = 0; break; case 5: v = (4 * kCycleScale + RdAvgXtraCyc); break; case 6: v = (8 * kCycleScale + RdAvgXtraCyc); break; case 7: switch (r) { case 0: v = (4 * kCycleScale + RdAvgXtraCyc); break; case 1: v = (8 * kCycleScale + 2 * RdAvgXtraCyc); break; case 2: v = (4 * kCycleScale + RdAvgXtraCyc); break; case 3: v = (8 * kCycleScale + RdAvgXtraCyc); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif LOCALFUNC blnr IsValidAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, falseblnr); } LOCALFUNC MayNotInline blnr CheckDataAltAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr); } LOCALFUNC MayNotInline blnr CheckDataAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, falseblnr); } LOCALFUNC MayNotInline blnr CheckControlAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidControl, falseblnr); } LOCALFUNC MayNotInline blnr CheckControlAltAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidControlAlt, falseblnr); } LOCALFUNC MayNotInline blnr CheckAltMemAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr); } LOCALPROC FindOpSizeFromb76(WorkR *p) { p->opsize = 1 << b76(p); #if 0 switch (b76(p)) { case 0 : p->opsize = 1; break; case 1 : p->opsize = 2; break; case 2 : p->opsize = 4; break; } #endif } LOCALFUNC ui3r OpSizeOffset(WorkR *p) { ui3r v; switch (p->opsize) { case 1 : v = 0; break; case 2 : v = 1; break; case 4 : default : v = 2; break; } return v; } LOCALFUNC ui5r octdat(ui5r x) { if (x == 0) { return 8; } else { return x; } } LOCALPROC MayInline DeCode0(WorkR *p) { if (b8(p) == 1) { if (mode(p) == 1) { /* MoveP 0000ddd1mm001aaa */ #if WantCycByPriOp switch (b76(p)) { case 0: p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc); break; case 1: p->Cycles = (24 * kCycleScale + 6 * RdAvgXtraCyc); break; case 2: p->Cycles = (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 3: default: /* keep compiler happy */ p->Cycles = (24 * kCycleScale + 2 * RdAvgXtraCyc + 4 * WrAvgXtraCyc); break; } #endif p->MainClass = kIKindMoveP; } else { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ if (mode(p) == 0) { #if WantCycByPriOp switch (b76(p)) { case 0: /* BTst */ p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); break; case 1: /* BChg */ p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); break; case 2: /* BClr */ p->Cycles = (10 * kCycleScale + RdAvgXtraCyc); break; case 3: /* BSet */ p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); break; } #endif p->MainClass = kIKindBitOpDD; } else { if (b76(p) == 0) { /* BTst */ if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindBitOpDM; } } else { if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindBitOpDM; } } } } } else { if (rg9(p) == 4) { /* static bit 00001010ssmmmrrr */ if (mode(p) == 0) { #if WantCycByPriOp switch (b76(p)) { case 0: /* BTst */ p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 1: /* BChg */ p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc); break; case 2: /* BClr */ p->Cycles = (14 * kCycleScale + 2 * RdAvgXtraCyc); break; case 3: /* BSet */ p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc); break; } #endif p->MainClass = kIKindBitOpND; } else { if (b76(p) == 0) { /* BTst */ if ((mode(p) == 7) && (reg(p) == 4)) { p->MainClass = kIKindIllegal; } else { if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + 2 * RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindBitOpNM; } } } else { if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindBitOpNM; } } } } else if (b76(p) == 3) { #if Use68020 if (rg9(p) < 3) { /* CHK2 or CMP2 00000ss011mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCHK2orCMP2; } } else if (rg9(p) >= 5) { if ((mode(p) == 7) && (reg(p) == 4)) { /* CAS2 00001ss011111100 */ p->MainClass = kIKindCAS2; } else { /* CAS 00001ss011mmmrrr */ p->MainClass = kIKindCAS; } } else if (rg9(p) == 3) { /* CALLM or RTM 0000011011mmmrrr */ p->MainClass = kIKindCallMorRtm; } else #endif { p->MainClass = kIKindIllegal; } } else if (rg9(p) == 6) { /* CMPI 00001100ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindCmpI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 == mode(p)) { p->Cycles = (4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCmpB + OpSizeOffset(p); } } else if (rg9(p) == 7) { #if Use68020 /* MoveS 00001110ssmmmrrr */ if (CheckAltMemAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveS; } #else p->MainClass = kIKindIllegal; #endif } else { if ((mode(p) == 7) && (reg(p) == 4)) { switch (rg9(p)) { case 0: case 1: case 5: #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 3 * RdAvgXtraCyc); #endif p->MainClass = kIKindBinOpStatusCCR; break; default: p->MainClass = kIKindIllegal; break; } } else { switch (rg9(p)) { case 0: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindOrI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindOrI; } break; case 1: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindAndI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAndI; } break; case 2: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindSubI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } break; case 3: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindAddI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } break; case 5: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindEorI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindEorI; } break; default: /* for compiler. should be 0, 1, 2, 3, or 5 */ p->MainClass = kIKindIllegal; break; } } } } } LOCALPROC MayInline DeCode1(WorkR *p) { p->opsize = 1; if (md6(p) == 1) { /* MOVEA */ p->MainClass = kIKindIllegal; } else if (mode(p) == 1) { /* not allowed for byte sized move */ p->MainClass = kIKindIllegal; } else { if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); #endif p->MainClass = kIKindMoveB; } } } LOCALPROC MayInline DeCode2(WorkR *p) { p->opsize = 4; if (md6(p) == 1) { /* MOVEA */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveAL; } } else { if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); #endif p->MainClass = kIKindMoveL; } } } LOCALPROC MayInline DeCode3(WorkR *p) { p->opsize = 2; if (md6(p) == 1) { /* MOVEA */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveAW; } } else { if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); #endif p->MainClass = kIKindMoveW; } } } #if WantCycByPriOp #if WantCloserCyc #define MoveAvgN 0 #else #define MoveAvgN 3 #endif LOCALFUNC MayNotInline ui4r MoveMEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; UnusedParam(p); switch (m) { case 2: case 3: case 4: v = (8 * kCycleScale + 2 * RdAvgXtraCyc); break; case 5: v = (12 * kCycleScale + 3 * RdAvgXtraCyc); break; case 6: v = (14 * kCycleScale + 3 * RdAvgXtraCyc); break; case 7: switch (r) { case 0: v = (12 * kCycleScale + 3 * RdAvgXtraCyc); break; case 1: v = (16 * kCycleScale + 4 * RdAvgXtraCyc); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif LOCALPROC MayInline DeCode4(WorkR *p) { if (b8(p) != 0) { switch (b76(p)) { case 0: #if Use68020 /* Chk.L 0100ddd100mmmrrr */ if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindChkL; } #else p->MainClass = kIKindIllegal; #endif break; case 1: p->MainClass = kIKindIllegal; break; case 2: /* Chk.W 0100ddd110mmmrrr */ if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles = (10 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindChkW; } break; case 3: default: /* keep compiler happy */ #if Use68020 if ((0 == mode(p)) && (4 == rg9(p))) { p->MainClass = kIKindEXTBL; } else #endif { /* Lea 0100aaa111mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += LeaPeaEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindLea; } } break; } } else { switch (rg9(p)) { case 0: if (b76(p) != 3) { /* NegX 01000000ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNegXB + OpSizeOffset(p); } } else { #if Use68020 /* reference seems incorrect to say not for 68000 */ #endif /* Move from SR 0100000011mmmrrr */ if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveSREa; } } break; case 1: if (b76(p) != 3) { /* Clr 01000010ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindClr; } } else { #if Use68020 /* Move from CCR 0100001011mmmrrr */ if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveCCREa; } #else p->MainClass = kIKindIllegal; #endif } break; case 2: if (b76(p) != 3) { /* Neg 01000100ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNegB + OpSizeOffset(p); } } else { /* Move to CCR 0100010011mmmrrr */ if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveEaCCR; } } break; case 3: if (b76(p) != 3) { /* Not 01000110ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNot; } } else { /* Move from SR 0100011011mmmrrr */ if (CheckDataAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveEaSR; } } break; case 4: switch (b76(p)) { case 0: #if Use68020 if (mode(p) == 1) { /* Link.L 0100100000001rrr */ p->MainClass = kIKindLinkL; } else #endif { /* Nbcd 0100100000mmmrrr */ if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNbcd; } } break; case 1: if (mode(p) == 0) { /* Swap 0100100001000rrr */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindSwap; } else #if Use68020 if (mode(p) == 1) { p->MainClass = kIKindBkpt; } else #endif { /* PEA 0100100001mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc); p->Cycles += LeaPeaEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindPEA; } } break; case 2: if (mode(p) == 0) { /* EXT.W */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindEXTW; } else { /* MOVEM reg to mem 01001d001ssmmmrrr */ if (mode(p) == 4) { #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * WrAvgXtraCyc; #endif p->MainClass = kIKindMOVEMRmMW; } else { if (CheckControlAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * WrAvgXtraCyc; #endif p->MainClass = kIKindMOVEMrm; } } } break; case 3: default: /* keep compiler happy */ if (mode(p) == 0) { /* EXT.L */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindEXTL; } else { /* MOVEM reg to mem 01001d001ssmmmrrr */ if (mode(p) == 4) { #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 8 * kCycleScale + MoveAvgN * 2 * WrAvgXtraCyc; #endif p->MainClass = kIKindMOVEMRmML; } else { if (CheckControlAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 8 * kCycleScale + MoveAvgN * 2 * WrAvgXtraCyc; #endif p->MainClass = kIKindMOVEMrm; } } } break; } break; case 5: if (b76(p) == 3) { if ((mode(p) == 7) && (reg(p) == 4)) { /* the ILLEGAL instruction */ p->MainClass = kIKindIllegal; } else { /* Tas 0100101011mmmrrr */ if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (14 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindTas; } } } else { /* Tst 01001010ssmmmrrr */ FindOpSizeFromb76(p); if (b76(p) == 0) { if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindTst; } } else { if (IsValidAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindTst; } } } break; case 6: if (((p->opcode >> 7) & 1) == 1) { /* MOVEM mem to reg 0100110011smmmrrr */ FindOpSizeFromb76(p); if (mode(p) == 3) { #if WantCycByPriOp p->Cycles = 4 * kCycleScale + RdAvgXtraCyc; p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p)); if (4 == p->opsize) { p->Cycles += MoveAvgN * 8 * kCycleScale + 2 * MoveAvgN * RdAvgXtraCyc; } else { p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * RdAvgXtraCyc; } #endif if (b76(p) == 2) { p->MainClass = kIKindMOVEMApRW; } else { p->MainClass = kIKindMOVEMApRL; } } else { if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles = 4 * kCycleScale + RdAvgXtraCyc; p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p)); if (4 == p->opsize) { p->Cycles += MoveAvgN * 8 * kCycleScale + 2 * MoveAvgN * RdAvgXtraCyc; } else { p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * RdAvgXtraCyc; } #endif p->MainClass = kIKindMOVEMmr; } } } else { #if Use68020 if (((p->opcode >> 6) & 1) == 1) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ p->MainClass = kIKindDivL; } else { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ p->MainClass = kIKindMulL; } #else p->MainClass = kIKindIllegal; #endif } break; case 7: default: /* keep compiler happy */ switch (b76(p)) { case 0: p->MainClass = kIKindIllegal; break; case 1: switch (mode(p)) { case 0: case 1: /* Trap 010011100100vvvv */ #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif p->MainClass = kIKindTrap; break; case 2: /* Link */ #if WantCycByPriOp p->Cycles = (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); #endif if (reg(p) == 6) { p->MainClass = kIKindLinkA6; } else { p->MainClass = kIKindLink; } break; case 3: /* Unlk */ #if WantCycByPriOp p->Cycles = (12 * kCycleScale + 3 * RdAvgXtraCyc); #endif if (reg(p) == 6) { p->MainClass = kIKindUnlkA6; } else { p->MainClass = kIKindUnlk; } break; case 4: /* MOVE USP 0100111001100aaa */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindMoveRUSP; break; case 5: /* MOVE USP 0100111001101aaa */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindMoveUSPR; break; case 6: switch (reg(p)) { case 0: /* Reset 0100111001100000 */ #if WantCycByPriOp p->Cycles = (132 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindReset; break; case 1: /* Nop = 0100111001110001 */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindNop; break; case 2: /* Stop 0100111001110010 */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale); #endif p->MainClass = kIKindStop; break; case 3: /* Rte 0100111001110011 */ #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 5 * RdAvgXtraCyc); #endif p->MainClass = kIKindRte; break; case 4: /* Rtd 0100111001110100 */ #if Use68020 p->MainClass = kIKindRtd; #else p->MainClass = kIKindIllegal; #endif break; case 5: /* Rts 0100111001110101 */ #if WantCycByPriOp p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc); #endif p->MainClass = kIKindRts; break; case 6: /* TrapV 0100111001110110 */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindTrapV; break; case 7: default: /* keep compiler happy */ /* Rtr 0100111001110111 */ #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 2 * RdAvgXtraCyc); #endif p->MainClass = kIKindRtr; break; } break; case 7: default: /* keep compiler happy */ #if Use68020 /* MOVEC 010011100111101m */ p->MainClass = kIKindMoveC; #else p->MainClass = kIKindIllegal; #endif break; } break; case 2: /* Jsr 0100111010mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp switch (mode(p)) { case 2: p->Cycles = (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 5: p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 6: p->Cycles = (22 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 7: default: /* keep compiler happy */ switch (reg(p)) { case 0: p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 1: p->Cycles = (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 2: p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 3: default: /* keep compiler happy */ p->Cycles = (22 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; } break; } #endif p->MainClass = kIKindJsr; } break; case 3: default: /* keep compiler happy */ /* JMP 0100111011mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp switch (mode(p)) { case 2: p->Cycles = (8 * kCycleScale + 2 * RdAvgXtraCyc); break; case 5: p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 6: p->Cycles = (14 * kCycleScale + 2 * RdAvgXtraCyc); break; case 7: default: /* keep compiler happy */ switch (reg(p)) { case 0: p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 1: p->Cycles = (12 * kCycleScale + 3 * RdAvgXtraCyc); break; case 2: p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 3: default: /* keep compiler happy */ p->Cycles = (14 * kCycleScale + 3 * RdAvgXtraCyc); break; } break; } #endif p->MainClass = kIKindJmp; } break; } break; } } } LOCALPROC MayInline DeCode5(WorkR *p) { if (b76(p) == 3) { if (mode(p) == 1) { /* DBcc 0101cccc11001ddd */ #if WantCycByPriOp #if WantCloserCyc p->Cycles = 0; #else p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc); /* average of cc true 12(2/0), cc false taken 10(2/0), and not 14(3/0) */ #endif #endif if (1 == ((p->opcode >> 8) & 15)) { p->MainClass = kIKindDBF; } else { p->MainClass = kIKindDBcc; } } else { #if Use68020 if ((mode(p) == 7) && (reg(p) >= 2)) { /* TRAPcc 0101cccc11111sss */ p->MainClass = kIKindTRAPcc; } else #endif { p->opsize = 1; /* Scc 0101cccc11mmmrrr */ if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { #if WantCloserCyc p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #else p->Cycles = (5 * kCycleScale + RdAvgXtraCyc); /* 4 when false, 6 when true */ #endif } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindScc; } } } } else { if (mode(p) == 1) { p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, trueblnr, kAMdDat4, kArgkCnst, octdat(rg9(p))); SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, reg(p) + 8); /* always long, regardless of opsize */ if (b8(p) == 0) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindAddQA; /* AddQA 0101nnn0ss001rrr */ } else { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindSubQA; /* SubQA 0101nnn1ss001rrr */ } } else { FindOpSizeFromb76(p); SetDcoArgFields(p, trueblnr, kAMdDat4, kArgkCnst, octdat(rg9(p))); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif if (b8(p) == 0) { /* AddQ 0101nnn0ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindAddQ; } #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } else { /* SubQ 0101nnn1ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindSubQ; } #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } } } } } LOCALPROC MayInline DeCode6(WorkR *p) { ui5b cond = (p->opcode >> 8) & 15; if (cond == 1) { /* Bsr 01100001nnnnnnnn */ #if WantCycByPriOp p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); #endif if (0 == (p->opcode & 255)) { p->MainClass = kIKindBsrW; } else #if Use68020 if (255 == (p->opcode & 255)) { p->MainClass = kIKindBsrL; } else #endif { p->MainClass = kIKindBsrB; } } else if (cond == 0) { /* Bra 01100000nnnnnnnn */ #if WantCycByPriOp p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); #endif if (0 == (p->opcode & 255)) { p->MainClass = kIKindBraW; } else #if Use68020 if (255 == (p->opcode & 255)) { p->MainClass = kIKindBraL; } else #endif { p->MainClass = kIKindBraB; } } else { /* Bcc 0110ccccnnnnnnnn */ if (0 == (p->opcode & 255)) { #if WantCycByPriOp #if WantCloserCyc p->Cycles = 0; #else p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc); /* average of branch taken 10(2/0) and not 12(2/0) */ #endif #endif p->MainClass = kIKindBccW; } else #if Use68020 if (255 == (p->opcode & 255)) { p->MainClass = kIKindBccL; } else #endif { #if WantCycByPriOp #if WantCloserCyc p->Cycles = 0; #else p->Cycles = (9 * kCycleScale + RdAvgXtraCyc + (RdAvgXtraCyc / 2)); /* average of branch taken 10(2/0) and not 8(1/0) */ #endif #endif p->MainClass = kIKindBccB; } } } LOCALPROC MayInline DeCode7(WorkR *p) { if (b8(p) == 0) { p->opsize = 4; #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindMoveQ; } else { p->MainClass = kIKindIllegal; } } LOCALPROC MayInline DeCode8(WorkR *p) { if (b76(p) == 3) { p->opsize = 2; if (CheckDataAddrMode(p)) { if (b8(p) == 0) { /* DivU 1000ddd011mmmrrr */ #if WantCycByPriOp p->Cycles = RdAvgXtraCyc; p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #if ! WantCloserCyc p->Cycles += 133 * kCycleScale; /* worse case 140, less than ten percent different from best case */ #endif #endif p->MainClass = kIKindDivU; } else { /* DivS 1000ddd111mmmrrr */ #if WantCycByPriOp p->Cycles = RdAvgXtraCyc; p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #if ! WantCloserCyc p->Cycles += 150 * kCycleScale; /* worse case 158, less than ten percent different from best case */ #endif #endif p->MainClass = kIKindDivS; } } } else { if (b8(p) == 0) { /* OR 1000ddd0ssmmmrrr */ #if 0 if (CheckDataAddrMode(p)) { p->MainClass = kIKindOrEaD; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindOrEaD; } } else { if (mode(p) < 2) { switch (b76(p)) { case 0: /* SBCD 1000xxx10000mxxx */ #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (18 * kCycleScale + 3 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } #endif if (mode(p) == 0) { p->MainClass = kIKindSbcdr; } else { p->MainClass = kIKindSbcdm; } break; #if Use68020 case 1: /* PACK 1000rrr10100mrrr */ p->MainClass = kIKindPack; break; case 2: /* UNPK 1000rrr11000mrrr */ p->MainClass = kIKindUnpk; break; #endif default: p->MainClass = kIKindIllegal; break; } } else { /* OR 1000ddd1ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindOrDEa; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindOrDEa; } } } } } LOCALPROC MayInline DeCode9(WorkR *p) { if (b76(p) == 3) { /* SUBA 1001dddm11mmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindSubA; } #endif p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubA; } } else { if (b8(p) == 0) { /* SUB 1001ddd0ssmmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindSubEaR; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } } else { if (mode(p) == 0) { /* SUBX 1001ddd1ss000rrr */ /* p->MainClass = kIKindSubXd; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindSubXB + OpSizeOffset(p); } } else if (mode(p) == 1) { /* SUBX 1001ddd1ss001rrr */ /* p->MainClass = kIKindSubXm; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (30 * kCycleScale + 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (18 * kCycleScale + 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc); #endif p->MainClass = kIKindSubXB + OpSizeOffset(p); } } else { /* SUB 1001ddd1ssmmmrrr */ #if 0 if (CheckAltMemAddrMode(p)) { p->MainClass = kIKindSubREa; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } } } } } LOCALPROC MayInline DeCodeA(WorkR *p) { #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif p->MainClass = kIKindA; } LOCALPROC MayInline DeCodeB(WorkR *p) { if (b76(p) == 3) { /* CMPA 1011ddds11mmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindCmpA; } #endif p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCmpA; } } else if (b8(p) == 1) { if (mode(p) == 1) { /* CmpM 1011ddd1ss001rrr */ #if 0 p->MainClass = kIKindCmpM; #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 3, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 3, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 5 * RdAvgXtraCyc) : (12 * kCycleScale + 3 * RdAvgXtraCyc); #endif p->MainClass = kIKindCmpB + OpSizeOffset(p); } } else { #if 0 /* Eor 1011ddd1ssmmmrrr */ if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindEor; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindEor; } } } else { /* Cmp 1011ddd0ssmmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindCmp; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCmpB + OpSizeOffset(p); } } } LOCALPROC MayInline DeCodeC(WorkR *p) { if (b76(p) == 3) { p->opsize = 2; if (CheckDataAddrMode(p)) { #if WantCycByPriOp #if WantCloserCyc p->Cycles = (38 * kCycleScale + RdAvgXtraCyc); #else p->Cycles = (54 * kCycleScale + RdAvgXtraCyc); /* worst case 70, best case 38 */ #endif p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif if (b8(p) == 0) { /* MulU 1100ddd011mmmrrr */ p->MainClass = kIKindMulU; } else { /* MulS 1100ddd111mmmrrr */ p->MainClass = kIKindMulS; } } } else { if (b8(p) == 0) { /* And 1100ddd0ssmmmrrr */ #if 0 if (CheckDataAddrMode(p)) { p->MainClass = kIKindAndEaD; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAndEaD; } } else { if (mode(p) < 2) { switch (b76(p)) { case 0: /* ABCD 1100ddd10000mrrr */ #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (18 * kCycleScale + 3 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } #endif if (mode(p) == 0) { p->MainClass = kIKindAbcdr; } else { p->MainClass = kIKindAbcdm; } break; case 1: /* Exg 1100ddd10100trrr */ #if WantCycByPriOp p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); #endif if (mode(p) == 0) { p->MainClass = kIKindExgdd; } else { p->MainClass = kIKindExgaa; } break; case 2: default: /* keep compiler happy */ if (mode(p) == 0) { p->MainClass = kIKindIllegal; } else { /* Exg 1100ddd110001rrr */ #if WantCycByPriOp p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindExgda; } break; } } else { /* And 1100ddd1ssmmmrrr */ #if 0 if (CheckAltMemAddrMode(p)) { p->MainClass = kIKindAndDEa; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAndDEa; } } } } } LOCALPROC MayInline DeCodeD(WorkR *p) { if (b76(p) == 3) { /* ADDA 1101dddm11mmmrrr */ p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddA; } } else { if (b8(p) == 0) { /* ADD 1101ddd0ssmmmrrr */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } } else { if (mode(p) == 0) { /* ADDX 1101ddd1ss000rrr */ /* p->MainClass = kIKindAddXd; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindAddXB + OpSizeOffset(p); } } else if (mode(p) == 1) { /* p->MainClass = kIKindAddXm; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (30 * kCycleScale + 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (18 * kCycleScale + 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc); #endif p->MainClass = kIKindAddXB + OpSizeOffset(p); } } else { /* ADD 1101ddd1ssmmmrrr */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } } } } } LOCALPROC MayInline DeCodeE(WorkR *p) { if (b76(p) == 3) { if ((p->opcode & 0x0800) != 0) { #if Use68020 /* 11101???11mmmrrr */ switch (mode(p)) { case 1: case 3: case 4: default: /* keep compiler happy */ p->MainClass = kIKindIllegal; break; case 0: case 2: case 5: case 6: p->MainClass = kIKindBitField; break; case 7: switch (reg(p)) { case 0: case 1: p->MainClass = kIKindBitField; break; case 2: case 3: switch ((p->opcode >> 8) & 7) { case 0: /* BFTST */ case 1: /* BFEXTU */ case 3: /* BFEXTS */ case 5: /* BFFFO */ p->MainClass = kIKindBitField; break; default: p->MainClass = kIKindIllegal; break; } break; default: p->MainClass = kIKindIllegal; break; } break; } #else p->MainClass = kIKindIllegal; #endif } else { /* 11100ttd11mmmddd */ if (CheckAltMemAddrMode(p)) { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindRolopNM; } } } else { if (mode(p) < 4) { /* 1110cccdss0ttddd */ #if WantCycByPriOp p->Cycles = (octdat(rg9(p)) * (2 * kCycleScale)) + ((4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (6 * kCycleScale + RdAvgXtraCyc)); #endif p->MainClass = kIKindRolopND; } else { /* 1110rrrdss1ttddd */ #if WantCycByPriOp #if WantCloserCyc p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (6 * kCycleScale + RdAvgXtraCyc); #else p->Cycles = (4 == p->opsize) ? ((8 * kCycleScale) + RdAvgXtraCyc + (8 * (2 * kCycleScale))) /* say average shift count of 8 */ : ((6 * kCycleScale) + RdAvgXtraCyc + (4 * (2 * kCycleScale))); /* say average shift count of 4 */ #endif #endif p->MainClass = kIKindRolopDD; } } } LOCALPROC MayInline DeCodeF(WorkR *p) { #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif p->MainClass = kIKindF; } LOCALPROC DeCodeOneOp(WorkR *p) { switch (p->opcode >> 12) { case 0x0: DeCode0(p); break; case 0x1: DeCode1(p); break; case 0x2: DeCode2(p); break; case 0x3: DeCode3(p); break; case 0x4: DeCode4(p); break; case 0x5: DeCode5(p); break; case 0x6: DeCode6(p); break; case 0x7: DeCode7(p); break; case 0x8: DeCode8(p); break; case 0x9: DeCode9(p); break; case 0xA: DeCodeA(p); break; case 0xB: DeCodeB(p); break; case 0xC: DeCodeC(p); break; case 0xD: DeCodeD(p); break; case 0xE: DeCodeE(p); break; case 0xF: default: /* keep compiler happy */ DeCodeF(p); break; } if (kIKindIllegal == p->MainClass) { #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif SetDcoSrcAMd(&p->DecOp, 0); SetDcoSrcArgk(&p->DecOp, 0); SetDcoSrcArgDat(&p->DecOp, 0); SetDcoDstAMd(&p->DecOp, 0); SetDcoDstArgk(&p->DecOp, 0); SetDcoDstArgDat(&p->DecOp, 0); } SetDcoMainClas(&p->DecOp, p->MainClass); #if WantCycByPriOp SetDcoCycles(&p->DecOp, p->Cycles); #else SetDcoCycles(&p->DecOp, kMyAvgCycPerInstr); #endif } GLOBALPROC M68KITAB_setup(DecOpR *p) { ui5b i; WorkR r; for (i = 0; i < (ui5b)256 * 256; ++i) { r.opcode = i; r.MainClass = kIKindIllegal; r.DecOp.A = 0; r.DecOp.B = 0; #if WantCycByPriOp r.Cycles = kMyAvgCycPerInstr; #endif DeCodeOneOp(&r); p[i].A = r.DecOp.A; p[i].B = r.DecOp.B; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/M68KITAB.h b/Mini vMac/mnvm_core/M68KITAB.h new file mode 100755 index 0000000..6d07bd4 --- /dev/null +++ b/Mini vMac/mnvm_core/M68KITAB.h @@ -0,0 +1 @@ +/* M68KITAB.h Copyright (C) 2007, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef M68KITAB_H #error "header already included" #else #define M68KITAB_H #endif enum { kIKindTst, kIKindCmpB, kIKindCmpW, kIKindCmpL, kIKindBccB, kIKindBccW, kIKindBraB, kIKindBraW, kIKindDBcc, kIKindDBF, kIKindSwap, kIKindMoveL, kIKindMoveW, kIKindMoveB, kIKindMoveAL, kIKindMoveAW, kIKindMoveQ, kIKindAddB, kIKindAddW, kIKindAddL, kIKindSubB, kIKindSubW, kIKindSubL, kIKindLea, kIKindPEA, kIKindA, kIKindBsrB, kIKindBsrW, kIKindJsr, kIKindLinkA6, kIKindMOVEMRmML, kIKindMOVEMApRL, kIKindUnlkA6, kIKindRts, kIKindJmp, kIKindClr, kIKindAddA, kIKindAddQA, kIKindSubA, kIKindSubQA, kIKindCmpA, kIKindAddXB, kIKindAddXW, kIKindAddXL, kIKindSubXB, kIKindSubXW, kIKindSubXL, kIKindRolopNM, kIKindRolopND, kIKindRolopDD, kIKindBitOpDD, kIKindBitOpDM, kIKindBitOpND, kIKindBitOpNM, kIKindAndI, kIKindAndEaD, kIKindAndDEa, kIKindOrI, kIKindOrDEa, kIKindOrEaD, kIKindEor, kIKindEorI, kIKindNot, kIKindScc, kIKindNegXB, kIKindNegXW, kIKindNegXL, kIKindNegB, kIKindNegW, kIKindNegL, kIKindEXTW, kIKindEXTL, kIKindMulU, kIKindMulS, kIKindDivU, kIKindDivS, kIKindExgdd, kIKindExgaa, kIKindExgda, kIKindMoveCCREa, kIKindMoveEaCCR, kIKindMoveSREa, kIKindMoveEaSR, kIKindBinOpStatusCCR, kIKindMOVEMApRW, kIKindMOVEMRmMW, kIKindMOVEMrm, kIKindMOVEMmr, kIKindAbcdr, kIKindAbcdm, kIKindSbcdr, kIKindSbcdm, kIKindNbcd, kIKindRte, kIKindNop, kIKindMoveP, kIKindIllegal, kIKindChkW, kIKindTrap, kIKindTrapV, kIKindRtr, kIKindLink, kIKindUnlk, kIKindMoveRUSP, kIKindMoveUSPR, kIKindTas, kIKindF, kIKindCallMorRtm, kIKindStop, kIKindReset, #if Use68020 kIKindBraL, kIKindBccL, kIKindBsrL, kIKindEXTBL, kIKindTRAPcc, kIKindChkL, kIKindBkpt, kIKindDivL, kIKindMulL, kIKindRtd, kIKindMoveC, kIKindLinkL, kIKindPack, kIKindUnpk, kIKindCHK2orCMP2, kIKindCAS2, kIKindCAS, kIKindMoveS, kIKindBitField, #endif kNumIKinds }; enum { kAMdReg, kAMdIndirect, kAMdAPosIncB, kAMdAPosIncW, kAMdAPosIncL, kAMdAPreDecB, kAMdAPreDecW, kAMdAPreDecL, kAMdADisp, kAMdAIndex, kAMdAbsW, kAMdAbsL, kAMdPCDisp, kAMdPCIndex, kAMdImmedB, kAMdImmedW, kAMdImmedL, kAMdDat4, kNumAMds }; enum { kArgkRegB, kArgkRegW, kArgkRegL, kArgkMemB, kArgkMemW, kArgkMemL, kArgkCnst, kNumArgks }; struct DecOpR { /* expected size : 8 bytes */ ui5b A; ui5b B; }; typedef struct DecOpR DecOpR; #define GetUi5rField(v, shift, sz) \ (((v) >> (shift)) & ((1UL << (sz)) - 1)) #define SetUi5rField(v, shift, sz, x) \ (v) = (((v) & ~ (((1UL << (sz)) - 1) << (shift))) \ | (((x) & ((1UL << (sz)) - 1)) << (shift))) #define GetDcoFldAMd(f) (GetUi5rField((f), 16, 8)) #define GetDcoFldArgk(f) (GetUi5rField((f), 24, 4)) #define GetDcoFldArgDat(f) (GetUi5rField((f), 28, 4)) #define SetDcoFldAMd(f, x) SetUi5rField((f), 16, 8, x) #define SetDcoFldArgk(f, x) SetUi5rField((f), 24, 4, x) #define SetDcoFldArgDat(f, x) SetUi5rField((f), 28, 4, x) #define GetDcoMainClas(p) (GetUi5rField((p)->A, 0, 16)) #define GetDcoDstAMd(p) (GetDcoFldAMd((p)->A)) #define GetDcoDstArgk(p) (GetDcoFldArgk((p)->A)) #define GetDcoDstArgDat(p) (GetDcoFldArgDat((p)->A)) #define GetDcoSrcAMd(p) (GetDcoFldAMd((p)->B)) #define GetDcoSrcArgk(p) (GetDcoFldArgk((p)->B)) #define GetDcoSrcArgDat(p) (GetDcoFldArgDat((p)->B)) #define GetDcoCycles(p) (GetUi5rField((p)->B, 0, 16)) #define SetDcoMainClas(p, x) SetUi5rField((p)->A, 0, 16, x) #define SetDcoDstAMd(p, x) SetDcoFldAMd((p)->A, x) #define SetDcoDstArgk(p, x) SetDcoFldArgk((p)->A, x) #define SetDcoDstArgDat(p, x) SetDcoFldArgDat((p)->A, x) #define SetDcoSrcAMd(p, x) SetDcoFldAMd((p)->B, x) #define SetDcoSrcArgk(p, x) SetDcoFldArgk((p)->B, x) #define SetDcoSrcArgDat(p, x) SetDcoFldArgDat((p)->B, x) #define SetDcoCycles(p, x) SetUi5rField((p)->B, 0, 16, x) EXPORTPROC M68KITAB_setup(DecOpR *p); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MINEM68K.c b/Mini vMac/mnvm_core/MINEM68K.c new file mode 100755 index 0000000..636cafc --- /dev/null +++ b/Mini vMac/mnvm_core/MINEM68K.c @@ -0,0 +1 @@ +/* MINEM68K.c Copyright (C) 2009 Bernd Schmidt, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* MINimum EMulator of 68K cpu This code descends from a simple 68000 emulator that I (Paul C. Pratt) wrote long ago. That emulator ran on a 680x0, and used the cpu it ran on to do some of the work. This descendent fills in those holes with code from the Un*x Amiga Emulator by Bernd Schmidt, as found being used in vMac. This emulator is about 10 times smaller than the UAE, at the cost of being 2 to 3 times slower. FPU Emulation added 9/12/2009 by Ross Martin (this code now located in "FPCPEMDV.h") */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #if WantDisasm #include "DISAM68K.h" #endif #endif #include "MINEM68K.h" typedef unsigned char flagtype; /* Memory Address Translation Cache record */ struct MATCr { ui5r cmpmask; ui5r cmpvalu; ui5r usemask; ui3p usebase; }; typedef struct MATCr MATCr; typedef MATCr *MATCp; /* This variable was introduced because a program could do a Bcc from within chip memory to a location within expansion memory. With a pointer variable the program counter would point to the wrong location. With this variable unset the program counter is always correct, but programs will run slower (about 4%). Usually, you'll want to have this defined. vMac REQUIRES this. It allows for fun things like Restart. */ #ifndef USE_POINTER #define USE_POINTER 1 #endif #define AKMemory 0 #define AKRegister 1 #define AKConstant 2 union ArgAddrT { ui5r mem; ui5r *rga; }; typedef union ArgAddrT ArgAddrT; LOCALVAR struct regstruct { ui5r regs[16]; /* Data and Address registers */ ui5r pc; /* Program Counter */ CPTR usp; /* User Stack Pointer */ CPTR isp; /* Interrupt Stack Pointer */ #if Use68020 CPTR msp; /* Master Stack Pointer */ #endif /* Status Register */ ui5r intmask; /* bits 10-8 : interrupt priority mask */ flagtype t1; /* bit 15: Trace mode 1 */ #if Use68020 flagtype t0; /* bit 14: Trace mode 0 */ #endif flagtype s; /* bit 13: Supervisor or user privilege level */ #if Use68020 flagtype m; /* bit 12: Master or interrupt mode */ #endif flagtype x; /* bit 4: eXtend */ flagtype n; /* bit 3: Negative */ flagtype z; /* bit 2: Zero */ flagtype v; /* bit 1: oVerflow */ flagtype c; /* bit 0: Carry */ flagtype TracePending; flagtype ExternalInterruptPending; #if 0 flagtype ResetPending; #endif ui3b *fIPL; #if Use68020 ui5b sfc; /* Source Function Code register */ ui5b dfc; /* Destination Function Code register */ ui5b vbr; /* Vector Base Register */ ui5b cacr; /* Cache Control Register */ /* bit 0 : Enable Cache bit 1 : Freeze Cache bit 2 : Clear Entry In Cache (write only) bit 3 : Clear Cache (write only) */ ui5b caar; /* Cache Address Register */ #endif MATCr MATCrdB; MATCr MATCwrB; MATCr MATCrdW; MATCr MATCwrW; MATCr MATCex; ATTep HeadATTel; DecOpR CurDecOp; #if USE_POINTER ui3p pc_p; ui3p pc_oldp; #endif ui5b opsize; ui5b ArgKind; ArgAddrT ArgAddr; ui5b SrcVal; ui5b opcode; si5r MaxCyclesToGo; si5r MoreCyclesToGo; si5r ResidualCycles; ui3b fakeword[2]; #define disp_table_sz (256 * 256) #if SmallGlobals DecOpR *disp_table; #else DecOpR disp_table[disp_table_sz]; #endif } regs; #define ui5r_MSBisSet(x) (((si5r)(x)) < 0) #define ZFLG regs.z #define NFLG regs.n #define CFLG regs.c #define VFLG regs.v #define XFLG regs.x LOCALFUNC ui4b m68k_getCR(void) { return (XFLG << 4) | (NFLG << 3) | (ZFLG << 2) | (VFLG << 1) | CFLG; } LOCALFUNC MayInline void m68k_setCR(ui4b newcr) { XFLG = (newcr >> 4) & 1; NFLG = (newcr >> 3) & 1; ZFLG = (newcr >> 2) & 1; VFLG = (newcr >> 1) & 1; CFLG = newcr & 1; } LOCALFUNC MayInline blnr cctrue(void) { switch ((regs.opcode >> 8) & 15) { case 0: return trueblnr; /* T */ case 1: return falseblnr; /* F */ case 2: return (! CFLG) && (! ZFLG); /* HI */ case 3: return CFLG || ZFLG; /* LS */ case 4: return ! CFLG; /* CC */ case 5: return CFLG; /* CS */ case 6: return ! ZFLG; /* NE */ case 7: return ZFLG; /* EQ */ case 8: return ! VFLG; /* VC */ case 9: return VFLG; /* VS */ case 10: return ! NFLG; /* PL */ case 11: return NFLG; /* MI */ case 12: return NFLG == VFLG; /* GE */ case 13: return NFLG != VFLG; /* LT */ case 14: return (! ZFLG) && (NFLG == VFLG); /* GT */ case 15: return ZFLG || (NFLG != VFLG); /* LE */ default: return falseblnr; /* shouldn't get here */ } } LOCALPROC ALU_CmpB(ui5r srcvalue, ui5r dstvalue) { ui5r result0 = dstvalue - srcvalue; ui5r result1 = ui5r_FromUByte(dstvalue) - ui5r_FromUByte(srcvalue); ui5r result = ui5r_FromSByte(result0); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; CFLG = (result1 >> 8) & 1; } LOCALPROC ALU_CmpW(ui5r srcvalue, ui5r dstvalue) { ui5r result0 = dstvalue - srcvalue; ui5r result1 = ui5r_FromUWord(dstvalue) - ui5r_FromUWord(srcvalue); ui5r result = ui5r_FromSWord(result0); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; CFLG = (result1 >> 16) & 1; } LOCALPROC ALU_CmpL(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSLong(dstvalue - srcvalue); int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (flgs != flgo) && (NFLG != flgo); CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); } LOCALFUNC ui5r ALU_AddB(ui5r srcvalue, ui5r dstvalue) { ui5r result0 = dstvalue + srcvalue; ui5r result1 = ui5r_FromUByte(dstvalue) + ui5r_FromUByte(srcvalue); ui5r result = ui5r_FromSByte(result0); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; XFLG = CFLG = (result1 >> 8); return result; } LOCALFUNC ui5r ALU_AddW(ui5r srcvalue, ui5r dstvalue) { ui5r result0 = dstvalue + srcvalue; ui5r result1 = ui5r_FromUWord(dstvalue) + ui5r_FromUWord(srcvalue); ui5r result = ui5r_FromSWord(result0); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; XFLG = CFLG = (result1 >> 16); return result; } LOCALFUNC ui5r ALU_AddL(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSLong(dstvalue + srcvalue); int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (flgs && flgo && ! NFLG) || ((! flgs) && (! flgo) && NFLG); XFLG = CFLG = (flgs && flgo) || ((! NFLG) && (flgo || flgs)); return result; } LOCALFUNC ui5r ALU_SubB(ui5r srcvalue, ui5r dstvalue) { ui5r result0 = dstvalue - srcvalue; ui5r result1 = ui5r_FromUByte(dstvalue) - ui5r_FromUByte(srcvalue); ui5r result = ui5r_FromSByte(result0); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; XFLG = CFLG = (result1 >> 8) & 1; return result; } LOCALFUNC ui5r ALU_SubW(ui5r srcvalue, ui5r dstvalue) { ui5r result0 = dstvalue - srcvalue; ui5r result1 = ui5r_FromUWord(dstvalue) - ui5r_FromUWord(srcvalue); ui5r result = ui5r_FromSWord(result0); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; XFLG = CFLG = (result1 >> 16) & 1; return result; } LOCALFUNC ui5r ALU_SubL(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSLong(dstvalue - srcvalue); int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (flgs != flgo) && (NFLG != flgo); XFLG = CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); return result; } LOCALFUNC ui5r ALU_NegB(ui5r dstvalue) { ui5r result = ui5r_FromSByte(0 - dstvalue); int flgs = ui5r_MSBisSet(dstvalue); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (flgs && NFLG); XFLG = CFLG = (flgs || NFLG); return result; } LOCALFUNC ui5r ALU_NegW(ui5r dstvalue) { ui5r result = ui5r_FromSWord(0 - dstvalue); int flgs = ui5r_MSBisSet(dstvalue); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (flgs && NFLG); XFLG = CFLG = (flgs || NFLG); return result; } LOCALFUNC ui5r ALU_NegL(ui5r dstvalue) { ui5r result = ui5r_FromSLong(0 - dstvalue); int flgs = ui5r_MSBisSet(dstvalue); ZFLG = (result == 0); NFLG = ui5r_MSBisSet(result); VFLG = (flgs && NFLG); XFLG = CFLG = (flgs || NFLG); return result; } LOCALFUNC ui5r ALU_NegXB(ui5r dstvalue) { ui5r result = ui5r_FromSByte(0 - dstvalue - (XFLG ? 1 : 0)); int flgs = ui5r_MSBisSet(dstvalue); if (result != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(result); VFLG = (flgs && NFLG); XFLG = CFLG = (flgs || NFLG); return result; } LOCALFUNC ui5r ALU_NegXW(ui5r dstvalue) { ui5r result = ui5r_FromSWord(0 - dstvalue - (XFLG ? 1 : 0)); int flgs = ui5r_MSBisSet(dstvalue); if (result != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(result); VFLG = (flgs && NFLG); XFLG = CFLG = (flgs || NFLG); return result; } LOCALFUNC ui5r ALU_NegXL(ui5r dstvalue) { ui5r result = ui5r_FromSLong(0 - dstvalue - (XFLG ? 1 : 0)); int flgs = ui5r_MSBisSet(dstvalue); if (result != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(result); VFLG = (flgs && NFLG); XFLG = CFLG = (flgs || NFLG); return result; } LOCALPROC SetCCRforAddX(ui5r srcvalue, ui5r dstvalue, ui5r result) { int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); if (result != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(result); XFLG = CFLG = (flgs && flgo) || ((! NFLG) && (flgo || flgs)); VFLG = (flgs && flgo && ! NFLG) || ((! flgs) && (! flgo) && NFLG); } LOCALFUNC ui5r ALU_AddXB(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSByte(dstvalue + srcvalue + (XFLG ? 1 : 0)); SetCCRforAddX(srcvalue, dstvalue, result); return result; } LOCALFUNC ui5r ALU_AddXW(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSWord(dstvalue + srcvalue + (XFLG ? 1 : 0)); SetCCRforAddX(srcvalue, dstvalue, result); return result; } LOCALFUNC ui5r ALU_AddXL(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSLong(dstvalue + srcvalue + (XFLG ? 1 : 0)); SetCCRforAddX(srcvalue, dstvalue, result); return result; } LOCALPROC SetCCRforSubX(ui5r srcvalue, ui5r dstvalue, ui5r result) { int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); if (result != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(result); VFLG = ((! flgs) && flgo && (! NFLG)) || (flgs && (! flgo) && NFLG); XFLG = CFLG = (flgs && (! flgo)) || (NFLG && ((! flgo) || flgs)); } LOCALFUNC ui5r ALU_SubXB(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSByte(dstvalue - srcvalue - (XFLG ? 1 : 0)); SetCCRforSubX(srcvalue, dstvalue, result); return result; } LOCALFUNC ui5r ALU_SubXW(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSWord(dstvalue - srcvalue - (XFLG ? 1 : 0)); SetCCRforSubX(srcvalue, dstvalue, result); return result; } LOCALFUNC ui5r ALU_SubXL(ui5r srcvalue, ui5r dstvalue) { ui5r result = ui5r_FromSLong(dstvalue - srcvalue - (XFLG ? 1 : 0)); SetCCRforSubX(srcvalue, dstvalue, result); return result; } #define m68k_logExceptions (dbglog_HAVE && 0) GLOBALFUNC ATTep FindATTel(CPTR addr) { ATTep prev; ATTep p; p = regs.HeadATTel; if ((addr & p->cmpmask) != p->cmpvalu) { do { prev = p; p = p->Next; } while ((addr & p->cmpmask) != p->cmpvalu); { ATTep next = p->Next; if (nullpr == next) { /* don't move the end guard */ } else { /* move to first */ prev->Next = next; p->Next = regs.HeadATTel; regs.HeadATTel = p; } } } return p; } LOCALPROC SetUpMATC( MATCp CurMATC, ATTep p) { CurMATC->cmpmask = p->cmpmask; CurMATC->usemask = p->usemask; CurMATC->cmpvalu = p->cmpvalu; CurMATC->usebase = p->usebase; } LOCALFUNC ui5r get_byte_ext(CPTR addr) { ATTep p; ui3p m; ui5r AccFlags; ui5r Data; Label_Retry: p = FindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_readreadymask)) { SetUpMATC(®s.MATCrdB, p); m = p->usebase + (addr & p->usemask); Data = *m; } else if (0 != (AccFlags & kATTA_mmdvmask)) { Data = MMDV_Access(p, 0, falseblnr, trueblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } else { Data = 0; /* fail */ } } else { Data = 0; /* fail */ } return ui5r_FromSByte(Data); } LOCALFUNC MayNotInline ui5r get_byte(CPTR addr) { ui3p m = (addr & regs.MATCrdB.usemask) + regs.MATCrdB.usebase; if ((addr & regs.MATCrdB.cmpmask) == regs.MATCrdB.cmpvalu) { return ui5r_FromSByte(*m); } else { return get_byte_ext(addr); } } LOCALPROC put_byte_ext(CPTR addr, ui5r b) { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = FindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_writereadymask)) { SetUpMATC(®s.MATCwrB, p); m = p->usebase + (addr & p->usemask); *m = b; } else if (0 != (AccFlags & kATTA_mmdvmask)) { (void) MMDV_Access(p, b & 0x00FF, trueblnr, trueblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } else { /* fail */ } } else { /* fail */ } } LOCALPROC MayNotInline put_byte(CPTR addr, ui5r b) { ui3p m = (addr & regs.MATCwrB.usemask) + regs.MATCwrB.usebase; if ((addr & regs.MATCwrB.cmpmask) == regs.MATCwrB.cmpvalu) { *m = b; } else { put_byte_ext(addr, b); } } LOCALFUNC ui5r get_word_ext(CPTR addr) { ui5r Data; if (0 != (addr & 0x01)) { ui5r hi = get_byte(addr); ui5r lo = get_byte(addr + 1); Data = ((hi << 8) & 0x0000FF00) | (lo & 0x000000FF); } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = FindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_readreadymask)) { SetUpMATC(®s.MATCrdW, p); regs.MATCrdW.cmpmask |= 0x01; m = p->usebase + (addr & p->usemask); Data = do_get_mem_word(m); } else if (0 != (AccFlags & kATTA_mmdvmask)) { Data = MMDV_Access(p, 0, falseblnr, falseblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } else { Data = 0; /* fail */ } } else { Data = 0; /* fail */ } } return ui5r_FromSWord(Data); } LOCALFUNC MayNotInline ui5r get_word(CPTR addr) { ui3p m = (addr & regs.MATCrdW.usemask) + regs.MATCrdW.usebase; if ((addr & regs.MATCrdW.cmpmask) == regs.MATCrdW.cmpvalu) { return ui5r_FromSWord(do_get_mem_word(m)); } else { return get_word_ext(addr); } } LOCALPROC put_word_ext(CPTR addr, ui5r w) { if (0 != (addr & 0x01)) { put_byte(addr, w >> 8); put_byte(addr + 1, w); } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = FindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_writereadymask)) { SetUpMATC(®s.MATCwrW, p); regs.MATCwrW.cmpmask |= 0x01; m = p->usebase + (addr & p->usemask); do_put_mem_word(m, w); } else if (0 != (AccFlags & kATTA_mmdvmask)) { (void) MMDV_Access(p, w & 0x0000FFFF, trueblnr, falseblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } else { /* fail */ } } else { /* fail */ } } } LOCALPROC MayNotInline put_word(CPTR addr, ui5r w) { ui3p m = (addr & regs.MATCwrW.usemask) + regs.MATCwrW.usebase; if ((addr & regs.MATCwrW.cmpmask) == regs.MATCwrW.cmpvalu) { do_put_mem_word(m, w); } else { put_word_ext(addr, w); } } LOCALFUNC ui5r get_long_ext(CPTR addr) { ui5r hi = get_word(addr); ui5r lo = get_word(addr + 2); ui5r Data = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); return ui5r_FromSLong(Data); } LOCALFUNC MayNotInline ui5r get_long(CPTR addr) { CPTR addr2 = addr + 2; ui3p m = (addr & regs.MATCrdW.usemask) + regs.MATCrdW.usebase; ui3p m2 = (addr2 & regs.MATCrdW.usemask) + regs.MATCrdW.usebase; if (((addr & regs.MATCrdW.cmpmask) == regs.MATCrdW.cmpvalu) && ((addr2 & regs.MATCrdW.cmpmask) == regs.MATCrdW.cmpvalu)) { ui5r hi = do_get_mem_word(m); ui5r lo = do_get_mem_word(m2); ui5r Data = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); return ui5r_FromSLong(Data); } else { return get_long_ext(addr); } } LOCALPROC put_long_ext(CPTR addr, ui5r l) { put_word(addr, l >> 16); put_word(addr + 2, l); } LOCALPROC MayNotInline put_long(CPTR addr, ui5r l) { CPTR addr2 = addr + 2; ui3p m = (addr & regs.MATCwrW.usemask) + regs.MATCwrW.usebase; ui3p m2 = (addr2 & regs.MATCwrW.usemask) + regs.MATCwrW.usebase; if (((addr & regs.MATCwrW.cmpmask) == regs.MATCwrW.cmpvalu) && ((addr2 & regs.MATCwrW.cmpmask) == regs.MATCwrW.cmpvalu)) { do_put_mem_word(m, l >> 16); do_put_mem_word(m2, l); } else { put_long_ext(addr, l); } } #if ! USE_POINTER LOCALFUNC ui4r get_pc_word_ext(void) { ui4r Data; CPTR addr = regs.pc; if (0 != (addr & 0x01)) { Data = 0; /* fail */ /* should be an error, if had way to return it */ #if 0 ui4r hi = get_byte(addr); ui4r lo = get_byte(addr + 1); Data = ((hi << 8) & 0x0000FF00) | (lo & 0x000000FF); #endif } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = FindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_readreadymask)) { SetUpMATC(®s.MATCex, p); regs.MATCex.cmpmask |= 0x01; m = p->usebase + (addr & p->usemask); Data = do_get_mem_word(m); } else /* no, don't run from device if (0 != (AccFlags & kATTA_mmdvmask)) { Data = MMDV_Access(p, 0, falseblnr, falseblnr, addr); } else */ if (0 != (AccFlags & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } else { Data = 0; /* fail */ } } else { Data = 0; /* fail */ } } return Data; } #endif LOCALFUNC MayInline ui4r nextiword(void) /* NOT sign extended */ { #if USE_POINTER ui4r r = do_get_mem_word(regs.pc_p); regs.pc_p += 2; return r; #else ui3p m; ui4r Data; CPTR addr = regs.pc; m = (addr & regs.MATCex.usemask) + regs.MATCex.usebase; if ((addr & regs.MATCex.cmpmask) == regs.MATCex.cmpvalu) { Data = do_get_mem_word(m); } else { Data = get_pc_word_ext(); } regs.pc = addr + 2; return Data; #endif } LOCALFUNC MayInline ui3r nextibyte(void) { #if USE_POINTER ui3r r = do_get_mem_byte(regs.pc_p + 1); regs.pc_p += 2; return r; #else return (ui3b) nextiword(); #endif } LOCALFUNC MayInline ui5r nextilong(void) { #if USE_POINTER ui5r r = do_get_mem_long(regs.pc_p); regs.pc_p += 4; #else ui5r hi = nextiword(); ui5r lo = nextiword(); ui5r r = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); #endif return r; } LOCALFUNC MayInline void BackupPC(void) { #if USE_POINTER regs.pc_p -= 2; #else regs.pc -= 2; #endif } LOCALFUNC MayInline void SkipiWord(void) { #if USE_POINTER regs.pc_p += 2; #else regs.pc += 2; #endif } #if Use68020 LOCALFUNC MayInline void SkipiLong(void) { #if USE_POINTER regs.pc_p += 4; #else regs.pc += 4; #endif } #endif #ifndef WantDumpAJump #define WantDumpAJump 0 #endif #if WantDumpAJump LOCALPROC DumpAJump(CPTR toaddr) { #if USE_POINTER CPTR fromaddr = regs.pc + (regs.pc_p - regs.pc_oldp); if ((toaddr > fromaddr) || (toaddr < regs.pc)) #else CPTR fromaddr = regs.pc; #endif { dbglog_writeHex(fromaddr); dbglog_writeCStr(","); dbglog_writeHex(toaddr); dbglog_writeReturn(); } } #endif #if USE_POINTER LOCALFUNC ui3p get_pc_real_address(CPTR addr) { ui3p v; ATTep p; Label_Retry: p = FindATTel(addr); if (0 == (p->Access & kATTA_readreadymask)) { if (0 != (p->Access & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } } /* in trouble if get here */ /* ReportAbnormal("get_pc_real_address fails"); */ v = regs.fakeword; regs.MATCex.cmpmask = 0; regs.MATCex.cmpvalu = 0xFFFFFFFF; } else { SetUpMATC(®s.MATCex, p); v = (addr & p->usemask) + p->usebase; } return v; } #endif LOCALFUNC MayInline void m68k_setpc(CPTR newpc) { #if WantDumpAJump DumpAJump(newpc); #endif #if 0 if (newpc == 0xBD50 /* 401AB4 */) { /* Debugger(); */ /* Exception(5); */ /* try and get macsbug */ } #endif #if USE_POINTER { ui3p m; m = (newpc & regs.MATCex.usemask) + regs.MATCex.usebase; if ((newpc & regs.MATCex.cmpmask) != regs.MATCex.cmpvalu) { m = get_pc_real_address(newpc); } regs.pc_p = regs.pc_oldp = m; } #endif regs.pc = newpc; } LOCALFUNC MayInline CPTR m68k_getpc(void) { #if USE_POINTER return regs.pc + (regs.pc_p - regs.pc_oldp); #else return regs.pc; #endif } LOCALFUNC ui4b m68k_getSR(void) { return (regs.t1 << 15) #if Use68020 | (regs.t0 << 14) #endif | (regs.s << 13) #if Use68020 | (regs.m << 12) #endif | (regs.intmask << 8) | m68k_getCR(); } LOCALPROC NeedToGetOut(void) { if (regs.MaxCyclesToGo <= 0) { /* already have gotten out, and exception processing has caused another exception, such as because a bad stack pointer pointing to a memory mapped device. */ } else { regs.MoreCyclesToGo += regs.MaxCyclesToGo; /* not counting the current instruction */ regs.MaxCyclesToGo = 0; } } LOCALPROC SetExternalInterruptPending(void) { regs.ExternalInterruptPending = trueblnr; NeedToGetOut(); } #define m68k_dreg(num) (regs.regs[(num)]) #define m68k_areg(num) (regs.regs[(num) + 8]) LOCALPROC m68k_setSR(ui4r newsr) { CPTR *pnewstk; CPTR *poldstk = regs.s ? ( #if Use68020 regs.m ? ®s.msp : #endif ®s.isp) : ®s.usp; ui5r oldintmask = regs.intmask; m68k_setCR(newsr); regs.t1 = (newsr >> 15) & 1; #if Use68020 regs.t0 = (newsr >> 14) & 1; if (regs.t0) { ReportAbnormal("t0 flag set in m68k_setSR"); } #endif regs.s = (newsr >> 13) & 1; #if Use68020 regs.m = (newsr >> 12) & 1; if (regs.m) { ReportAbnormal("m flag set in m68k_setSR"); } #endif regs.intmask = (newsr >> 8) & 7; pnewstk = regs.s ? ( #if Use68020 regs.m ? ®s.msp : #endif ®s.isp) : ®s.usp; if (poldstk != pnewstk) { *poldstk = m68k_areg(7); m68k_areg(7) = *pnewstk; } if (regs.intmask != oldintmask) { SetExternalInterruptPending(); } if (regs.t1) { NeedToGetOut(); } else { /* regs.TracePending = falseblnr; */ } } #ifndef FastRelativeJump #define FastRelativeJump (1 && USE_POINTER) #endif LOCALPROC ExceptionTo(CPTR newpc #if Use68020 , int nr #endif ) { ui4b saveSR = m68k_getSR(); if (! regs.s) { regs.usp = m68k_areg(7); m68k_areg(7) = #if Use68020 regs.m ? regs.msp : #endif regs.isp; regs.s = 1; } #if Use68020 switch (nr) { case 5: /* Zero Divide */ case 6: /* CHK, CHK2 */ case 7: /* cpTRAPcc, TRAPCcc, TRAPv */ case 9: /* Trace */ m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); m68k_areg(7) -= 2; put_word(m68k_areg(7), 0x2000 + nr * 4); break; default: m68k_areg(7) -= 2; put_word(m68k_areg(7), nr * 4); break; } /* if regs.m should make throw away stack frame */ #endif m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); m68k_areg(7) -= 2; put_word(m68k_areg(7), saveSR); m68k_setpc(newpc); regs.t1 = 0; #if Use68020 regs.t0 = 0; regs.m = 0; #endif regs.TracePending = falseblnr; } LOCALPROC Exception(int nr) { ExceptionTo(get_long(4 * nr #if Use68020 + regs.vbr #endif ) #if Use68020 , nr #endif ); } LOCALFUNC MayNotInline ui5b get_disp_ea(ui5b base) { ui4b dp = nextiword(); int regno = (dp >> 12) & 0x0F; si5b regd = regs.regs[regno]; if ((dp & 0x0800) == 0) { regd = (si5b)(si4b)regd; } #if Use68020 regd <<= (dp >> 9) & 3; #if ExtraAbnormalReports if (((dp >> 9) & 3) != 0) { /* ReportAbnormal("Have scale in Extension Word"); */ /* apparently can happen in Sys 7.5.5 boot on 68000 */ } #endif if (dp & 0x0100) { if ((dp & 0x80) != 0) { base = 0; /* ReportAbnormal("Extension Word: suppress base"); */ /* used by Sys 7.5.5 boot */ } if ((dp & 0x40) != 0) { regd = 0; /* ReportAbnormal("Extension Word: suppress regd"); */ /* used by Mac II boot */ } switch ((dp >> 4) & 0x03) { case 0: /* reserved */ ReportAbnormal("Extension Word: dp reserved"); break; case 1: /* no displacement */ /* ReportAbnormal("Extension Word: no displacement"); */ /* used by Sys 7.5.5 boot */ break; case 2: base += (si5b)(si4b)nextiword(); /* ReportAbnormal("Extension Word: word displacement"); */ /* used by Sys 7.5.5 boot */ break; case 3: base += nextilong(); /* ReportAbnormal("Extension Word: long displacement"); */ /* used by Mac II boot from system 6.0.8? */ break; } if ((dp & 0x03) == 0) { base += regd; if ((dp & 0x04) != 0) { ReportAbnormal("Extension Word: reserved dp form"); } /* ReportAbnormal("Extension Word: noindex"); */ /* used by Sys 7.5.5 boot */ } else { if ((dp & 0x04) != 0) { base = get_long(base); base += regd; /* ReportAbnormal("Extension Word: postindex"); */ /* used by Sys 7.5.5 boot */ } else { base += regd; base = get_long(base); /* ReportAbnormal("Extension Word: preindex"); */ /* used by Sys 7.5.5 boot */ } switch (dp & 0x03) { case 1: /* null outer displacement */ /* ReportAbnormal( "Extension Word: null outer displacement"); */ /* used by Sys 7.5.5 boot */ break; case 2: base += (si5b)(si4b)nextiword(); /* ReportAbnormal( "Extension Word: word outer displacement"); */ /* used by Mac II boot from system 6.0.8? */ break; case 3: base += nextilong(); /* ReportAbnormal( "Extension Word: long outer displacement"); */ /* used by Mac II boot from system 6.0.8? */ break; } } return base; } else #endif { return base + (si3b)(dp) + regd; } } LOCALFUNC MayNotInline ArgAddrT DecodeSrcDst(ui5r f) { ui5r *p; ArgAddrT v; switch (GetDcoFldAMd(f)) { case kAMdReg : v.rga = ®s.regs[GetDcoFldArgDat(f)]; break; case kAMdIndirect : p = ®s.regs[GetDcoFldArgDat(f)]; v.mem = *p; break; case kAMdAPosIncB : p = ®s.regs[GetDcoFldArgDat(f)]; v.mem = *p; *p += 1; break; case kAMdAPosIncW : p = ®s.regs[GetDcoFldArgDat(f)]; v.mem = *p; *p += 2; break; case kAMdAPosIncL : p = ®s.regs[GetDcoFldArgDat(f)]; v.mem = *p; *p += 4; break; case kAMdAPreDecB : p = ®s.regs[GetDcoFldArgDat(f)]; *p -= 1; v.mem = *p; break; case kAMdAPreDecW : p = ®s.regs[GetDcoFldArgDat(f)]; *p -= 2; v.mem = *p; break; case kAMdAPreDecL : p = ®s.regs[GetDcoFldArgDat(f)]; *p -= 4; v.mem = *p; break; case kAMdADisp : p = ®s.regs[GetDcoFldArgDat(f)]; v.mem = *p + ui5r_FromSWord(nextiword()); break; case kAMdAIndex : p = ®s.regs[GetDcoFldArgDat(f)]; v.mem = get_disp_ea(*p); break; case kAMdAbsW : v.mem = ui5r_FromSWord(nextiword()); break; case kAMdAbsL : v.mem = nextilong(); break; case kAMdPCDisp : v.mem = m68k_getpc(); v.mem += ui5r_FromSWord(nextiword()); break; case kAMdPCIndex : v.mem = get_disp_ea(m68k_getpc()); break; case kAMdImmedB : v.mem = ui5r_FromSByte(nextibyte()); break; case kAMdImmedW : v.mem = ui5r_FromSWord(nextiword()); break; case kAMdImmedL : v.mem = ui5r_FromSLong(nextilong()); break; case kAMdDat4 : default: /* make compiler happy, should not happen */ v.mem = GetDcoFldArgDat(f); break; } return v; } LOCALFUNC MayNotInline ui5r GetSrcDstValue(ui5r f, ArgAddrT addr) { ui5r v; switch (GetDcoFldArgk(f)) { case kArgkRegB: v = ui5r_FromSByte(*addr.rga); break; case kArgkRegW: v = ui5r_FromSWord(*addr.rga); break; case kArgkRegL: v = ui5r_FromSLong(*addr.rga); break; case kArgkMemB: v = get_byte(addr.mem); break; case kArgkMemW: v = get_word(addr.mem); break; case kArgkMemL: v = get_long(addr.mem); break; case kArgkCnst: default: /* for compiler. shouldn't be any other cases */ v = addr.mem; break; } return v; } LOCALPROC MayNotInline SetSrcDstValue(ui5r f, ArgAddrT addr, ui5r v) { switch (GetDcoFldArgk(f)) { case kArgkRegB: *addr.rga = (*addr.rga & ~ 0xff) | ((v) & 0xff); break; case kArgkRegW: *addr.rga = (*addr.rga & ~ 0xffff) | ((v) & 0xffff); break; case kArgkRegL: *addr.rga = v; break; case kArgkMemB: put_byte(addr.mem, v); break; case kArgkMemW: put_word(addr.mem, v); break; case kArgkMemL: put_long(addr.mem, v); break; default: /* for compiler. shouldn't be any other cases */ break; } } LOCALFUNC MayInline ArgAddrT DecodeSrc(void) { return DecodeSrcDst(regs.CurDecOp.B); } LOCALFUNC MayInline ui5r GetSrcValue(ArgAddrT addr) { return GetSrcDstValue(regs.CurDecOp.B, addr); } LOCALFUNC MayInline ArgAddrT DecodeDst(void) { return DecodeSrcDst(regs.CurDecOp.A); } LOCALFUNC MayInline ui5r GetDstValue(ArgAddrT addr) { return GetSrcDstValue(regs.CurDecOp.A, addr); } LOCALPROC MayInline SetDstValue(ArgAddrT addr, ui5r v) { SetSrcDstValue(regs.CurDecOp.A, addr, v); } LOCALFUNC MayNotInline ui5r DecodeSrcDstGet(void) { ArgAddrT SrcAddr = DecodeSrc(); ui5r srcvalue = GetSrcValue(SrcAddr); ArgAddrT DstAddr = DecodeDst(); ui5r dstvalue = GetDstValue(DstAddr); regs.SrcVal = srcvalue; regs.ArgAddr = DstAddr; return dstvalue; } LOCALFUNC MayNotInline ui5r DecodeDstGet(void) { ArgAddrT DstAddr = DecodeDst(); ui5r dstvalue = GetDstValue(DstAddr); regs.ArgAddr = DstAddr; return dstvalue; } LOCALPROC MayNotInline SetDstArgValue(ui5r v) { SetDstValue(regs.ArgAddr, v); } LOCALPROCUSEDONCE DoCodeTst(void) { /* Tst 01001010ssmmmrrr */ ArgAddrT DstAddr = DecodeDst(); ui5r srcvalue = GetDstValue(DstAddr); VFLG = CFLG = 0; ZFLG = (srcvalue == 0); NFLG = ui5r_MSBisSet(srcvalue); } LOCALPROCUSEDONCE DoCodeCmpB(void) { ui5r dstvalue = DecodeSrcDstGet(); ALU_CmpB(regs.SrcVal, dstvalue); } LOCALPROCUSEDONCE DoCodeCmpW(void) { ui5r dstvalue = DecodeSrcDstGet(); ALU_CmpW(regs.SrcVal, dstvalue); } LOCALPROCUSEDONCE DoCodeCmpL(void) { ui5r dstvalue = DecodeSrcDstGet(); ALU_CmpL(regs.SrcVal, dstvalue); } LOCALPROCUSEDONCE DoCodeBraB(void) { ui5b src = ((ui5b)regs.opcode) & 255; #if FastRelativeJump ui3p s = regs.pc_p; #else ui5r s = m68k_getpc(); #endif s += (si3b)(ui3b)src; #if FastRelativeJump regs.pc_p = s; #else m68k_setpc(s); #endif } LOCALPROCUSEDONCE DoCodeBraW(void) { #if FastRelativeJump ui3p s = regs.pc_p; #else ui5r s = m68k_getpc(); #endif s += (si4b)(ui4b)nextiword(); #if FastRelativeJump regs.pc_p = s; #else m68k_setpc(s); #endif } #if Use68020 LOCALPROCUSEDONCE DoCodeBraL(void) { #if FastRelativeJump ui3p s = regs.pc_p; #else ui5r s = m68k_getpc(); #endif s += (si5b)(ui5b)nextilong(); /* Bra 0110ccccnnnnnnnn */ #if FastRelativeJump regs.pc_p = s; #else m68k_setpc(s); #endif } #endif LOCALPROCUSEDONCE DoCodeBccB(void) { /* Bcc 0110ccccnnnnnnnn */ if (cctrue()) { #if WantCloserCyc regs.MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); #endif DoCodeBraB(); } else { #if WantCloserCyc regs.MaxCyclesToGo -= (8 * kCycleScale + RdAvgXtraCyc); #endif /* do nothing */ } } LOCALPROCUSEDONCE DoCodeBccW(void) { /* Bcc 0110ccccnnnnnnnn */ if (cctrue()) { #if WantCloserCyc regs.MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); #endif DoCodeBraW(); } else { #if WantCloserCyc regs.MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc); #endif SkipiWord(); } } #if Use68020 LOCALPROCUSEDONCE DoCodeBccL(void) { /* Bcc 0110ccccnnnnnnnn */ if (cctrue()) { DoCodeBraL(); } else { SkipiLong(); } } #endif #define reg (regs.opcode & 7) #define rg9 ((regs.opcode >> 9) & 7) LOCALPROCUSEDONCE DoCodeDBcc(void) { /* DBcc 0101cccc11001ddd */ ui5r dstvalue; #if FastRelativeJump ui3p srcvalue = regs.pc_p; #else ui5r srcvalue = m68k_getpc(); #endif srcvalue += (si4b)(ui4b)nextiword(); if (cctrue()) { #if WantCloserCyc regs.MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc); #endif } else { dstvalue = ui5r_FromSWord(m68k_dreg(reg)); --dstvalue; m68k_dreg(reg) = (m68k_dreg(reg) & ~ 0xffff) | ((dstvalue) & 0xffff); if ((si5b)dstvalue == -1) { #if WantCloserCyc regs.MaxCyclesToGo -= (14 * kCycleScale + 3 * RdAvgXtraCyc); #endif } else { #if WantCloserCyc regs.MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); #endif #if FastRelativeJump regs.pc_p = srcvalue; #else m68k_setpc(srcvalue); #endif } } } LOCALPROCUSEDONCE DoCodeSwap(void) { /* Swap 0100100001000rrr */ ui5r srcreg = reg; ui5r src = m68k_dreg(srcreg); ui5r dst = ui5r_FromSLong(((src >> 16) & 0xFFFF) | ((src & 0xFFFF) << 16)); VFLG = CFLG = 0; ZFLG = (dst == 0); NFLG = ui5r_MSBisSet(dst); m68k_dreg(srcreg) = dst; } LOCALPROCUSEDONCE DoCodeMove(void) { ArgAddrT SrcAddr = DecodeSrc(); ui5r src = GetSrcValue(SrcAddr); ArgAddrT DstAddr = DecodeDst(); VFLG = CFLG = 0; ZFLG = (src == 0); NFLG = ui5r_MSBisSet(src); SetDstValue(DstAddr, src); } LOCALPROC DoCodeMoveA(void) /* MOVE */ { ArgAddrT SrcAddr; ui5r src; SrcAddr = DecodeSrc(); src = GetSrcValue(SrcAddr); m68k_areg(rg9) = src; } LOCALPROCUSEDONCE DoCodeMoveQ(void) { /* MoveQ 0111ddd0nnnnnnnn */ ui5r src = ui5r_FromSByte(regs.opcode); ui5r dstreg = rg9; VFLG = CFLG = 0; ZFLG = (src == 0); NFLG = ui5r_MSBisSet(src); m68k_dreg(dstreg) = src; } LOCALPROCUSEDONCE DoCodeAddB(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_AddB(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeAddW(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_AddW(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeAddL(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_AddL(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeSubB(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_SubB(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeSubW(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_SubW(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeSubL(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_SubL(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeLea(void) { ArgAddrT DstAddr; /* Lea 0100aaa111mmmrrr */ DstAddr = DecodeDst(); m68k_areg(rg9) = DstAddr.mem; } LOCALPROCUSEDONCE DoCodePEA(void) { ArgAddrT DstAddr; /* PEA 0100100001mmmrrr */ DstAddr = DecodeDst(); m68k_areg(7) -= 4; put_long(m68k_areg(7), DstAddr.mem); } LOCALPROCUSEDONCE DoCodeA(void) { BackupPC(); Exception(0xA); } LOCALPROCUSEDONCE DoCodeBsrB(void) { ui5b src = ((ui5b)regs.opcode) & 255; #if FastRelativeJump ui3p s = regs.pc_p; #else ui5r s = m68k_getpc(); #endif s += (si3b)(ui3b)src; m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); #if FastRelativeJump regs.pc_p = s; #else m68k_setpc(s); #endif } LOCALPROCUSEDONCE DoCodeBsrW(void) { #if FastRelativeJump ui3p s = regs.pc_p; #else ui5r s = m68k_getpc(); #endif s += (si4b)(ui4b)nextiword(); m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); #if FastRelativeJump regs.pc_p = s; #else m68k_setpc(s); #endif } #if Use68020 LOCALPROCUSEDONCE DoCodeBsrL(void) { #if FastRelativeJump ui3p s = regs.pc_p; #else ui5r s = m68k_getpc(); #endif s += (si5b)(ui5b)nextilong(); /* ReportAbnormal("long branch in DoCode6"); */ /* Used by various Apps */ m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); #if FastRelativeJump regs.pc_p = s; #else m68k_setpc(s); #endif } #endif LOCALPROCUSEDONCE DoCodeJsr(void) { /* Jsr 0100111010mmmrrr */ ArgAddrT DstAddr = DecodeDst(); m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); m68k_setpc(DstAddr.mem); } LOCALPROCUSEDONCE DoCodeLinkA6(void) { CPTR stackp = m68k_areg(7); stackp -= 4; put_long(stackp, m68k_areg(6)); m68k_areg(6) = stackp; m68k_areg(7) = stackp + ui5r_FromSWord(nextiword()); } LOCALPROCUSEDONCE DoCodeMOVEMRmML(void) { /* MOVEM reg to mem 01001000111100rrr */ si4b z; ui5r regmask = nextiword(); ui5r p = m68k_areg(reg); #if Use68020 { int n = 0; for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { n++; } } m68k_areg(reg) = p - n * 4; } #endif for (z = 16; --z >= 0; ) { if ((regmask & (1 << (15 - z))) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc); #endif p -= 4; put_long(p, regs.regs[z]); } } #if ! Use68020 m68k_areg(reg) = p; #endif } LOCALPROCUSEDONCE DoCodeMOVEMApRL(void) { /* MOVEM mem to reg 01001100111011rrr */ si4b z; ui5r regmask = nextiword(); ui5r p = m68k_areg(reg); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc); #endif regs.regs[z] = get_long(p); p += 4; } } m68k_areg(reg) = p; } LOCALPROCUSEDONCE DoCodeUnlkA6(void) { ui5r src = m68k_areg(6); m68k_areg(6) = get_long(src); m68k_areg(7) = src + 4; } LOCALPROCUSEDONCE DoCodeRts(void) { /* Rts 0100111001110101 */ ui5r NewPC = get_long(m68k_areg(7)); m68k_areg(7) += 4; m68k_setpc(NewPC); } LOCALPROCUSEDONCE DoCodeJmp(void) { /* JMP 0100111011mmmrrr */ ArgAddrT DstAddr = DecodeDst(); m68k_setpc(DstAddr.mem); } LOCALPROCUSEDONCE DoCodeClr(void) { /* Clr 01000010ssmmmrrr */ ArgAddrT DstAddr = DecodeDst(); VFLG = CFLG = 0; ZFLG = 1; NFLG = 0; SetDstValue(DstAddr, 0); } LOCALPROCUSEDONCE DoCodeAddA(void) { /* ADDA 1101dddm11mmmrrr */ ui5r dstvalue = DecodeSrcDstGet(); dstvalue += regs.SrcVal; SetDstArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeSubA(void) { ui5r dstvalue = DecodeSrcDstGet(); dstvalue -= regs.SrcVal; SetDstArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeCmpA(void) { ui5r dstvalue = DecodeSrcDstGet(); { int flgs = ui5r_MSBisSet(regs.SrcVal); int flgo = ui5r_MSBisSet(dstvalue); dstvalue -= regs.SrcVal; dstvalue = ui5r_FromSLong(dstvalue); ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = (flgs != flgo) && (NFLG != flgo); CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); } } LOCALPROCUSEDONCE DoCodeAddXB(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_AddXB(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeAddXW(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_AddXW(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeAddXL(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_AddXL(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeSubXB(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_SubXB(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeSubXW(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_SubXW(regs.SrcVal, dstvalue)); } LOCALPROCUSEDONCE DoCodeSubXL(void) { ui5r dstvalue = DecodeSrcDstGet(); SetDstArgValue(ALU_SubXL(regs.SrcVal, dstvalue)); } LOCALPROC SetArgKindReg(ui5b thereg) { regs.ArgKind = AKRegister; regs.ArgAddr.rga = ®s.regs[thereg]; } LOCALPROC MayNotInline DecodeModeRegister(ui5b themode, ui5b thereg) { switch (themode) { case 0 : SetArgKindReg(thereg); break; case 1 : SetArgKindReg(thereg + 8); break; case 2 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = m68k_areg(thereg); break; case 3 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = m68k_areg(thereg); if ((thereg == 7) && (regs.opsize == 1)) { m68k_areg(thereg) += 2; } else { m68k_areg(thereg) += regs.opsize; } break; case 4 : regs.ArgKind = AKMemory; if ((thereg == 7) && (regs.opsize == 1)) { m68k_areg(thereg) -= 2; } else { m68k_areg(thereg) -= regs.opsize; } regs.ArgAddr.mem = m68k_areg(thereg); break; case 5 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = m68k_areg(thereg) + ui5r_FromSWord(nextiword()); break; case 6 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = get_disp_ea(m68k_areg(thereg)); break; case 7 : switch (thereg) { case 0 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = ui5r_FromSWord(nextiword()); break; case 1 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = nextilong(); break; case 2 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = m68k_getpc(); regs.ArgAddr.mem += ui5r_FromSWord(nextiword()); break; case 3 : regs.ArgKind = AKMemory; regs.ArgAddr.mem = get_disp_ea(m68k_getpc()); break; case 4 : regs.ArgKind = AKConstant; if (regs.opsize == 2) { regs.ArgAddr.mem = ui5r_FromSWord(nextiword()); } else if (regs.opsize < 2) { regs.ArgAddr.mem = ui5r_FromSByte(nextibyte()); } else { regs.ArgAddr.mem = ui5r_FromSLong(nextilong()); } break; } break; case 8 : regs.ArgKind = AKConstant; regs.ArgAddr.mem = thereg; break; } } LOCALFUNC ui5r GetArgValue(void) { ui5r v; switch (regs.ArgKind) { case AKMemory: if (regs.opsize == 2) { v = get_word(regs.ArgAddr.mem); } else if (regs.opsize < 2) { v = get_byte(regs.ArgAddr.mem); } else { v = get_long(regs.ArgAddr.mem); } break; case AKRegister: v = *regs.ArgAddr.rga; if (regs.opsize == 2) { v = ui5r_FromSWord(v); } else if (regs.opsize < 2) { v = ui5r_FromSByte(v); } else { v = ui5r_FromSLong(v); } break; case AKConstant: default: /* for compiler. shouldn't be any other cases */ v = regs.ArgAddr.mem; break; } return v; } LOCALPROC SetArgValue(ui5r v) { if (regs.ArgKind == AKRegister) { if (regs.opsize == 2) { *regs.ArgAddr.rga = (*regs.ArgAddr.rga & ~ 0xffff) | ((v) & 0xffff); } else if (regs.opsize < 2) { *regs.ArgAddr.rga = (*regs.ArgAddr.rga & ~ 0xff) | ((v) & 0xff); } else { *regs.ArgAddr.rga = v; } } else { /* must be AKMemory */ /* should not get here for AKConstant */ if (regs.opsize == 2) { put_word(regs.ArgAddr.mem, v); } else if (regs.opsize < 2) { put_byte(regs.ArgAddr.mem, v); } else { put_long(regs.ArgAddr.mem, v); } } } #define b76 ((regs.opcode >> 6) & 3) #define b8 ((regs.opcode >> 8) & 1) #define mode ((regs.opcode >> 3) & 7) #define md6 ((regs.opcode >> 6) & 7) LOCALPROC FindOpSizeFromb76(void) { regs.opsize = 1 << b76; #if 0 switch (b76) { case 0 : regs.opsize = 1; break; case 1 : regs.opsize = 2; break; case 2 : regs.opsize = 4; break; } #endif } LOCALFUNC ui5r octdat(ui5r x) { if (x == 0) { return 8; } else { return x; } } #define extendopsizedstvalue() \ if (regs.opsize == 2) {\ dstvalue = ui5r_FromSWord(dstvalue);\ } else if (regs.opsize < 2) {\ dstvalue = ui5r_FromSByte(dstvalue);\ } else {\ dstvalue = ui5r_FromSLong(dstvalue);\ } #define unextendopsizedstvalue() \ if (regs.opsize == 2) {\ dstvalue = ui5r_FromUWord(dstvalue);\ } else if (regs.opsize < 2) {\ dstvalue = ui5r_FromUByte(dstvalue);\ } else {\ dstvalue = ui5r_FromULong(dstvalue);\ } #define BinOpASL 0 #define BinOpASR 1 #define BinOpLSL 2 #define BinOpLSR 3 #define BinOpRXL 4 #define BinOpRXR 5 #define BinOpROL 6 #define BinOpROR 7 LOCALPROC DoBinOp1(ui5r srcvalue, ui5r binop) { ui5r dstvalue; ui5r cnt = srcvalue & 63; dstvalue = GetArgValue(); switch (binop) { case BinOpASL: { ui5r dstvalue0 = dstvalue; ui5r comparevalue; if (! cnt) { VFLG = 0; CFLG = 0; } else { if (cnt > 32) { dstvalue = 0; } else { dstvalue = dstvalue << (cnt - 1); } extendopsizedstvalue(); CFLG = XFLG = ui5r_MSBisSet(dstvalue); dstvalue = dstvalue << 1; extendopsizedstvalue(); } if (ui5r_MSBisSet(dstvalue)) { comparevalue = - ((- dstvalue) >> cnt); } else { comparevalue = dstvalue >> cnt; } VFLG = (comparevalue != dstvalue0); ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); } break; case BinOpASR: { NFLG = ui5r_MSBisSet(dstvalue); VFLG = 0; if (! cnt) { CFLG = 0; } else { if (NFLG) { dstvalue = (~ dstvalue); } unextendopsizedstvalue(); if (cnt > 32) { dstvalue = 0; } else { dstvalue = dstvalue >> (cnt - 1); } CFLG = (dstvalue & 1) != 0; dstvalue = dstvalue >> 1; if (NFLG) { CFLG = ! CFLG; dstvalue = (~ dstvalue); } XFLG = CFLG; } ZFLG = (dstvalue == 0); } break; case BinOpLSL: { if (! cnt) { CFLG = 0; } else { if (cnt > 32) { dstvalue = 0; } else { dstvalue = dstvalue << (cnt - 1); } extendopsizedstvalue(); CFLG = XFLG = ui5r_MSBisSet(dstvalue); dstvalue = dstvalue << 1; extendopsizedstvalue(); } ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = 0; } break; case BinOpLSR: { if (! cnt) { CFLG = 0; } else { unextendopsizedstvalue(); if (cnt > 32) { dstvalue = 0; } else { dstvalue = dstvalue >> (cnt - 1); } CFLG = XFLG = (dstvalue & 1) != 0; dstvalue = dstvalue >> 1; } ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); /* if cnt != 0, always false */ VFLG = 0; } break; case BinOpROL: { if (! cnt) { CFLG = 0; } else { for (; cnt; --cnt) { CFLG = ui5r_MSBisSet(dstvalue); dstvalue = dstvalue << 1; if (CFLG) { dstvalue = dstvalue | 1; } extendopsizedstvalue(); } } ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = 0; } break; case BinOpRXL: { if (! cnt) { CFLG = XFLG; } else { for (; cnt; --cnt) { CFLG = ui5r_MSBisSet(dstvalue); dstvalue = dstvalue << 1; if (XFLG) { dstvalue = dstvalue | 1; } extendopsizedstvalue(); XFLG = CFLG; } } ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = 0; } break; case BinOpROR: { ui5r cmask = (ui5r)1 << (regs.opsize * 8 - 1); if (! cnt) { CFLG = 0; } else { unextendopsizedstvalue(); for (; cnt; --cnt) { CFLG = (dstvalue & 1) != 0; dstvalue = dstvalue >> 1; if (CFLG) { dstvalue = dstvalue | cmask; } } extendopsizedstvalue(); } ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = 0; } break; case BinOpRXR: { ui5r cmask = (ui5r)1 << (regs.opsize * 8 - 1); if (! cnt) { CFLG = XFLG; } else { unextendopsizedstvalue(); for (; cnt; --cnt) { CFLG = (dstvalue & 1) != 0; dstvalue = dstvalue >> 1; if (XFLG) { dstvalue = dstvalue | cmask; } XFLG = CFLG; } extendopsizedstvalue(); } ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = 0; } break; default: /* should not get here */ break; } SetArgValue(dstvalue); } LOCALFUNC ui5r rolops(ui5r x) { ui5r binop; binop = (x << 1); if (! b8) { binop++; /* 'R' */ } /* else 'L' */ return binop; } LOCALPROCUSEDONCE DoCodeRolopNM(void) { regs.opsize = 2; DecodeModeRegister(mode, reg); DoBinOp1(1, rolops(rg9)); } LOCALPROCUSEDONCE DoCodeRolopND(void) { /* 1110cccdss0ttddd */ FindOpSizeFromb76(); SetArgKindReg(reg); DoBinOp1(octdat(rg9), rolops(mode & 3)); } LOCALPROCUSEDONCE DoCodeRolopDD(void) { /* 1110rrrdss1ttddd */ ui5r srcvalue; FindOpSizeFromb76(); SetArgKindReg(rg9); srcvalue = GetArgValue(); SetArgKindReg(reg); #if WantCloserCyc regs.MaxCyclesToGo -= ((srcvalue & 63) * 2 * kCycleScale); #endif DoBinOp1(srcvalue, rolops(mode & 3)); } #define BinOpBTst 0 #define BinOpBChg 1 #define BinOpBClr 2 #define BinOpBSet 3 LOCALPROC DoBinBitOp1(ui5r srcvalue) { ui5r dstvalue; ui5r binop; dstvalue = GetArgValue(); ZFLG = ((dstvalue & ((ui5r)1 << srcvalue)) == 0); binop = b76; if (binop != BinOpBTst) { switch (binop) { case BinOpBChg: dstvalue ^= (1 << srcvalue); break; case BinOpBClr: dstvalue &= ~ (1 << srcvalue); break; case BinOpBSet: dstvalue |= (1 << srcvalue); break; default: /* should not get here */ break; } SetArgValue(dstvalue); } } LOCALPROCUSEDONCE DoCodeBitOpDD(void) { /* dynamic bit, Opcode = 0000ddd1tt000rrr */ ui5r srcvalue = (ui5r_FromSByte(m68k_dreg(rg9))) & 31; regs.opsize = 4; SetArgKindReg(reg); DoBinBitOp1(srcvalue); } LOCALPROCUSEDONCE DoCodeBitOpDM(void) { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ ui5r srcvalue = (ui5r_FromSByte(m68k_dreg(rg9))) & 7; regs.opsize = 1; DecodeModeRegister(mode, reg); DoBinBitOp1(srcvalue); } LOCALPROCUSEDONCE DoCodeBitOpND(void) { /* static bit 00001010tt000rrr */ ui5r srcvalue = (ui5r_FromSByte(nextibyte())) & 31; regs.opsize = 4; SetArgKindReg(reg); DoBinBitOp1(srcvalue); } LOCALPROCUSEDONCE DoCodeBitOpNM(void) { /* static bit 00001010ttmmmrrr */ ui5r srcvalue = (ui5r_FromSByte(nextibyte())) & 7; regs.opsize = 1; DecodeModeRegister(mode, reg); DoBinBitOp1(srcvalue); } LOCALPROCUSEDONCE DoCodeAnd(void) { /* DoBinOpAnd(DecodeI_xxxxxxxxssmmmrrr()); */ ui5r dstvalue = DecodeSrcDstGet(); dstvalue &= regs.SrcVal; /* don't need to extend, since excess high bits all the same as desired high bit. */ VFLG = CFLG = 0; ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); SetDstArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeOr(void) { /* DoBinOr(DecodeI_xxxxxxxxssmmmrrr()); */ ui5r dstvalue = DecodeSrcDstGet(); dstvalue |= regs.SrcVal; /* don't need to extend, since excess high bits all the same as desired high bit. */ VFLG = CFLG = 0; ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); SetDstArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeEor(void) { /* Eor 1011ddd1ssmmmrrr */ /* DoBinOpEor(DecodeDEa_xxxxdddxssmmmrrr()); */ ui5r dstvalue = DecodeSrcDstGet(); dstvalue ^= regs.SrcVal; /* don't need to extend, since excess high bits all the same as desired high bit. */ VFLG = CFLG = 0; ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); SetDstArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeNot(void) { /* Not 01000110ssmmmrrr */ ui5r dstvalue = DecodeDstGet(); dstvalue = ~ dstvalue; ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = CFLG = 0; SetDstArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeScc(void) { /* Scc 0101cccc11mmmrrr */ regs.opsize = 1; DecodeModeRegister(mode, reg); if (cctrue()) { #if WantCloserCyc if (mode == 0) { regs.MaxCyclesToGo -= (2 * kCycleScale); } #endif SetArgValue(0xff); } else { SetArgValue(0); } } LOCALPROCUSEDONCE DoCodeEXTL(void) { /* EXT.L */ ui5r srcreg = reg; ui5r src = m68k_dreg(srcreg); ui5r dst = ui5r_FromSWord(src); VFLG = CFLG = 0; ZFLG = (dst == 0); NFLG = ui5r_MSBisSet(dst); m68k_dreg(srcreg) = dst; } LOCALPROCUSEDONCE DoCodeEXTW(void) { /* EXT.W */ ui5r srcreg = reg; ui5r src = m68k_dreg(srcreg); ui5r dst = ui5r_FromSByte(src); VFLG = CFLG = 0; ZFLG = (dst == 0); NFLG = ui5r_MSBisSet(dst); m68k_dreg(srcreg) = (m68k_dreg(srcreg) & ~ 0xffff) | (dst & 0xffff); } LOCALPROCUSEDONCE DoCodeNegB(void) { ui5r dstvalue = DecodeDstGet(); SetDstArgValue(ALU_NegB(dstvalue)); } LOCALPROCUSEDONCE DoCodeNegW(void) { ui5r dstvalue = DecodeDstGet(); SetDstArgValue(ALU_NegW(dstvalue)); } LOCALPROCUSEDONCE DoCodeNegL(void) { ui5r dstvalue = DecodeDstGet(); SetDstArgValue(ALU_NegL(dstvalue)); } LOCALPROCUSEDONCE DoCodeNegXB(void) { ui5r dstvalue = DecodeDstGet(); SetDstArgValue(ALU_NegXB(dstvalue)); } LOCALPROCUSEDONCE DoCodeNegXW(void) { ui5r dstvalue = DecodeDstGet(); SetDstArgValue(ALU_NegXW(dstvalue)); } LOCALPROCUSEDONCE DoCodeNegXL(void) { ui5r dstvalue = DecodeDstGet(); SetDstArgValue(ALU_NegXL(dstvalue)); } LOCALPROCUSEDONCE DoCodeMulU(void) { /* MulU 1100ddd011mmmrrr */ ui5r srcvalue; ui5r dstvalue; regs.opsize = 2; DecodeModeRegister(mode, reg); srcvalue = GetArgValue(); dstvalue = ui5r_FromSLong(ui5r_FromUWord(regs.regs[rg9]) * ui5r_FromUWord(srcvalue)); #if WantCloserCyc { ui5r v = srcvalue; while (v != 0) { if ((v & 1) != 0) { regs.MaxCyclesToGo -= (2 * kCycleScale); } v >>= 1; } } #endif VFLG = CFLG = 0; ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); regs.regs[rg9] = dstvalue; } LOCALPROCUSEDONCE DoCodeMulS(void) { /* MulS 1100ddd111mmmrrr */ ui5r srcvalue; ui5r dstvalue; regs.opsize = 2; DecodeModeRegister(mode, reg); srcvalue = GetArgValue(); dstvalue = ui5r_FromSLong((si5b)(si4b)regs.regs[rg9] * (si5b)(si4b)srcvalue); #if WantCloserCyc { ui5r v = (srcvalue << 1); while (v != 0) { if ((v & 1) != ((v >> 1) & 1)) { regs.MaxCyclesToGo -= (2 * kCycleScale); } v >>= 1; } } #endif VFLG = CFLG = 0; ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); regs.regs[rg9] = dstvalue; } LOCALPROCUSEDONCE DoCodeDivU(void) { /* DivU 1000ddd011mmmrrr */ ui5r srcvalue; ui5r dstvalue; regs.opsize = 2; DecodeModeRegister(mode, reg); srcvalue = GetArgValue(); dstvalue = regs.regs[rg9]; if (srcvalue == 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(5); #if m68k_logExceptions dbglog_StartLine(); dbglog_writeCStr("*** zero devide exception"); dbglog_writeReturn(); #endif } else { ui5b newv = (ui5b)dstvalue / (ui5b)(ui4b)srcvalue; ui5b rem = (ui5b)dstvalue % (ui5b)(ui4b)srcvalue; #if WantCloserCyc regs.MaxCyclesToGo -= (133 * kCycleScale); #endif if (newv > 0xffff) { VFLG = NFLG = 1; CFLG = 0; } else { VFLG = CFLG = 0; ZFLG = ((si4b)(newv)) == 0; NFLG = ((si4b)(newv)) < 0; newv = (newv & 0xffff) | ((ui5b)rem << 16); dstvalue = newv; } } regs.regs[rg9] = dstvalue; } LOCALPROCUSEDONCE DoCodeDivS(void) { /* DivS 1000ddd111mmmrrr */ ui5r srcvalue; ui5r dstvalue; regs.opsize = 2; DecodeModeRegister(mode, reg); srcvalue = GetArgValue(); dstvalue = regs.regs[rg9]; if (srcvalue == 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(5); #if m68k_logExceptions dbglog_StartLine(); dbglog_writeCStr("*** zero devide exception"); dbglog_writeReturn(); #endif } else { si5b newv = (si5b)dstvalue / (si5b)(si4b)srcvalue; ui4b rem = (si5b)dstvalue % (si5b)(si4b)srcvalue; #if WantCloserCyc regs.MaxCyclesToGo -= (150 * kCycleScale); #endif if (((newv & 0xffff8000) != 0) && ((newv & 0xffff8000) != 0xffff8000)) { VFLG = NFLG = 1; CFLG = 0; } else { if (((si4b)rem < 0) != ((si5b)dstvalue < 0)) { rem = - rem; } VFLG = CFLG = 0; ZFLG = ((si4b)(newv)) == 0; NFLG = ((si4b)(newv)) < 0; newv = (newv & 0xffff) | ((ui5b)rem << 16); dstvalue = newv; } } regs.regs[rg9] = dstvalue; } LOCALPROCUSEDONCE DoCodeExgdd(void) { /* Exg 1100ddd101000rrr, opsize = 4 */ ui5r srcreg = rg9; ui5r dstreg = reg; ui5r src = m68k_dreg(srcreg); ui5r dst = m68k_dreg(dstreg); m68k_dreg(srcreg) = dst; m68k_dreg(dstreg) = src; } LOCALPROCUSEDONCE DoCodeExgaa(void) { /* Exg 1100ddd101001rrr, opsize = 4 */ ui5r srcreg = rg9; ui5r dstreg = reg; ui5r src = m68k_areg(srcreg); ui5r dst = m68k_areg(dstreg); m68k_areg(srcreg) = dst; m68k_areg(dstreg) = src; } LOCALPROCUSEDONCE DoCodeExgda(void) { /* Exg 1100ddd110001rrr, opsize = 4 */ ui5r srcreg = rg9; ui5r dstreg = reg; ui5r src = m68k_dreg(srcreg); ui5r dst = m68k_areg(dstreg); m68k_dreg(srcreg) = dst; m68k_areg(dstreg) = src; } LOCALPROCUSEDONCE DoCodeMoveCCREa(void) { /* Move from CCR 0100001011mmmrrr */ #if ! Use68020 ReportAbnormal("Move from CCR"); #endif regs.opsize = 2; DecodeModeRegister(mode, reg); SetArgValue(m68k_getSR() & 0xFF); } LOCALPROCUSEDONCE DoCodeMoveEaCR(void) { /* 0100010011mmmrrr */ regs.opsize = 2; DecodeModeRegister(mode, reg); m68k_setCR(GetArgValue()); } LOCALPROCUSEDONCE DoCodeMoveSREa(void) { /* Move from SR 0100000011mmmrrr */ regs.opsize = 2; DecodeModeRegister(mode, reg); SetArgValue(m68k_getSR()); } LOCALPROCUSEDONCE DoCodeMoveEaSR(void) { /* 0100011011mmmrrr */ regs.opsize = 2; DecodeModeRegister(mode, reg); m68k_setSR(GetArgValue()); } LOCALPROC DoPrivilegeViolation(void) { #if WantCloserCyc regs.MaxCyclesToGo += GetDcoCycles(®s.CurDecOp); regs.MaxCyclesToGo -= (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif BackupPC(); Exception(8); } LOCALPROC DoBinOpStatusCCR(void) { blnr IsStatus = (b76 != 0); ui5r srcvalue; ui5r dstvalue; FindOpSizeFromb76(); if (IsStatus && (! regs.s)) { DoPrivilegeViolation(); } else { srcvalue = ui5r_FromSWord(nextiword()); dstvalue = m68k_getSR(); switch (rg9) { case 0 : dstvalue |= srcvalue; break; case 1 : dstvalue &= srcvalue; break; case 5 : dstvalue ^= srcvalue; break; default: /* should not happen */ break; } if (IsStatus) { m68k_setSR(dstvalue); } else { m68k_setCR(dstvalue); } } } LOCALPROCUSEDONCE DoCodeMOVEMApRW(void) { /* MOVEM mem to reg 01001100110011rrr */ si4b z; ui5r regmask = nextiword(); ui5r p = m68k_areg(reg); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc); #endif regs.regs[z] = get_word(p); p += 2; } } m68k_areg(reg) = p; } LOCALPROCUSEDONCE DoCodeMOVEMRmMW(void) { /* MOVEM reg to mem 01001000110100rrr */ si4b z; ui5r regmask = nextiword(); ui5r p = m68k_areg(reg); #if Use68020 { int n = 0; for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { n++; } } m68k_areg(reg) = p - n * 2; } #endif for (z = 16; --z >= 0; ) { if ((regmask & (1 << (15 - z))) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc); #endif p -= 2; put_word(p, regs.regs[z]); } } #if ! Use68020 m68k_areg(reg) = p; #endif } LOCALPROC reglist(si4b direction, ui5b m1, ui5b r1) { si4b z; ui5r p; ui5r regmask; regmask = nextiword(); regs.opsize = 2 * b76 - 2; DecodeModeRegister(m1, r1); p = regs.ArgAddr.mem; if (direction == 0) { if (regs.opsize == 2) { for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc); #endif put_word(p, regs.regs[z]); p += 2; } } } else { for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc); #endif put_long(p, regs.regs[z]); p += 4; } } } } else { if (regs.opsize == 2) { for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc); #endif regs.regs[z] = get_word(p); p += 2; } } } else { for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc regs.MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc); #endif regs.regs[z] = get_long(p); p += 4; } } } } } LOCALPROCUSEDONCE DoCodeMOVEMrm(void) { /* MOVEM reg to mem 010010001ssmmmrrr */ reglist(0, mode, reg); } LOCALPROCUSEDONCE DoCodeMOVEMmr(void) { /* MOVEM mem to reg 0100110011smmmrrr */ reglist(1, mode, reg); } LOCALPROC DoBinOpAbcd(ui5b m1, ui5b r1, ui5b m2, ui5b r2) { ui5r srcvalue; ui5r dstvalue; regs.opsize = 1; DecodeModeRegister(m1, r1); srcvalue = GetArgValue(); DecodeModeRegister(m2, r2); dstvalue = GetArgValue(); { /* if (regs.opsize != 1) a bug */ int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ui4b newv_lo = (srcvalue & 0xF) + (dstvalue & 0xF) + (XFLG ? 1 : 0); ui4b newv_hi = (srcvalue & 0xF0) + (dstvalue & 0xF0); ui4b newv; if (newv_lo > 9) { newv_lo += 6; } newv = newv_hi + newv_lo; CFLG = XFLG = (newv & 0x1F0) > 0x90; if (CFLG) { newv += 0x60; } dstvalue = ui5r_FromSByte(newv); if (dstvalue != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(dstvalue); VFLG = (flgs != flgo) && (NFLG != flgo); /* but according to my reference book, VFLG is Undefined for ABCD */ } SetArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeAbcdr(void) { /* ABCD 1100ddd100000rrr */ DoBinOpAbcd(0, reg, 0, rg9); } LOCALPROCUSEDONCE DoCodeAbcdm(void) { /* ABCD 1100ddd100001rrr */ DoBinOpAbcd(4, reg, 4, rg9); } LOCALPROC DoBinOpSbcd(ui5b m1, ui5b r1, ui5b m2, ui5b r2) { ui5r srcvalue; ui5r dstvalue; regs.opsize = 1; DecodeModeRegister(m1, r1); srcvalue = GetArgValue(); DecodeModeRegister(m2, r2); dstvalue = GetArgValue(); { int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ui4b newv_lo = (dstvalue & 0xF) - (srcvalue & 0xF) - (XFLG ? 1 : 0); ui4b newv_hi = (dstvalue & 0xF0) - (srcvalue & 0xF0); ui4b newv; if (newv_lo > 9) { newv_lo -= 6; newv_hi -= 0x10; } newv = newv_hi + (newv_lo & 0xF); CFLG = XFLG = (newv_hi & 0x1F0) > 0x90; if (CFLG) { newv -= 0x60; } dstvalue = ui5r_FromSByte(newv); if (dstvalue != 0) { ZFLG = 0; } NFLG = ui5r_MSBisSet(dstvalue); VFLG = (flgs != flgo) && (NFLG != flgo); /* but according to my reference book, VFLG is Undefined for SBCD */ } SetArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeSbcdr(void) { /* SBCD 1000xxx100000xxx */ DoBinOpSbcd(0, reg, 0, rg9); } LOCALPROCUSEDONCE DoCodeSbcdm(void) { /* SBCD 1000xxx100001xxx */ DoBinOpSbcd(4, reg, 4, rg9); } LOCALPROCUSEDONCE DoCodeNbcd(void) { /* Nbcd 0100100000mmmrrr */ ui5r dstvalue; regs.opsize = 1; DecodeModeRegister(mode, reg); dstvalue = GetArgValue(); { ui4b newv_lo = - (dstvalue & 0xF) - (XFLG ? 1 : 0); ui4b newv_hi = - (dstvalue & 0xF0); ui4b newv; if (newv_lo > 9) { newv_lo -= 6; newv_hi -= 0x10; } newv = newv_hi + (newv_lo & 0xF); CFLG = XFLG = (newv_hi & 0x1F0) > 0x90; if (CFLG) { newv -= 0x60; } dstvalue = ui5r_FromSByte(newv); NFLG = ui5r_MSBisSet(dstvalue); if (dstvalue != 0) { ZFLG = 0; } } SetArgValue(dstvalue); } LOCALPROCUSEDONCE DoCodeRte(void) { /* Rte 0100111001110011 */ if (! regs.s) { DoPrivilegeViolation(); } else { ui5r NewPC; CPTR stackp = m68k_areg(7); ui5r NewSR = get_word(stackp); stackp += 2; NewPC = get_long(stackp); stackp += 4; #if Use68020 { ui4b format = get_word(stackp); stackp += 2; switch ((format >> 12) & 0x0F) { case 0: /* ReportAbnormal("rte stack frame format 0"); */ break; case 1: ReportAbnormal("rte stack frame format 1"); NewPC = m68k_getpc() - 2; /* rerun instruction */ break; case 2: ReportAbnormal("rte stack frame format 2"); stackp += 4; break; case 9: ReportAbnormal("rte stack frame format 9"); stackp += 12; break; case 10: ReportAbnormal("rte stack frame format 10"); stackp += 24; break; case 11: ReportAbnormal("rte stack frame format 11"); stackp += 84; break; default: ReportAbnormal("unknown rte stack frame format"); Exception(14); return; break; } } #endif m68k_areg(7) = stackp; m68k_setSR(NewSR); m68k_setpc(NewPC); } } LOCALPROCUSEDONCE DoCodeNop(void) { /* Nop 0100111001110001 */ } LOCALPROCUSEDONCE DoCodeMoveP(void) { /* MoveP 0000ddd1mm001aaa */ ui5r TheReg = reg; ui5r TheRg9 = rg9; ui5r Displacement = nextiword(); /* shouldn't this sign extend ? */ CPTR memp = m68k_areg(TheReg) + Displacement; #if 0 if ((Displacement & 0x00008000) != 0) { /* **** for testing only **** */ BackupPC(); op_illg(); } #endif switch (b76) { case 0: { ui4b val = ((get_byte(memp) & 0x00FF) << 8) | (get_byte(memp + 2) & 0x00FF); m68k_dreg(TheRg9) = (m68k_dreg(TheRg9) & ~ 0xffff) | (val & 0xffff); } break; case 1: { ui5b val = ((get_byte(memp) & 0x00FF) << 24) | ((get_byte(memp + 2) & 0x00FF) << 16) | ((get_byte(memp + 4) & 0x00FF) << 8) | (get_byte(memp + 6) & 0x00FF); m68k_dreg(TheRg9) = val; } break; case 2: { si4b src = m68k_dreg(TheRg9); put_byte(memp, src >> 8); put_byte(memp + 2, src); } break; case 3: { si5b src = m68k_dreg(TheRg9); put_byte(memp, src >> 24); put_byte(memp + 2, src >> 16); put_byte(memp + 4, src >> 8); put_byte(memp + 6, src); } break; } } LOCALPROC op_illg(void) { BackupPC(); Exception(4); } LOCALPROC DoCheck(void) { ui5r srcvalue; ui5r dstvalue; DecodeModeRegister(mode, reg); srcvalue = GetArgValue(); DecodeModeRegister(0, rg9); dstvalue = GetArgValue(); if (ui5r_MSBisSet(dstvalue)) { #if WantCloserCyc regs.MaxCyclesToGo -= (30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif NFLG = 1; Exception(6); } else if (((si5r)dstvalue) > ((si5r)srcvalue)) { #if WantCloserCyc regs.MaxCyclesToGo -= (30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif NFLG = 0; Exception(6); } } LOCALPROCUSEDONCE DoCodeChkW(void) { /* Chk.W 0100ddd110mmmrrr */ regs.opsize = 2; DoCheck(); } LOCALPROCUSEDONCE DoCodeTrap(void) { /* Trap 010011100100vvvv */ Exception((regs.opcode & 15) + 32); } LOCALPROCUSEDONCE DoCodeTrapV(void) { /* TrapV 0100111001110110 */ if (VFLG) { #if WantCloserCyc regs.MaxCyclesToGo += GetDcoCycles(®s.CurDecOp); regs.MaxCyclesToGo -= (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(7); } } LOCALPROCUSEDONCE DoCodeRtr(void) { /* Rtr 0100111001110111 */ ui5r NewPC; CPTR stackp = m68k_areg(7); ui5r NewCR = get_word(stackp); stackp += 2; NewPC = get_long(stackp); stackp += 4; m68k_areg(7) = stackp; m68k_setCR(NewCR); m68k_setpc(NewPC); } LOCALPROCUSEDONCE DoCodeLink(void) { ui5r srcreg = reg; CPTR stackp = m68k_areg(7); stackp -= 4; m68k_areg(7) = stackp; /* only matters if srcreg == 7 */ put_long(stackp, m68k_areg(srcreg)); m68k_areg(srcreg) = stackp; m68k_areg(7) += ui5r_FromSWord(nextiword()); } LOCALPROCUSEDONCE DoCodeUnlk(void) { ui5r srcreg = reg; if (srcreg != 7) { ui5r src = m68k_areg(srcreg); m68k_areg(srcreg) = get_long(src); m68k_areg(7) = src + 4; } else { /* wouldn't expect this to happen */ m68k_areg(7) = get_long(m68k_areg(7)) + 4; } } LOCALPROCUSEDONCE DoCodeMoveRUSP(void) { /* MOVE USP 0100111001100aaa */ if (! regs.s) { DoPrivilegeViolation(); } else { regs.usp = m68k_areg(reg); } } LOCALPROCUSEDONCE DoCodeMoveUSPR(void) { /* MOVE USP 0100111001101aaa */ if (! regs.s) { DoPrivilegeViolation(); } else { m68k_areg(reg) = regs.usp; } } LOCALPROCUSEDONCE DoCodeTas(void) { /* Tas 0100101011mmmrrr */ ui5r dstvalue; regs.opsize = 1; DecodeModeRegister(mode, reg); dstvalue = GetArgValue(); { ZFLG = (dstvalue == 0); NFLG = ui5r_MSBisSet(dstvalue); VFLG = CFLG = 0; dstvalue |= 0x80; } SetArgValue(dstvalue); } LOCALPROC DoCodeFdefault(void) { BackupPC(); Exception(0xB); } #if EmMMU LOCALPROCUSEDONCE DoCodeMMU(void) { /* Emulate enough of MMU for System 7.5.5 universal to boot on Mac Plus 68020. There is one spurious "PMOVE TC, (A0)". And implement a few more PMOVE operations seen when running Disk Copy 6.3.3 and MacsBug. */ if (regs.opcode == 0xF010) { ui4b ew = (int)nextiword(); if (ew == 0x4200) { /* PMOVE TC, (A0) */ /* fprintf(stderr, "0xF010 0x4200\n"); */ regs.opsize = 4; DecodeModeRegister(mode, reg); SetArgValue(0); return; } else if ((ew == 0x4E00) || (ew == 0x4A00)) { /* PMOVE CRP, (A0) and PMOVE SRP, (A0) */ /* fprintf(stderr, "0xF010 %x\n", ew); */ regs.opsize = 4; DecodeModeRegister(mode, reg); SetArgValue(0x7FFF0001); regs.ArgAddr.mem += 4; SetArgValue(0); return; } else if (ew == 0x6200) { /* PMOVE MMUSR, (A0) */ /* fprintf(stderr, "0xF010 %x\n", ew); */ regs.opsize = 2; DecodeModeRegister(mode, reg); SetArgValue(0); return; } /* fprintf(stderr, "extensions %x\n", ew); */ BackupPC(); } /* fprintf(stderr, "opcode %x\n", (int)regs.opcode); */ ReportAbnormal("MMU op"); DoCodeFdefault(); } #endif #if EmFPU #if 0 #include "FPMATHNT.h" #else #include "FPMATHEM.h" #endif #include "FPCPEMDV.h" #endif LOCALPROCUSEDONCE DoCodeF(void) { /* ReportAbnormal("DoCodeF"); */ #if EmMMU if (0 == rg9) { DoCodeMMU(); } else #endif #if EmFPU if (1 == rg9) { DoCodeFPU(); } else #endif { DoCodeFdefault(); } } LOCALPROCUSEDONCE DoCodeCallMorRtm(void) { /* CALLM or RTM 0000011011mmmrrr */ ReportAbnormal("CALLM or RTM instruction"); } LOCALPROC m68k_setstopped(void) { /* not implemented. doesn't seemed to be used on Mac Plus */ Exception(4); /* fake an illegal instruction */ } LOCALPROCUSEDONCE DoCodeStop(void) { /* Stop 0100111001110010 */ if (! regs.s) { DoPrivilegeViolation(); } else { m68k_setSR(nextiword()); m68k_setstopped(); } } LOCALPROCUSEDONCE DoCodeReset(void) { /* Reset 0100111001100000 */ if (! regs.s) { DoPrivilegeViolation(); } else { customreset(); } } #if Use68020 LOCALPROCUSEDONCE DoCodeEXTBL(void) { /* EXTB.L */ ui5r srcreg = reg; ui5r src = m68k_dreg(srcreg); ui5r dst = ui5r_FromSByte(src); VFLG = CFLG = 0; ZFLG = (dst == 0); NFLG = ui5r_MSBisSet(dst); m68k_dreg(srcreg) = dst; } #endif #if Use68020 LOCALPROC DoCHK2orCMP2(void) { /* CHK2 or CMP2 00000ss011mmmrrr */ ui5r regv; ui5r lower; ui5r upper; ui5r extra = nextiword(); /* ReportAbnormal("CHK2 or CMP2 instruction"); */ switch ((regs.opcode >> 9) & 3) { case 0: regs.opsize = 1; break; case 1: regs.opsize = 2; break; case 2: regs.opsize = 4; break; default: ReportAbnormal("illegal opsize in CHK2 or CMP2"); break; } if ((extra & 0x8000) == 0) { DecodeModeRegister(0, (extra >> 12) & 0x07); regv = GetArgValue(); } else { regv = ui5r_FromSLong(m68k_areg((extra >> 12) & 0x07)); } DecodeModeRegister(mode, reg); /* regs.ArgKind == AKMemory, otherwise illegal and don't get here */ lower = GetArgValue(); regs.ArgAddr.mem += regs.opsize; upper = GetArgValue(); ZFLG = (upper == regv) || (lower == regv); CFLG = (((si5r)lower) <= ((si5r)upper)) ? (((si5r)regv) < ((si5r)lower) || ((si5r)regv) > ((si5r)upper)) : (((si5r)regv) > ((si5r)upper) || ((si5r)regv) < ((si5r)lower)); if ((extra & 0x800) && CFLG) { Exception(6); } } #endif #if Use68020 LOCALPROC DoCAS(void) { /* CAS 00001ss011mmmrrr */ ui5r srcvalue; ui5r dstvalue; ui4b src = nextiword(); int ru = (src >> 6) & 7; int rc = src & 7; ReportAbnormal("CAS instruction"); switch ((regs.opcode >> 9) & 3) { case 1 : regs.opsize = 1; break; case 2 : regs.opsize = 2; break; case 3 : regs.opsize = 4; break; } DecodeModeRegister(0, rc); srcvalue = GetArgValue(); DecodeModeRegister(mode, reg); dstvalue = GetArgValue(); { int flgs = ((si5b)srcvalue) < 0; int flgo = ((si5b)dstvalue) < 0; ui5r newv = dstvalue - srcvalue; if (regs.opsize == 1) { newv = ui5r_FromSByte(newv); } else if (regs.opsize == 2) { newv = ui5r_FromSWord(newv); } else { newv = ui5r_FromSLong(newv); } ZFLG = (((si5b)newv) == 0); NFLG = (((si5b)newv) < 0); VFLG = (flgs != flgo) && (NFLG != flgo); CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); if (ZFLG) { SetArgValue(m68k_dreg(ru)); } else { DecodeModeRegister(0, rc); SetArgValue(dstvalue); } } } #endif #if Use68020 LOCALPROC DoCAS2(void) { /* CAS2 00001ss011111100 */ ui5b extra = nextilong(); int dc2 = extra & 7; int du2 = (extra >> 6) & 7; int dc1 = (extra >> 16) & 7; int du1 = (extra >> 22) & 7; CPTR rn1 = regs.regs[(extra >> 28) & 0x0F]; CPTR rn2 = regs.regs[(extra >> 12) & 0x0F]; si5b src = m68k_dreg(dc1); si5r dst1; si5r dst2; ReportAbnormal("DoCAS2 instruction"); switch ((regs.opcode >> 9) & 3) { case 1 : op_illg(); return; break; case 2 : regs.opsize = 2; break; case 3 : regs.opsize = 4; break; } if (regs.opsize == 2) { dst1 = get_word(rn1); dst2 = get_word(rn2); src = (si5b)(si4b)src; } else { dst1 = get_long(rn1); dst2 = get_long(rn2); } { int flgs = src < 0; int flgo = dst1 < 0; si5b newv = dst1 - src; if (regs.opsize == 2) { newv = (ui4b)newv; } ZFLG = (newv == 0); NFLG = (newv < 0); VFLG = (flgs != flgo) && (NFLG != flgo); CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); if (ZFLG) { src = m68k_dreg(dc2); if (regs.opsize == 2) { src = (si5b)(si4b)src; } flgs = src < 0; flgo = dst2 < 0; newv = dst2 - src; if (regs.opsize == 2) { newv = (ui4b)newv; } ZFLG = (newv == 0); NFLG = (newv < 0); VFLG = (flgs != flgo) && (NFLG != flgo); CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); if (ZFLG) { if (regs.opsize == 2) { put_word(rn1, m68k_dreg(du1)); put_word(rn2, m68k_dreg(du2)); } else { put_word(rn1, m68k_dreg(du1)); put_word(rn2, m68k_dreg(du2)); } } } } if (! ZFLG) { if (regs.opsize == 2) { m68k_dreg(du1) = (m68k_dreg(du1) & ~ 0xffff) | ((ui5b)dst1 & 0xffff); m68k_dreg(du2) = (m68k_dreg(du2) & ~ 0xffff) | ((ui5b)dst2 & 0xffff); } else { m68k_dreg(du1) = dst1; m68k_dreg(du2) = dst2; } } } #endif #if Use68020 LOCALPROC DoMOVES(void) { /* MoveS 00001110ssmmmrrr */ ReportAbnormal("MoveS instruction"); if (! regs.s) { DoPrivilegeViolation(); } else { ui4b extra = nextiword(); FindOpSizeFromb76(); DecodeModeRegister(mode, reg); if (extra & 0x0800) { ui5b src = regs.regs[(extra >> 12) & 0x0F]; SetArgValue(src); } else { ui5b rr = (extra >> 12) & 7; si5b srcvalue = GetArgValue(); if (extra & 0x8000) { m68k_areg(rr) = srcvalue; } else { DecodeModeRegister(0, rr); SetArgValue(srcvalue); } } } } #endif #define ui5b_lo(x) ((x) & 0x0000FFFF) #define ui5b_hi(x) (((x) >> 16) & 0x0000FFFF) #if Use68020 struct ui6r0 { ui5b hi; ui5b lo; }; typedef struct ui6r0 ui6r0; #endif #if Use68020 LOCALPROC Ui6r_Negate(ui6r0 *v) { v->hi = ~ v->hi; v->lo = - v->lo; if (v->lo == 0) { v->hi++; } } #endif #if Use68020 LOCALFUNC blnr Ui6r_IsZero(ui6r0 *v) { return (v->hi == 0) && (v->lo == 0); } #endif #if Use68020 LOCALFUNC blnr Ui6r_IsNeg(ui6r0 *v) { return ((si5b)v->hi) < 0; } #endif #if Use68020 LOCALPROC mul_unsigned(ui5b src1, ui5b src2, ui6r0 *dst) { ui5b src1_lo = ui5b_lo(src1); ui5b src2_lo = ui5b_lo(src2); ui5b src1_hi = ui5b_hi(src1); ui5b src2_hi = ui5b_hi(src2); ui5b r0 = src1_lo * src2_lo; ui5b r1 = src1_hi * src2_lo; ui5b r2 = src1_lo * src2_hi; ui5b r3 = src1_hi * src2_hi; ui5b ra1 = ui5b_hi(r0) + ui5b_lo(r1) + ui5b_lo(r2); dst->lo = (ui5b_lo(ra1) << 16) | ui5b_lo(r0); dst->hi = ui5b_hi(ra1) + ui5b_hi(r1) + ui5b_hi(r2) + r3; } #endif #if Use68020 LOCALFUNC blnr div_unsigned(ui6r0 *src, ui5b div, ui5b *quot, ui5b *rem) { int i; ui5b q = 0; ui5b cbit = 0; ui5b src_hi = src->hi; ui5b src_lo = src->lo; if (div <= src_hi) { return trueblnr; } for (i = 0 ; i < 32 ; i++) { cbit = src_hi & 0x80000000ul; src_hi <<= 1; if (src_lo & 0x80000000ul) { src_hi++; } src_lo <<= 1; q = q << 1; if (cbit || div <= src_hi) { q |= 1; src_hi -= div; } } *quot = q; *rem = src_hi; return falseblnr; } #endif #if Use68020 LOCALPROC DoMulL(void) { ui6r0 dst; ui5r srcvalue; ui4b extra = nextiword(); ui5b r2 = (extra >> 12) & 7; ui5b dstvalue = m68k_dreg(r2); DecodeModeRegister(mode, reg); srcvalue = GetArgValue(); if (extra & 0x800) { /* MULS.L - signed */ si5b src1 = (si5b)srcvalue; si5b src2 = (si5b)dstvalue; flagtype s1 = src1 < 0; flagtype s2 = src2 < 0; flagtype sr = s1 != s2; /* ReportAbnormal("MULS.L"); */ /* used by Sys 7.5.5 boot extensions */ if (s1) { src1 = - src1; } if (s2) { src2 = - src2; } mul_unsigned((ui5b)src1, (ui5b)src2, &dst); if (sr) { Ui6r_Negate(&dst); } VFLG = CFLG = 0; ZFLG = Ui6r_IsZero(&dst); NFLG = Ui6r_IsNeg(&dst); if (extra & 0x400) { m68k_dreg(extra & 7) = dst.hi; } else { if ((dst.lo & 0x80000000) != 0) { if ((dst.hi & 0xffffffff) != 0xffffffff) { VFLG = 1; } } else { if (dst.hi != 0) { VFLG = 1; } } } } else { /* MULU.L - unsigned */ /* ReportAbnormal("MULU.U"); */ /* Used by various Apps */ mul_unsigned(srcvalue, dstvalue, &dst); VFLG = CFLG = 0; ZFLG = Ui6r_IsZero(&dst); NFLG = Ui6r_IsNeg(&dst); if (extra & 0x400) { m68k_dreg(extra & 7) = dst.hi; } else { if (dst.hi != 0) { VFLG = 1; } } } m68k_dreg(r2) = dst.lo; } #endif #if Use68020 LOCALPROC DoDivL(void) { ui6r0 v2; ui5b src; ui5b quot; ui5b rem; ui4b extra = nextiword(); ui5b rDr = extra & 7; ui5b rDq = (extra >> 12) & 7; DecodeModeRegister(mode, reg); src = (ui5b)(si5b)GetArgValue(); if (src == 0) { Exception(5); #if m68k_logExceptions dbglog_StartLine(); dbglog_writeCStr("*** zero devide exception"); dbglog_writeReturn(); #endif return; } if (0 != (extra & 0x0800)) { /* signed variant */ flagtype sr; flagtype s2; flagtype s1 = ((si5b)src < 0); v2.lo = (si5b)m68k_dreg(rDq); if (extra & 0x0400) { v2.hi = (si5b)m68k_dreg(rDr); } else { v2.hi = ((si5b)v2.lo) < 0 ? -1 : 0; } s2 = Ui6r_IsNeg(&v2); sr = (s1 != s2); if (s2) { Ui6r_Negate(&v2); } if (s1) { src = - src; } if (div_unsigned(&v2, src, ", &rem) || (sr ? quot > 0x80000000 : quot > 0x7fffffff)) { VFLG = NFLG = 1; CFLG = 0; } else { if (sr) { quot = - quot; } if (((si5b)rem < 0) != s2) { rem = - rem; } VFLG = CFLG = 0; ZFLG = ((si5b)quot) == 0; NFLG = ((si5b)quot) < 0; m68k_dreg(rDr) = rem; m68k_dreg(rDq) = quot; } } else { /* unsigned */ v2.lo = (ui5b)m68k_dreg(rDq); if (extra & 0x400) { v2.hi = (ui5b)m68k_dreg(rDr); } else { v2.hi = 0; } if (div_unsigned(&v2, src, ", &rem)) { VFLG = NFLG = 1; CFLG = 0; } else { VFLG = CFLG = 0; ZFLG = ((si5b)quot) == 0; NFLG = ((si5b)quot) < 0; m68k_dreg(rDr) = rem; m68k_dreg(rDq) = quot; } } } #endif #if Use68020 LOCALPROC DoMoveToControl(void) { if (! regs.s) { DoPrivilegeViolation(); } else { ui4b src = nextiword(); int regno = (src >> 12) & 0x0F; ui5b v = regs.regs[regno]; switch (src & 0x0FFF) { case 0x0000: regs.sfc = v & 7; /* ReportAbnormal("DoMoveToControl: sfc"); */ /* happens on entering macsbug */ break; case 0x0001: regs.dfc = v & 7; /* ReportAbnormal("DoMoveToControl: dfc"); */ break; case 0x0002: regs.cacr = v & 0x3; /* ReportAbnormal("DoMoveToControl: cacr"); */ /* used by Sys 7.5.5 boot */ break; case 0x0800: regs.usp = v; ReportAbnormal("DoMoveToControl: usp"); break; case 0x0801: regs.vbr = v; /* ReportAbnormal("DoMoveToControl: vbr"); */ /* happens on entering macsbug */ break; case 0x0802: regs.caar = v &0xfc; /* ReportAbnormal("DoMoveToControl: caar"); */ /* happens on entering macsbug */ break; case 0x0803: regs.msp = v; if (regs.m == 1) { m68k_areg(7) = regs.msp; } /* ReportAbnormal("DoMoveToControl: msp"); */ /* happens on entering macsbug */ break; case 0x0804: regs.isp = v; if (regs.m == 0) { m68k_areg(7) = regs.isp; } ReportAbnormal("DoMoveToControl: isp"); break; default: op_illg(); ReportAbnormal("DoMoveToControl: unknown reg"); break; } } } #endif #if Use68020 LOCALPROC DoMoveFromControl(void) { if (! regs.s) { DoPrivilegeViolation(); } else { ui5b v; ui4b src = nextiword(); int regno = (src >> 12) & 0x0F; switch (src & 0x0FFF) { case 0x0000: v = regs.sfc; /* ReportAbnormal("DoMoveFromControl: sfc"); */ /* happens on entering macsbug */ break; case 0x0001: v = regs.dfc; /* ReportAbnormal("DoMoveFromControl: dfc"); */ /* happens on entering macsbug */ break; case 0x0002: v = regs.cacr; /* ReportAbnormal("DoMoveFromControl: cacr"); */ /* used by Sys 7.5.5 boot */ break; case 0x0800: v = regs.usp; ReportAbnormal("DoMoveFromControl: usp"); break; case 0x0801: v = regs.vbr; /* ReportAbnormal("DoMoveFromControl: vbr"); */ /* happens on entering macsbug */ break; case 0x0802: v = regs.caar; /* ReportAbnormal("DoMoveFromControl: caar"); */ /* happens on entering macsbug */ break; case 0x0803: v = (regs.m == 1) ? m68k_areg(7) : regs.msp; /* ReportAbnormal("DoMoveFromControl: msp"); */ /* happens on entering macsbug */ break; case 0x0804: v = (regs.m == 0) ? m68k_areg(7) : regs.isp; ReportAbnormal("DoMoveFromControl: isp"); break; default: v = 0; ReportAbnormal("DoMoveFromControl: unknown reg"); op_illg(); break; } regs.regs[regno] = v; } } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeMoveC(void) { /* MOVEC 010011100111101m */ /* ReportAbnormal("MOVEC"); */ switch (reg) { case 2: DoMoveFromControl(); break; case 3: DoMoveToControl(); break; default: op_illg(); break; } } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeChkL(void) { /* Chk.L 0100ddd100mmmrrr */ ReportAbnormal("CHK.L instruction"); regs.opsize = 4; DoCheck(); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeBkpt(void) { /* BKPT 0100100001001rrr */ ReportAbnormal("BKPT instruction"); op_illg(); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeDivL(void) { regs.opsize = 4; /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ /* ReportAbnormal("DIVS/DIVU long"); */ DoDivL(); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeMulL(void) { regs.opsize = 4; /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ DoMulL(); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeRtd(void) { /* Rtd 0100111001110100 */ ui5r NewPC = get_long(m68k_areg(7)); si5b offs = (si5b)(si4b)nextiword(); /* ReportAbnormal("RTD"); */ /* used by Sys 7.5.5 boot */ m68k_areg(7) += (4 + offs); m68k_setpc(NewPC); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeLinkL(void) { /* Link.L 0100100000001rrr */ ui5b srcreg = reg; CPTR stackp = m68k_areg(7); ReportAbnormal("Link.L"); stackp -= 4; m68k_areg(7) = stackp; /* only matters if srcreg == 7 */ put_long(stackp, m68k_areg(srcreg)); m68k_areg(srcreg) = stackp; m68k_areg(7) += (si5b)nextilong(); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeTRAPcc(void) { /* TRAPcc 0101cccc11111sss */ /* ReportAbnormal("TRAPcc"); */ switch (reg) { case 2: ReportAbnormal("TRAPcc word data"); (void) nextiword(); break; case 3: ReportAbnormal("TRAPcc long data"); (void) nextilong(); break; case 4: /* no optional data */ break; default: ReportAbnormal("TRAPcc illegal format"); op_illg(); break; } if (cctrue()) { ReportAbnormal("TRAPcc trapping"); Exception(7); /* pc pushed onto stack wrong */ } } #endif #if Use68020 LOCALPROC DoUNPK(void) { ui5r val; ui5r m1 = ((regs.opcode >> 3) & 1) << 2; ui5r srcreg = reg; ui5r dstreg = rg9; ui5r offs = ui5r_FromSWord(nextiword()); regs.opsize = 1; DecodeModeRegister(m1, srcreg); val = GetArgValue(); val = (((val & 0xF0) << 4) | (val & 0x0F)) + offs; regs.opsize = 2; DecodeModeRegister(m1, dstreg); SetArgValue(val); } #endif #if Use68020 LOCALPROC DoPACK(void) { ui5r val; ui5r m1 = ((regs.opcode >> 3) & 1) << 2; ui5r srcreg = reg; ui5r dstreg = rg9; ui5r offs = ui5r_FromSWord(nextiword()); regs.opsize = 2; DecodeModeRegister(m1, srcreg); val = GetArgValue(); val += offs; val = ((val >> 4) & 0xf0) | (val & 0xf); regs.opsize = 1; DecodeModeRegister(m1, dstreg); SetArgValue(val); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodePack(void) { ReportAbnormal("PACK"); DoPACK(); } #endif #if Use68020 LOCALPROCUSEDONCE DoCodeUnpk(void) { ReportAbnormal("UNPK"); DoUNPK(); } #endif #if Use68020 LOCALPROC DoBitField(void) { ui5b tmp; ui5b newtmp; si5b dsta; ui5b bf0; ui3b bf1; ui5b dstreg = regs.opcode & 7; ui4b extra = nextiword(); si5b offset = ((extra & 0x0800) != 0) ? m68k_dreg((extra >> 6) & 7) : ((extra >> 6) & 0x1f); ui5b width = ((extra & 0x0020) != 0) ? m68k_dreg(extra & 7) : extra; ui3b bfa[5]; ui5b offwid; /* ReportAbnormal("Bit Field operator"); */ /* width = ((width - 1) & 0x1f) + 1; */ /* 0 -> 32 */ width &= 0x001F; /* except width == 0 really means 32 */ if (mode == 0) { bf0 = m68k_dreg(dstreg); offset &= 0x1f; tmp = bf0; if (0 != offset) { tmp = (tmp << offset) | (tmp >> (32 - offset)); } } else { DecodeModeRegister(mode, reg); /* regs.ArgKind == AKMemory, otherwise illegal and don't get here */ dsta = regs.ArgAddr.mem; dsta += (offset >> 3) | (offset & 0x80000000 ? ~ 0x1fffffff : 0); offset &= 7; offwid = offset + ((width == 0) ? 32 : width); /* if (offwid > 0) */ { bf1 = get_byte(dsta); bfa[0] = bf1; tmp = ((ui5b)bf1) << (24 + offset); } if (offwid > 8) { bf1 = get_byte(dsta + 1); bfa[1] = bf1; tmp |= ((ui5b)bf1) << (16 + offset); } if (offwid > 16) { bf1 = get_byte(dsta + 2); bfa[2] = bf1; tmp |= ((ui5r)bf1) << (8 + offset); } if (offwid > 24) { bf1 = get_byte(dsta + 3); bfa[3] = bf1; tmp |= ((ui5r)bf1) << (offset); } if (offwid > 32) { bf1 = get_byte(dsta + 4); bfa[4] = bf1; tmp |= ((ui5r)bf1) >> (8 - offset); } } NFLG = ((si5b)tmp) < 0; if (width != 0) { tmp >>= (32 - width); } ZFLG = tmp == 0; VFLG = 0; CFLG = 0; newtmp = tmp; switch ((regs.opcode >> 8) & 7) { case 0: /* BFTST */ /* do nothing */ break; case 1: /* BFEXTU */ m68k_dreg((extra >> 12) & 7) = tmp; break; case 2: /* BFCHG */ newtmp = ~ newtmp; if (width != 0) { newtmp &= ((1 << width) - 1); } break; case 3: /* BFEXTS */ if (NFLG) { m68k_dreg((extra >> 12) & 7) = tmp | ((width == 0) ? 0 : (-1 << width)); } else { m68k_dreg((extra >> 12) & 7) = tmp; } break; case 4: /* BFCLR */ newtmp = 0; break; case 5: /* BFFFO */ { ui5b mask = 1 << ((width == 0) ? 31 : (width - 1)); si5b i = offset; while ((0 != mask) && (0 == (tmp & mask))) { mask >>= 1; i++; } m68k_dreg((extra >> 12) & 7) = i; } break; case 6: /* BFSET */ newtmp = (width == 0) ? ~ 0 : ((1 << width) - 1); break; case 7: /* BFINS */ newtmp = m68k_dreg((extra >> 12) & 7); if (width != 0) { newtmp &= ((1 << width) - 1); } break; } if (newtmp != tmp) { if (width != 0) { newtmp <<= (32 - width); } if (mode == 0) { ui5b mask = ~ 0; if (width != 0) { mask <<= (32 - width); } if (0 != offset) { newtmp = (newtmp >> offset) | (newtmp << (32 - offset)); mask = (mask >> offset) | (mask << (32 - offset)); } bf0 = (bf0 & ~ mask) | (newtmp); m68k_dreg(dstreg) = bf0; } else { /* if (offwid > 0) */ { ui3b mask = ~ (0xFF >> offset); bf1 = newtmp >> (24 + offset); if (offwid < 8) { mask |= (0xFF >> offwid); } if (mask != 0) { bf1 |= bfa[0] & mask; } put_byte(dsta + 0, bf1); } if (offwid > 8) { bf1 = newtmp >> (16 + offset); if (offwid < 16) { bf1 |= (bfa[1] & (0xFF >> (offwid - 8))); } put_byte(dsta + 1, bf1); } if (offwid > 16) { bf1 = newtmp >> (8 + offset); if (offwid < 24) { bf1 |= (bfa[2] & (0xFF >> (offwid - 16))); } put_byte(dsta + 2, bf1); } if (offwid > 24) { bf1 = newtmp >> (offset); if (offwid < 32) { bf1 |= (bfa[3] & (0xFF >> (offwid - 24))); } put_byte(dsta + 3, bf1); } if (offwid > 32) { bf1 = newtmp << (8 - offset); bf1 |= (bfa[4] & (0xFF >> (offwid - 32))); put_byte(dsta + 4, bf1); } } } } #endif #ifndef WantDumpTable #define WantDumpTable 0 #endif #if WantDumpTable LOCALVAR ui5b DumpTable[kNumIKinds]; LOCALPROC InitDumpTable(void) { si5b i; for (i = 0; i < kNumIKinds; ++i) { DumpTable[i] = 0; } } LOCALPROC DumpATable(ui5b *p, ui5b n) { si5b i; for (i = 0; i < n; ++i) { dbglog_writeNum(p[i]); dbglog_writeReturn(); } } EXPORTPROC DoDumpTable(void); GLOBALPROC DoDumpTable(void) { DumpATable(DumpTable, kNumIKinds); } #endif LOCALPROC m68k_go_MaxCycles(void) { /* Main loop of emulator. Always execute at least one instruction, even if regs.MaxInstructionsToGo == 0. Needed for trace flag to work. */ do { #if WantDisasm DisasmOneOrSave(m68k_getpc()); #endif regs.opcode = nextiword(); regs.CurDecOp = regs.disp_table[regs.opcode]; #if WantDumpTable DumpTable[GetDcoMainClas(®s.CurDecOp)] ++; #endif regs.MaxCyclesToGo -= GetDcoCycles(®s.CurDecOp); switch (GetDcoMainClas(®s.CurDecOp)) { case kIKindTst : DoCodeTst(); break; case kIKindCmpB : DoCodeCmpB(); break; case kIKindCmpW : DoCodeCmpW(); break; case kIKindCmpL : DoCodeCmpL(); break; case kIKindBccB : DoCodeBccB(); break; case kIKindBccW : DoCodeBccW(); break; #if Use68020 case kIKindBccL : DoCodeBccL(); break; #endif case kIKindBraB : DoCodeBraB(); break; case kIKindBraW : DoCodeBraW(); break; #if Use68020 case kIKindBraL : DoCodeBraL(); break; #endif case kIKindDBcc : DoCodeDBcc(); break; case kIKindDBF : DoCodeDBcc(); break; case kIKindSwap : DoCodeSwap(); break; case kIKindMoveL : DoCodeMove(); break; case kIKindMoveW : DoCodeMove(); break; case kIKindMoveB : DoCodeMove(); break; case kIKindMoveAL : DoCodeMoveA(); break; case kIKindMoveAW : DoCodeMoveA(); break; case kIKindMoveQ: DoCodeMoveQ(); break; case kIKindAddB : DoCodeAddB(); break; case kIKindAddW : DoCodeAddW(); break; case kIKindAddL : DoCodeAddL(); break; case kIKindSubB : DoCodeSubB(); break; case kIKindSubW : DoCodeSubW(); break; case kIKindSubL : DoCodeSubL(); break; case kIKindLea : DoCodeLea(); break; case kIKindPEA : DoCodePEA(); break; case kIKindA : DoCodeA(); break; case kIKindBsrB : DoCodeBsrB(); break; case kIKindBsrW : DoCodeBsrW(); break; #if Use68020 case kIKindBsrL : DoCodeBsrL(); break; #endif case kIKindJsr : DoCodeJsr(); break; case kIKindLinkA6 : DoCodeLinkA6(); break; case kIKindMOVEMRmML : DoCodeMOVEMRmML(); break; case kIKindMOVEMApRL : DoCodeMOVEMApRL(); break; case kIKindUnlkA6 : DoCodeUnlkA6(); break; case kIKindRts : DoCodeRts(); break; case kIKindJmp : DoCodeJmp(); break; case kIKindClr : DoCodeClr(); break; case kIKindAddA : DoCodeAddA(); break; case kIKindAddQA : DoCodeAddA(); /* DoCodeAddQA(); */ break; case kIKindSubA : DoCodeSubA(); break; case kIKindSubQA : DoCodeSubA(); /* DoCodeSubQA(); */ break; case kIKindCmpA : DoCodeCmpA(); break; case kIKindAddXB : DoCodeAddXB(); break; case kIKindAddXW : DoCodeAddXW(); break; case kIKindAddXL : DoCodeAddXL(); break; case kIKindSubXB : DoCodeSubXB(); break; case kIKindSubXW : DoCodeSubXW(); break; case kIKindSubXL : DoCodeSubXL(); break; case kIKindRolopNM : DoCodeRolopNM(); break; case kIKindRolopND : DoCodeRolopND(); break; case kIKindRolopDD : DoCodeRolopDD(); break; case kIKindBitOpDD : DoCodeBitOpDD(); break; case kIKindBitOpDM : DoCodeBitOpDM(); break; case kIKindBitOpND : DoCodeBitOpND(); break; case kIKindBitOpNM : DoCodeBitOpNM(); break; case kIKindAndI : DoCodeAnd(); /* DoCodeAndI(); */ break; case kIKindAndEaD : DoCodeAnd(); /* DoCodeAndEaD(); */ break; case kIKindAndDEa : DoCodeAnd(); /* DoCodeAndDEa(); */ break; case kIKindOrI : DoCodeOr(); break; case kIKindOrEaD : /* DoCodeOrEaD(); */ DoCodeOr(); break; case kIKindOrDEa : /* DoCodeOrDEa(); */ DoCodeOr(); break; case kIKindEor : DoCodeEor(); break; case kIKindEorI : DoCodeEor(); break; case kIKindNot : DoCodeNot(); break; case kIKindScc : DoCodeScc(); break; case kIKindEXTL : DoCodeEXTL(); break; case kIKindEXTW : DoCodeEXTW(); break; case kIKindNegB : DoCodeNegB(); break; case kIKindNegW : DoCodeNegW(); break; case kIKindNegL : DoCodeNegL(); break; case kIKindNegXB : DoCodeNegXB(); break; case kIKindNegXW : DoCodeNegXW(); break; case kIKindNegXL : DoCodeNegXL(); break; case kIKindMulU : DoCodeMulU(); break; case kIKindMulS : DoCodeMulS(); break; case kIKindDivU : DoCodeDivU(); break; case kIKindDivS : DoCodeDivS(); break; case kIKindExgdd : DoCodeExgdd(); break; case kIKindExgaa : DoCodeExgaa(); break; case kIKindExgda : DoCodeExgda(); break; case kIKindMoveCCREa : DoCodeMoveCCREa(); break; case kIKindMoveEaCCR : DoCodeMoveEaCR(); break; case kIKindMoveSREa : DoCodeMoveSREa(); break; case kIKindMoveEaSR : DoCodeMoveEaSR(); break; case kIKindBinOpStatusCCR : DoBinOpStatusCCR(); break; case kIKindMOVEMApRW : DoCodeMOVEMApRW(); break; case kIKindMOVEMRmMW : DoCodeMOVEMRmMW(); break; case kIKindMOVEMrm : DoCodeMOVEMrm(); break; case kIKindMOVEMmr : DoCodeMOVEMmr(); break; case kIKindAbcdr : DoCodeAbcdr(); break; case kIKindAbcdm : DoCodeAbcdm(); break; case kIKindSbcdr : DoCodeSbcdr(); break; case kIKindSbcdm : DoCodeSbcdm(); break; case kIKindNbcd : DoCodeNbcd(); break; case kIKindRte : DoCodeRte(); break; case kIKindNop : DoCodeNop(); break; case kIKindMoveP : DoCodeMoveP(); break; case kIKindIllegal : op_illg(); break; case kIKindChkW : DoCodeChkW(); break; case kIKindTrap : DoCodeTrap(); break; case kIKindTrapV : DoCodeTrapV(); break; case kIKindRtr : DoCodeRtr(); break; case kIKindLink : DoCodeLink(); break; case kIKindUnlk : DoCodeUnlk(); break; case kIKindMoveRUSP : DoCodeMoveRUSP(); break; case kIKindMoveUSPR : DoCodeMoveUSPR(); break; case kIKindTas : DoCodeTas(); break; case kIKindF : DoCodeF(); break; case kIKindCallMorRtm : DoCodeCallMorRtm(); break; case kIKindStop : DoCodeStop(); break; case kIKindReset : DoCodeReset(); break; #if Use68020 case kIKindEXTBL : DoCodeEXTBL(); break; case kIKindTRAPcc : DoCodeTRAPcc(); break; case kIKindChkL : DoCodeChkL(); break; case kIKindBkpt : DoCodeBkpt(); break; case kIKindDivL : DoCodeDivL(); break; case kIKindMulL : DoCodeMulL(); break; case kIKindRtd : DoCodeRtd(); break; case kIKindMoveC : DoCodeMoveC(); break; case kIKindLinkL : DoCodeLinkL(); break; case kIKindPack : DoCodePack(); break; case kIKindUnpk : DoCodeUnpk(); break; case kIKindCHK2orCMP2 : DoCHK2orCMP2(); break; case kIKindCAS2 : DoCAS2(); break; case kIKindCAS : DoCAS(); break; case kIKindMoveS : DoMOVES(); break; case kIKindBitField : DoBitField(); break; #endif } } while (regs.MaxCyclesToGo > 0); } GLOBALFUNC si5r GetCyclesRemaining(void) { return regs.MoreCyclesToGo + regs.MaxCyclesToGo; } GLOBALPROC SetCyclesRemaining(si5r n) { if (regs.MaxCyclesToGo >= n) { regs.MoreCyclesToGo = 0; regs.MaxCyclesToGo = n; } else { regs.MoreCyclesToGo = n - regs.MaxCyclesToGo; } } GLOBALFUNC ui3r get_vm_byte(CPTR addr) { return (ui3b) get_byte(addr); } GLOBALFUNC ui4r get_vm_word(CPTR addr) { return (ui4b) get_word(addr); } GLOBALFUNC ui5r get_vm_long(CPTR addr) { return (ui5b) get_long(addr); } GLOBALPROC put_vm_byte(CPTR addr, ui3r b) { put_byte(addr, ui5r_FromSByte(b)); } GLOBALPROC put_vm_word(CPTR addr, ui4r w) { put_word(addr, ui5r_FromSWord(w)); } GLOBALPROC put_vm_long(CPTR addr, ui5r l) { put_long(addr, ui5r_FromSLong(l)); } GLOBALPROC SetHeadATTel(ATTep p) { regs.MATCrdB.cmpmask = 0; regs.MATCrdB.cmpvalu = 0xFFFFFFFF; regs.MATCwrB.cmpmask = 0; regs.MATCwrB.cmpvalu = 0xFFFFFFFF; regs.MATCrdW.cmpmask = 0; regs.MATCrdW.cmpvalu = 0xFFFFFFFF; regs.MATCwrW.cmpmask = 0; regs.MATCwrW.cmpvalu = 0xFFFFFFFF; regs.MATCex.cmpmask = 0; regs.MATCex.cmpvalu = 0xFFFFFFFF; regs.HeadATTel = p; } LOCALPROC do_trace(void) { regs.TracePending = trueblnr; NeedToGetOut(); } GLOBALPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data) { ExceptionTo(newpc #if Use68020 , 0 #endif ); m68k_areg(7) -= 4; put_long(m68k_areg(7), data); } LOCALPROC DoCheckExternalInterruptPending(void) { ui3r level = *regs.fIPL; if ((level > regs.intmask) || (level == 7)) { #if WantCloserCyc regs.MaxCyclesToGo -= (44 * kCycleScale + 5 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(24 + level); regs.intmask = level; } } GLOBALPROC m68k_IPLchangeNtfy(void) { ui3r level = *regs.fIPL; if ((level > regs.intmask) || (level == 7)) { SetExternalInterruptPending(); } } #if WantDumpTable FORWARDPROC InitDumpTable(void); #endif GLOBALPROC m68k_reset(void) { #if WantDumpTable InitDumpTable(); #endif regs.MaxCyclesToGo = 0; regs.MoreCyclesToGo = 0; regs.ResidualCycles = 0; do_put_mem_word(regs.fakeword, 0x4AFC); /* illegal instruction opcode */ #if 0 regs.ResetPending = trueblnr; NeedToGetOut(); #else /* Sets the MC68000 reset jump vector... */ m68k_setpc(get_long(0x00000004)); /* Sets the initial stack vector... */ m68k_areg(7) = get_long(0x00000000); regs.s = 1; #if Use68020 regs.m = 0; regs.t0 = 0; #endif regs.t1 = 0; ZFLG = CFLG = NFLG = VFLG = 0; regs.ExternalInterruptPending = falseblnr; regs.TracePending = falseblnr; regs.intmask = 7; #if Use68020 regs.sfc = 0; regs.dfc = 0; regs.vbr = 0; regs.cacr = 0; regs.caar = 0; #endif #endif } #if SmallGlobals GLOBALPROC MINEM68K_ReserveAlloc(void) { ReserveAllocOneBlock((ui3p *)®s.disp_table, disp_table_sz * 8, 6, falseblnr); } #endif GLOBALPROC MINEM68K_Init( ui3b *fIPL) { regs.fIPL = fIPL; M68KITAB_setup(regs.disp_table); } GLOBALPROC m68k_go_nCycles(ui5b n) { regs.MaxCyclesToGo += (n + regs.ResidualCycles); while (regs.MaxCyclesToGo > 0) { #if 0 if (regs.ResetPending) { m68k_DoReset(); } #endif if (regs.TracePending) { #if WantCloserCyc regs.MaxCyclesToGo -= (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(9); } if (regs.ExternalInterruptPending) { regs.ExternalInterruptPending = falseblnr; DoCheckExternalInterruptPending(); } if (regs.t1) { do_trace(); } m68k_go_MaxCycles(); regs.MaxCyclesToGo += regs.MoreCyclesToGo; regs.MoreCyclesToGo = 0; } regs.ResidualCycles = regs.MaxCyclesToGo; regs.MaxCyclesToGo = 0; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MINEM68K.h b/Mini vMac/mnvm_core/MINEM68K.h new file mode 100755 index 0000000..47250ac --- /dev/null +++ b/Mini vMac/mnvm_core/MINEM68K.h @@ -0,0 +1 @@ +/* MINEM68K.h Copyright (C) 2004 Bernd Schmidt, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef MINEM68K_H #error "header already included" #else #define MINEM68K_H #endif EXPORTPROC MINEM68K_Init( ui3b *fIPL); #if SmallGlobals EXPORTPROC MINEM68K_ReserveAlloc(void); #endif EXPORTPROC m68k_IPLchangeNtfy(void); EXPORTPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data); EXPORTPROC m68k_reset(void); EXPORTFUNC si5r GetCyclesRemaining(void); EXPORTPROC SetCyclesRemaining(si5r n); EXPORTPROC m68k_go_nCycles(ui5b n); /* general purpose access of address space of emulated computer. (memory and memory mapped hardware.) */ EXPORTFUNC ui3r get_vm_byte(CPTR addr); EXPORTFUNC ui4r get_vm_word(CPTR addr); EXPORTFUNC ui5r get_vm_long(CPTR addr); EXPORTPROC put_vm_byte(CPTR addr, ui3r b); EXPORTPROC put_vm_word(CPTR addr, ui4r w); EXPORTPROC put_vm_long(CPTR addr, ui5r l); EXPORTPROC SetHeadATTel(ATTep p); EXPORTFUNC ATTep FindATTel(CPTR addr); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MOUSEMDV.c b/Mini vMac/mnvm_core/MOUSEMDV.c new file mode 100755 index 0000000..7737d0a --- /dev/null +++ b/Mini vMac/mnvm_core/MOUSEMDV.c @@ -0,0 +1 @@ +/* MOUSEMDV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* MOUSe EMulated DeVice Emulation of the mouse in the Mac Plus. This code descended from "Mouse-MacOS.c" in Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "SCCEMDEV.h" #endif #include "MOUSEMDV.h" GLOBALPROC Mouse_Update(void) { #if HaveMasterMyEvtQLock if (0 != MasterMyEvtQLock) { --MasterMyEvtQLock; } #endif /* Check mouse position first. After mouse button or key event, can't process another mouse position until following tick, otherwise button or key will be in wrong place. */ /* if start doing this too soon after boot, will mess up memory check */ if (Mouse_Enabled()) { MyEvtQEl *p; if ( #if HaveMasterMyEvtQLock (0 == MasterMyEvtQLock) && #endif (nullpr != (p = MyEvtQOutP()))) { #if EmClassicKbrd #if EnableMouseMotion if (MyEvtQElKindMouseDelta == p->kind) { if ((p->u.pos.h != 0) || (p->u.pos.v != 0)) { put_ram_word(0x0828, get_ram_word(0x0828) + p->u.pos.v); put_ram_word(0x082A, get_ram_word(0x082A) + p->u.pos.h); put_ram_byte(0x08CE, get_ram_byte(0x08CF)); /* Tell MacOS to redraw the Mouse */ } MyEvtQOutDone(); } else #endif #endif if (MyEvtQElKindMousePos == p->kind) { ui5r NewMouse = (p->u.pos.v << 16) | p->u.pos.h; if (get_ram_long(0x0828) != NewMouse) { put_ram_long(0x0828, NewMouse); /* Set Mouse Position */ put_ram_long(0x082C, NewMouse); #if EmClassicKbrd put_ram_byte(0x08CE, get_ram_byte(0x08CF)); /* Tell MacOS to redraw the Mouse */ #else put_ram_long(0x0830, NewMouse); put_ram_byte(0x08CE, 0xFF); /* Tell MacOS to redraw the Mouse */ #endif } MyEvtQOutDone(); } } } #if EmClassicKbrd { MyEvtQEl *p; if ( #if HaveMasterMyEvtQLock (0 == MasterMyEvtQLock) && #endif (nullpr != (p = MyEvtQOutP()))) { if (MyEvtQElKindMouseButton == p->kind) { MouseBtnUp = p->u.press.down ? 0 : 1; MyEvtQOutDone(); MasterMyEvtQLock = 4; } } } #endif } GLOBALPROC Mouse_EndTickNotify(void) { if (Mouse_Enabled()) { /* tell platform specific code where the mouse went */ CurMouseV = get_ram_word(0x082C); CurMouseH = get_ram_word(0x082E); } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MOUSEMDV.h b/Mini vMac/mnvm_core/MOUSEMDV.h new file mode 100755 index 0000000..95c3d90 --- /dev/null +++ b/Mini vMac/mnvm_core/MOUSEMDV.h @@ -0,0 +1 @@ +/* MOUSEMDV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef MOUSEMDV_H #error "header already included" #else #define MOUSEMDV_H #endif EXPORTPROC Mouse_Update(void); EXPORTPROC Mouse_EndTickNotify(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MYOSGLUE.h b/Mini vMac/mnvm_core/MYOSGLUE.h new file mode 100755 index 0000000..25e16b2 --- /dev/null +++ b/Mini vMac/mnvm_core/MYOSGLUE.h @@ -0,0 +1 @@ +/* MYOSGLUE.h Copyright (C) 2006 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* MY Operating System GLUE. header file for operating system dependent code. the same header is used for all platforms. This code is descended from Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. */ #ifdef MYOSGLUE_H #ifndef AllFiles #error "header already included" #endif #else #define MYOSGLUE_H #endif EXPORTPROC WarnMsgCorruptedROM(void); EXPORTPROC WarnMsgUnsupportedROM(void); EXPORTPROC WarnMsgAbnormal(void); #if dbglog_HAVE EXPORTPROC dbglog_writeCStr(char *s); EXPORTPROC dbglog_writeReturn(void); EXPORTPROC dbglog_writeHex(ui5r x); EXPORTPROC dbglog_writeNum(ui5r x); EXPORTPROC dbglog_writeMacChar(ui3r x); EXPORTPROC dbglog_writeln(char *s); EXPORTPROC dbglog_writelnNum(char *s, simr v); #endif EXPORTPROC ReserveAllocOneBlock(ui3p *p, uimr n, ui3r align, blnr FillOnes); EXPORTPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount); EXPORTVAR(ui3p, ROM) /* error codes returned by Mini vMac extensions (passed back to the emulated 68k code). */ #define tMacErr ui4r #define mnvm_noErr ((tMacErr) 0x0000) /* (ui4b) 0 - No Error */ #define mnvm_miscErr ((tMacErr) 0xFFFF) /* (ui4b) - 1 - Should probably replace these */ #define mnvm_controlErr ((tMacErr) 0xFFEF) /* (ui4b) - 17 - I/O System Errors */ #define mnvm_statusErr ((tMacErr) 0xFFEE) /* (ui4b) - 18 - Driver can't respond to Status call */ #define mnvm_closErr ((tMacErr) 0xFFE8) /* (ui4b) - 24 - I/O System Errors */ #define mnvm_eofErr ((tMacErr) 0xFFD9) /* (ui4b) - 39 - End of file */ #define mnvm_tmfoErr ((tMacErr) 0xFFD6) /* (ui4b) - 42 - too many files open */ #define mnvm_fnfErr ((tMacErr) 0xFFD5) /* (ui4b) - 43 - File not found */ #define mnvm_wPrErr ((tMacErr) 0xFFD4) /* (ui4b) - 44 - diskette is write protected */ #define mnvm_vLckdErr ((tMacErr) 0xFFD2) /* (ui4b) - 46 - volume is locked */ #define mnvm_dupFNErr ((tMacErr) 0xFFD0) /* (ui4b) - 48 - duplicate filename */ #define mnvm_opWrErr ((tMacErr) 0xFFCF) /* (ui4b) - 49 - file already open with with write permission */ #define mnvm_paramErr ((tMacErr) 0xFFCE) /* (ui4b) - 50 - error in parameter list */ #define mnvm_permErr ((tMacErr) 0xFFCA) /* (ui4b) - 54 - permissions error (on file open) */ #define mnvm_nsDrvErr ((tMacErr) 0xFFC8) /* (ui4b) - 56 - No Such Drive */ #define mnvm_wrPermErr ((tMacErr) 0xFFC3) /* (ui4b) - 61 - write permissions error */ #define mnvm_offLinErr ((tMacErr) 0xFFBF) /* (ui4b) - 65 - off-line drive */ #define mnvm_dirNFErr ((tMacErr) 0xFF88) /* (ui4b) - 120 - directory not found */ #define mnvm_afpAccessDenied ((tMacErr) 0xEC78) /* (ui4b) - 5000 - Insufficient access privileges for operation */ #if IncludePbufs #define tPbuf ui4r #define NotAPbuf ((tPbuf)0xFFFF) EXPORTFUNC tMacErr CheckPbuf(tPbuf Pbuf_No); EXPORTFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count); EXPORTFUNC tMacErr PbufNew(ui5b count, tPbuf *r); EXPORTPROC PbufDispose(tPbuf i); EXPORTPROC PbufTransfer(ui3p Buffer, tPbuf i, ui5r offset, ui5r count, blnr IsWrite); #endif #define tDrive ui4r EXPORTVAR(ui5b, vSonyWritableMask) EXPORTVAR(ui5b, vSonyInsertedMask) #define vSonyIsInserted(Drive_No) \ ((vSonyInsertedMask & ((ui5b)1 << (Drive_No))) != 0) EXPORTFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount); EXPORTFUNC tMacErr vSonyEject(tDrive Drive_No); EXPORTFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count); EXPORTFUNC blnr AnyDiskInserted(void); EXPORTPROC DiskRevokeWritable(tDrive Drive_No); #if IncludeSonyRawMode EXPORTVAR(blnr, vSonyRawMode) #endif #if IncludeSonyNew EXPORTVAR(blnr, vSonyNewDiskWanted) EXPORTVAR(ui5b, vSonyNewDiskSize) EXPORTFUNC tMacErr vSonyEjectDelete(tDrive Drive_No); #endif #if IncludeSonyNameNew EXPORTVAR(tPbuf, vSonyNewDiskName) #endif #if IncludeSonyGetName EXPORTFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r); #endif #if IncludeHostTextClipExchange EXPORTFUNC tMacErr HTCEexport(tPbuf i); EXPORTFUNC tMacErr HTCEimport(tPbuf *r); #endif EXPORTVAR(ui5b, OnTrueTime); EXPORTVAR(ui5b, CurMacDateInSeconds) EXPORTVAR(ui5b, CurMacLatitude) EXPORTVAR(ui5b, CurMacLongitude) EXPORTVAR(ui5b, CurMacDelta) /* (dlsDelta << 24) | (gmtDelta & 0x00FFFFFF) */ #define vMacScreenNumPixels \ ((long)vMacScreenHeight * (long)vMacScreenWidth) #define vMacScreenNumBits (vMacScreenNumPixels << vMacScreenDepth) #define vMacScreenNumBytes (vMacScreenNumBits / 8) #define vMacScreenBitWidth ((long)vMacScreenWidth << vMacScreenDepth) #define vMacScreenByteWidth (vMacScreenBitWidth / 8) #define vMacScreenMonoNumBytes (vMacScreenNumPixels / 8) #define vMacScreenMonoByteWidth ((long)vMacScreenWidth / 8) #if 0 != vMacScreenDepth EXPORTVAR(blnr, UseColorMode) EXPORTVAR(blnr, ColorModeWorks) #endif #if 0 != vMacScreenDepth EXPORTVAR(blnr, ColorMappingChanged) #endif #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) #define CLUT_size (1 << (1 << vMacScreenDepth)) EXPORTVAR(ui4r, CLUT_reds[CLUT_size]) EXPORTVAR(ui4r, CLUT_greens[CLUT_size]) EXPORTVAR(ui4r, CLUT_blues[CLUT_size]) #endif EXPORTVAR(blnr, EmVideoDisable); EXPORTVAR(si3b, EmLagTime); EXPORTPROC Screen_OutputFrame(ui3p screencurrentbuff); EXPORTPROC DoneWithDrawingForTick(void); EXPORTVAR(blnr, ForceMacOff) EXPORTVAR(blnr, WantMacInterrupt) EXPORTVAR(blnr, WantMacReset) EXPORTFUNC blnr ExtraTimeNotOver(void); EXPORTVAR(ui3b, SpeedValue) #if EnableAutoSlow EXPORTVAR(blnr, WantNotAutoSlow) #endif /* where emulated machine thinks mouse is */ EXPORTVAR(ui4b, CurMouseV) EXPORTVAR(ui4b, CurMouseH) #if EnableAutoSlow EXPORTVAR(ui5r, QuietTime) EXPORTVAR(ui5r, QuietSubTicks) #define QuietEnds() \ { \ QuietTime = 0; \ QuietSubTicks = 0; \ } #else #define QuietEnds() #endif #if 3 == kLn2SoundSampSz #define trSoundSamp ui3r #define tbSoundSamp ui3b #define tpSoundSamp ui3p #define kCenterSound 0x80 #elif 4 == kLn2SoundSampSz #define trSoundSamp ui4r #define tbSoundSamp ui4b #define tpSoundSamp ui4p #define kCenterSound 0x8000 #else #error "unsupported kLn2SoundSampSz" #endif #if MySoundEnabled EXPORTFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL); EXPORTPROC MySound_EndWrite(ui4r actL); /* 370 samples per tick = 22,254.54 per second */ #endif #if EmLocalTalk #define LT_TxBfMxSz 1024 EXPORTVAR(ui3p, LT_TxBuffer) EXPORTVAR(ui4r, LT_TxBuffSz) EXPORTPROC LT_TransmitPacket(void); EXPORTVAR(ui3p, LT_RxBuffer); EXPORTVAR(ui5r, LT_RxBuffSz); EXPORTPROC LT_ReceivePacket(void); #endif EXPORTPROC WaitForNextTick(void); #define MyEvtQElKindKey 0 #define MyEvtQElKindMouseButton 1 #define MyEvtQElKindMousePos 2 #define MyEvtQElKindMouseDelta 3 struct MyEvtQEl { /* expected size : 8 bytes */ ui3b kind; ui3b pad[3]; union { struct { ui3b down; ui3b key; } press; struct { ui4b h; ui4b v; } pos; } u; }; typedef struct MyEvtQEl MyEvtQEl; EXPORTFUNC MyEvtQEl * MyEvtQOutP(void); EXPORTPROC MyEvtQOutDone(void); #define MKC_A 0x00 #define MKC_B 0x0B #define MKC_C 0x08 #define MKC_D 0x02 #define MKC_E 0x0E #define MKC_F 0x03 #define MKC_G 0x05 #define MKC_H 0x04 #define MKC_I 0x22 #define MKC_J 0x26 #define MKC_K 0x28 #define MKC_L 0x25 #define MKC_M 0x2E #define MKC_N 0x2D #define MKC_O 0x1F #define MKC_P 0x23 #define MKC_Q 0x0C #define MKC_R 0x0F #define MKC_S 0x01 #define MKC_T 0x11 #define MKC_U 0x20 #define MKC_V 0x09 #define MKC_W 0x0D #define MKC_X 0x07 #define MKC_Y 0x10 #define MKC_Z 0x06 #define MKC_1 0x12 #define MKC_2 0x13 #define MKC_3 0x14 #define MKC_4 0x15 #define MKC_5 0x17 #define MKC_6 0x16 #define MKC_7 0x1A #define MKC_8 0x1C #define MKC_9 0x19 #define MKC_0 0x1D #define MKC_Command 0x37 #define MKC_Shift 0x38 #define MKC_CapsLock 0x39 #define MKC_Option 0x3A #define MKC_Space 0x31 #define MKC_Return 0x24 #define MKC_BackSpace 0x33 #define MKC_Tab 0x30 #define MKC_Left /* 0x46 */ 0x7B #define MKC_Right /* 0x42 */ 0x7C #define MKC_Down /* 0x48 */ 0x7D #define MKC_Up /* 0x4D */ 0x7E #define MKC_Minus 0x1B #define MKC_Equal 0x18 #define MKC_BackSlash 0x2A #define MKC_Comma 0x2B #define MKC_Period 0x2F #define MKC_Slash 0x2C #define MKC_SemiColon 0x29 #define MKC_SingleQuote 0x27 #define MKC_LeftBracket 0x21 #define MKC_RightBracket 0x1E #define MKC_Grave 0x32 #define MKC_Clear 0x47 #define MKC_KPEqual 0x51 #define MKC_KPDevide 0x4B #define MKC_KPMultiply 0x43 #define MKC_KPSubtract 0x4E #define MKC_KPAdd 0x45 #define MKC_Enter 0x4C #define MKC_KP1 0x53 #define MKC_KP2 0x54 #define MKC_KP3 0x55 #define MKC_KP4 0x56 #define MKC_KP5 0x57 #define MKC_KP6 0x58 #define MKC_KP7 0x59 #define MKC_KP8 0x5B #define MKC_KP9 0x5C #define MKC_KP0 0x52 #define MKC_Decimal 0x41 /* these aren't on the Mac Plus keyboard */ #define MKC_Control 0x3B #define MKC_Escape 0x35 #define MKC_F1 0x7a #define MKC_F2 0x78 #define MKC_F3 0x63 #define MKC_F4 0x76 #define MKC_F5 0x60 #define MKC_F6 0x61 #define MKC_F7 0x62 #define MKC_F8 0x64 #define MKC_F9 0x65 #define MKC_F10 0x6d #define MKC_F11 0x67 #define MKC_F12 0x6f #define MKC_Home 0x73 #define MKC_End 0x77 #define MKC_PageUp 0x74 #define MKC_PageDown 0x79 #define MKC_Help 0x72 /* = Insert */ #define MKC_ForwardDel 0x75 #define MKC_Print 0x69 #define MKC_ScrollLock 0x6B #define MKC_Pause 0x71 #define MKC_AngleBracket 0x0A /* found on german keyboard */ \ No newline at end of file diff --git a/Mini vMac/mnvm_core/PROGMAIN.c b/Mini vMac/mnvm_core/PROGMAIN.c new file mode 100755 index 0000000..4a6aaa0 --- /dev/null +++ b/Mini vMac/mnvm_core/PROGMAIN.c @@ -0,0 +1 @@ +/* PROGMAIN.c Copyright (C) 2009 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* PROGram MAIN. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #include "MINEM68K.h" #include "VIAEMDEV.h" #if EmVIA2 #include "VIA2EMDV.h" #endif #include "IWMEMDEV.h" #include "SCCEMDEV.h" #if EmRTC #include "RTCEMDEV.h" #endif #include "ROMEMDEV.h" #include "SCSIEMDV.h" #include "SONYEMDV.h" #include "SCRNEMDV.h" #if EmVidCard #include "VIDEMDEV.h" #endif #if EmClassicKbrd #include "KBRDEMDV.h" #elif EmPMU #include "PMUEMDEV.h" #else #include "ADBEMDEV.h" #endif #if EmASC #include "ASCEMDEV.h" #else #if MySoundEnabled && (CurEmMd != kEmMd_PB100) #include "SNDEMDEV.h" #endif #endif #include "MOUSEMDV.h" #endif #include "PROGMAIN.h" LOCALPROC EmulatedHardwareZap(void) { Memory_Reset(); ICT_Zap(); IWM_Reset(); SCC_Reset(); SCSI_Reset(); VIA1_Zap(); #if EmVIA2 VIA2_Zap(); #endif Sony_Reset(); Extn_Reset(); m68k_reset(); } LOCALPROC DoMacReset(void) { Sony_EjectAllDisks(); EmulatedHardwareZap(); } LOCALPROC InterruptReset_Update(void) { SetInterruptButton(falseblnr); /* in case has been set. so only stays set for 60th of a second. */ if (WantMacInterrupt) { SetInterruptButton(trueblnr); WantMacInterrupt = falseblnr; } if (WantMacReset) { DoMacReset(); WantMacReset = falseblnr; } } LOCALPROC SubTickNotify(int SubTick) { #if 0 dbglog_writeCStr("ending sub tick "); dbglog_writeNum(SubTick); dbglog_writeReturn(); #endif #if MySoundEnabled && (CurEmMd != kEmMd_PB100) MacSound_SubTick(SubTick); #else UnusedParam(SubTick); #endif } #define CyclesScaledPerTick (130240UL * kMyClockMult * kCycleScale) #define CyclesScaledPerSubTick (CyclesScaledPerTick / kNumSubTicks) LOCALVAR ui4r SubTickCounter; LOCALPROC SubTickTaskDo(void) { SubTickNotify(SubTickCounter); ++SubTickCounter; if (SubTickCounter < (kNumSubTicks - 1)) { /* final SubTick handled by SubTickTaskEnd, since CyclesScaledPerSubTick * kNumSubTicks might not equal CyclesScaledPerTick. */ ICT_add(kICT_SubTick, CyclesScaledPerSubTick); } } LOCALPROC SubTickTaskStart(void) { SubTickCounter = 0; ICT_add(kICT_SubTick, CyclesScaledPerSubTick); } LOCALPROC SubTickTaskEnd(void) { SubTickNotify(kNumSubTicks - 1); } LOCALPROC SixtiethSecondNotify(void) { #if dbglog_HAVE && 0 dbglog_StartLine(); dbglog_writeCStr("begin new Sixtieth"); dbglog_writeReturn(); #endif Mouse_Update(); InterruptReset_Update(); #if EmClassicKbrd KeyBoard_Update(); #endif #if EmADB ADB_Update(); #endif Sixtieth_PulseNtfy(); /* Vertical Blanking Interrupt */ Sony_Update(); #if EmLocalTalk LocalTalkTick(); #endif #if EmRTC RTC_Interrupt(); #endif #if EmVidCard Vid_Update(); #endif #if EmASC ASC_Update(); #endif SubTickTaskStart(); } LOCALPROC SixtiethEndNotify(void) { SubTickTaskEnd(); Mouse_EndTickNotify(); Screen_EndTickNotify(); #if dbglog_HAVE && 0 dbglog_StartLine(); dbglog_writeCStr("end Sixtieth"); dbglog_writeReturn(); #endif } LOCALPROC ExtraTimeBeginNotify(void) { #if 0 dbglog_writeCStr("begin extra time"); dbglog_writeReturn(); #endif VIA1_ExtraTimeBegin(); #if EmVIA2 VIA2_ExtraTimeBegin(); #endif } LOCALPROC ExtraTimeEndNotify(void) { VIA1_ExtraTimeEnd(); #if EmVIA2 VIA2_ExtraTimeEnd(); #endif #if 0 dbglog_writeCStr("end extra time"); dbglog_writeReturn(); #endif } GLOBALPROC EmulationReserveAlloc(void) { ReserveAllocOneBlock(&RAM, kRAM_Size + RAMSafetyMarginFudge, 5, falseblnr); #if EmVidCard ReserveAllocOneBlock(&VidROM, kVidROM_Size, 5, falseblnr); #endif #if IncludeVidMem ReserveAllocOneBlock(&VidMem, kVidMemRAM_Size + RAMSafetyMarginFudge, 5, trueblnr); #endif #if SmallGlobals MINEM68K_ReserveAlloc(); #endif } LOCALFUNC blnr InitEmulation(void) { #if EmRTC if (RTC_Init()) #endif if (ROM_Init()) #if EmVidCard if (Vid_Init()) #endif if (AddrSpac_Init()) { EmulatedHardwareZap(); return trueblnr; } return falseblnr; } LOCALPROC ICT_DoTask(int taskid) { switch (taskid) { case kICT_SubTick: SubTickTaskDo(); break; #if EmClassicKbrd case kICT_Kybd_ReceiveEndCommand: DoKybd_ReceiveEndCommand(); break; case kICT_Kybd_ReceiveCommand: DoKybd_ReceiveCommand(); break; #endif #if EmADB case kICT_ADB_NewState: ADB_DoNewState(); break; #endif #if EmPMU case kICT_PMU_Task: PMU_DoTask(); break; #endif case kICT_VIA1_Timer1Check: VIA1_DoTimer1Check(); break; case kICT_VIA1_Timer2Check: VIA1_DoTimer2Check(); break; #if EmVIA2 case kICT_VIA2_Timer1Check: VIA2_DoTimer1Check(); break; case kICT_VIA2_Timer2Check: VIA2_DoTimer2Check(); break; #endif default: ReportAbnormal("unknown taskid in ICT_DoTask"); break; } } LOCALPROC ICT_DoCurrentTasks(void) { int i = 0; uimr m = ICTactive; while (0 != m) { if (0 != (m & 1)) { if (i >= kNumICTs) { /* shouldn't happen */ ICTactive &= ((1 << kNumICTs) - 1); m = 0; } else if (ICTwhen[i] == NextiCount) { ICTactive &= ~ (1 << i); #ifdef _VIA_Debug fprintf(stderr, "doing task %d, %d\n", NextiCount, i); #endif ICT_DoTask(i); /* A Task may set the time of any task, including itself. But it cannot set any task to execute immediately, so one pass is sufficient. */ } } ++i; m >>= 1; } } LOCALFUNC ui5b ICT_DoGetNext(ui5b maxn) { int i = 0; uimr m = ICTactive; ui5b v = maxn; while (0 != m) { if (0 != (m & 1)) { if (i >= kNumICTs) { /* shouldn't happen */ m = 0; } else { ui5b d = ICTwhen[i] - NextiCount; /* at this point d must be > 0 */ if (d < v) { #ifdef _VIA_Debug fprintf(stderr, "coming task %d, %d, %d\n", NextiCount, i, d); #endif v = d; } } } ++i; m >>= 1; } return v; } LOCALPROC m68k_go_nCycles_1(ui5b n) { ui5b n2; ui5b StopiCount = NextiCount + n; do { ICT_DoCurrentTasks(); n2 = ICT_DoGetNext(n); #if dbglog_HAVE && 0 dbglog_StartLine(); dbglog_writeCStr("before m68k_go_nCycles, NextiCount:"); dbglog_writeHex(NextiCount); dbglog_writeCStr(", n2:"); dbglog_writeHex(n2); dbglog_writeCStr(", n:"); dbglog_writeHex(n); dbglog_writeReturn(); #endif NextiCount += n2; m68k_go_nCycles(n2); n = StopiCount - NextiCount; } while (n != 0); } LOCALVAR ui5b ExtraSubTicksToDo = 0; LOCALPROC DoEmulateOneTick(void) { #if EnableAutoSlow { ui5r NewQuietTime = QuietTime + 1; if (NewQuietTime > QuietTime) { /* if not overflow */ QuietTime = NewQuietTime; } } #endif #if EnableAutoSlow { ui5r NewQuietSubTicks = QuietSubTicks + kNumSubTicks; if (NewQuietSubTicks > QuietSubTicks) { /* if not overflow */ QuietSubTicks = NewQuietSubTicks; } } #endif SixtiethSecondNotify(); m68k_go_nCycles_1(CyclesScaledPerTick); SixtiethEndNotify(); if ((ui3b) -1 == SpeedValue) { ExtraSubTicksToDo = (ui5b) -1; } else { ui5b ExtraAdd = (kNumSubTicks << SpeedValue) - kNumSubTicks; ui5b ExtraLimit = ExtraAdd << 3; ExtraSubTicksToDo += ExtraAdd; if (ExtraSubTicksToDo > ExtraLimit) { ExtraSubTicksToDo = ExtraLimit; } } } LOCALFUNC blnr MoreSubTicksToDo(void) { blnr v = falseblnr; if (ExtraTimeNotOver() && (ExtraSubTicksToDo > 0)) { #if EnableAutoSlow if ((QuietSubTicks >= 16384) && (QuietTime >= 34) && ! WantNotAutoSlow) { ExtraSubTicksToDo = 0; } else #endif { v = trueblnr; } } return v; } LOCALPROC DoEmulateExtraTime(void) { /* DoEmulateExtraTime is used for anything over emulation speed of 1x. It periodically calls ExtraTimeNotOver and stops when this returns false (or it is finished with emulating the extra time). */ if (MoreSubTicksToDo()) { ExtraTimeBeginNotify(); do { #if EnableAutoSlow { ui5r NewQuietSubTicks = QuietSubTicks + 1; if (NewQuietSubTicks > QuietSubTicks) { /* if not overflow */ QuietSubTicks = NewQuietSubTicks; } } #endif m68k_go_nCycles_1(CyclesScaledPerSubTick); --ExtraSubTicksToDo; } while (MoreSubTicksToDo()); ExtraTimeEndNotify(); } } LOCALVAR ui5b CurEmulatedTime = 0; /* The number of ticks that have been emulated so far. That is, the number of times "DoEmulateOneTick" has been called. */ LOCALPROC RunEmulatedTicksToTrueTime(void) { /* The general idea is to call DoEmulateOneTick once per tick. But if emulation is lagging, we'll try to catch up by calling DoEmulateOneTick multiple times, unless we're too far behind, in which case we forget it. If emulating one tick takes longer than a tick we don't want to sit here forever. So the maximum number of calls to DoEmulateOneTick is determined at the beginning, rather than just calling DoEmulateOneTick until CurEmulatedTime >= TrueEmulatedTime. */ si3b n = OnTrueTime - CurEmulatedTime; if (n > 0) { DoEmulateOneTick(); ++CurEmulatedTime; DoneWithDrawingForTick(); if (n > 8) { /* emulation not fast enough */ n = 8; CurEmulatedTime = OnTrueTime - n; } if (ExtraTimeNotOver() && (--n > 0)) { /* lagging, catch up */ EmVideoDisable = trueblnr; do { DoEmulateOneTick(); ++CurEmulatedTime; } while (ExtraTimeNotOver() && (--n > 0)); EmVideoDisable = falseblnr; } EmLagTime = n; } } LOCALPROC MainEventLoop(void) { for (; ; ) { WaitForNextTick(); if (ForceMacOff) { return; } RunEmulatedTicksToTrueTime(); DoEmulateExtraTime(); } } GLOBALPROC ProgramMain(void) { if (InitEmulation()) { MainEventLoop(); } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/PROGMAIN.h b/Mini vMac/mnvm_core/PROGMAIN.h new file mode 100755 index 0000000..9a3db71 --- /dev/null +++ b/Mini vMac/mnvm_core/PROGMAIN.h @@ -0,0 +1 @@ +/* PROGMAIN.h Copyright (C) 2009 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef PROGMAIN_H #error "header already included" #else #define PROGMAIN_H #endif EXPORTPROC EmulationReserveAlloc(void); EXPORTPROC ProgramMain(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ROMEMDEV.c b/Mini vMac/mnvm_core/ROMEMDEV.c new file mode 100755 index 0000000..faacb40 --- /dev/null +++ b/Mini vMac/mnvm_core/ROMEMDEV.c @@ -0,0 +1 @@ +/* ROMEMDEV.c Copyright (C) 2007 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Read Only Memory EMulated DEVice Checks the header of the loaded ROM image, and then patches the ROM image. This code descended from "ROM.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "ROMEMDEV.h" #define UseSonyPatch \ ((CurEmMd <= kEmMd_Classic) || (CurEmMd == kEmMd_II) \ || (CurEmMd == kEmMd_IIx)) #define UseLargeScreenHack \ (IncludeVidMem \ && (CurEmMd != kEmMd_PB100) \ && (CurEmMd != kEmMd_II) \ && (CurEmMd != kEmMd_IIx)) #if UseSonyPatch LOCALVAR const ui3b sony_driver[] = { /* Replacement for .Sony driver 68k machine code, compiled from mydriver.a */ 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x18, 0x00, 0x24, 0x00, 0x4A, 0x00, 0x8A, 0x05, 0x2E, 0x53, 0x6F, 0x6E, 0x79, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x01, 0x60, 0x30, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x02, 0x41, 0xFA, 0x01, 0x84, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x0C, 0x68, 0x00, 0x01, 0x00, 0x1A, 0x66, 0x1E, 0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x01, 0x5E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x32, 0x28, 0x00, 0x06, 0x08, 0x01, 0x00, 0x09, 0x67, 0x0C, 0x4A, 0x40, 0x6F, 0x02, 0x42, 0x40, 0x31, 0x40, 0x00, 0x10, 0x4E, 0x75, 0x4A, 0x40, 0x6F, 0x04, 0x42, 0x40, 0x4E, 0x75, 0x2F, 0x38, 0x08, 0xFC, 0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x01, 0x1E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x4E, 0x75, 0x48, 0xE7, 0xE0, 0xC0, 0x20, 0x2F, 0x00, 0x14, 0x59, 0x4F, 0x2F, 0x00, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x08, 0x41, 0xFA, 0x00, 0xF8, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x32, 0x1F, 0x58, 0x4F, 0x20, 0x1F, 0x4A, 0x41, 0x66, 0x06, 0x30, 0x7C, 0x00, 0x07, 0xA0, 0x2F, 0x4C, 0xDF, 0x03, 0x07, 0x58, 0x4F, 0x4E, 0x73, 0x21, 0x40, 0x00, 0x06, 0x43, 0xF8, 0x03, 0x08, 0x4E, 0xF9, 0x00, 0x40, 0x0B, 0x20, 0x4E, 0x75, 0x48, 0xE7, 0x1F, 0x10, 0x48, 0xE7, 0x00, 0xC0, 0x5D, 0x4F, 0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0xB6, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x2E, 0x1F, 0x0C, 0x40, 0xFF, 0xCF, 0x66, 0x06, 0x42, 0x40, 0x60, 0x00, 0x00, 0x8E, 0x4A, 0x40, 0x66, 0x00, 0x00, 0x88, 0x20, 0x07, 0xA7, 0x1E, 0x26, 0x48, 0x20, 0x0B, 0x67, 0x00, 0x00, 0x86, 0x9E, 0xFC, 0x00, 0x10, 0x2F, 0x0B, 0x2F, 0x07, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x06, 0x41, 0xFA, 0x00, 0x7A, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x50, 0x4F, 0x2E, 0x1F, 0x76, 0x00, 0x36, 0x1F, 0x38, 0x1F, 0x3C, 0x1F, 0x3A, 0x1F, 0x26, 0x5F, 0x4A, 0x40, 0x66, 0x4A, 0x20, 0x0B, 0x67, 0x0E, 0x41, 0xFA, 0xFF, 0x8C, 0x27, 0x48, 0x00, 0x06, 0x20, 0x4B, 0xA0, 0x58, 0x60, 0x1A, 0x41, 0xFA, 0xFF, 0x70, 0x30, 0x3C, 0xA0, 0x4E, 0xA0, 0x47, 0x60, 0x0E, 0x20, 0x47, 0x30, 0x06, 0x48, 0x40, 0x30, 0x05, 0xA0, 0x4E, 0xDE, 0x83, 0x52, 0x46, 0x51, 0xCC, 0xFF, 0xF0, 0x48, 0x7A, 0xFF, 0x1C, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x07, 0x41, 0xFA, 0x00, 0x1E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x58, 0x4F, 0x4C, 0xDF, 0x03, 0x00, 0x4C, 0xDF, 0x08, 0xF8, 0x4E, 0x75, 0x30, 0x3C, 0xFF, 0xFF, 0x60, 0xF0 }; #endif #if UseSonyPatch LOCALVAR const ui3b my_disk_icon[] = { 0x7F, 0xFF, 0xFF, 0xF0, 0x81, 0x00, 0x01, 0x08, 0x81, 0x00, 0x71, 0x04, 0x81, 0x00, 0x89, 0x02, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xFF, 0xFE, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x83, 0xFF, 0xFF, 0xC1, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x06, 0x30, 0x21, 0x84, 0x06, 0x60, 0x21, 0x84, 0x06, 0xC0, 0x21, 0x84, 0x07, 0x80, 0x21, 0x84, 0x07, 0x00, 0x21, 0x84, 0x06, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x7F, 0xFF, 0xFF, 0xFE, /* mask */ 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, /* empty pascal string */ 0x00, 0x00, }; #endif #if CurEmMd <= kEmMd_128K #define Sony_DriverBase 0x1690 #elif CurEmMd <= kEmMd_Plus #define Sony_DriverBase 0x17D30 #elif CurEmMd <= kEmMd_Classic #define Sony_DriverBase 0x34680 #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define Sony_DriverBase 0x2D72C #endif #define kVidMem_Base 0x00540000 #if UseSonyPatch LOCALPROC Sony_Install(void) { ui3p pto = Sony_DriverBase + ROM; MyMoveBytes((anyp)sony_driver, (anyp)pto, sizeof(sony_driver)); pto += sizeof(sony_driver); do_put_mem_word(pto, kcom_callcheck); pto += 2; do_put_mem_word(pto, kExtnSony); pto += 2; do_put_mem_long(pto, kExtn_Block_Base); /* pokeaddr */ pto += 4; my_disk_icon_addr = (pto - ROM) + kROM_Base; MyMoveBytes((anyp)my_disk_icon, (anyp)pto, sizeof(my_disk_icon)); pto += sizeof(my_disk_icon); #if UseLargeScreenHack { ui3p patchp = pto; #include "SCRNHACK.h" } #endif (void) pto; /* avoid warning about unused */ } #endif LOCALFUNC blnr Check_Checksum(ui5r CheckSum1) { long int i; ui5b CheckSum2 = 0; ui3p p = 4 + ROM; for (i = (kCheckSumRom_Size - 4) >> 1; --i >= 0; ) { CheckSum2 += do_get_mem_word(p); p += 2; } return (CheckSum1 == CheckSum2); } GLOBALFUNC blnr ROM_Init(void) { ui5r CheckSum = do_get_mem_long(ROM); if (! Check_Checksum(CheckSum)) { WarnMsgCorruptedROM(); } else #if CurEmMd <= kEmMd_128K if (CheckSum == 0x28BA61CE) { } else if (CheckSum == 0x28BA4E50) { } else #elif CurEmMd <= kEmMd_Plus if (CheckSum == 0x4D1EEEE1) { /* Mac Plus ROM v 1, 'Lonely Hearts' */ } else if (CheckSum == 0x4D1EEAE1) { /* Mac Plus ROM v 2, 'Lonely Heifers' */ } else if (CheckSum == 0x4D1F8172) { /* Mac Plus ROM v 3, 'Loud Harmonicas' */ } else #elif CurEmMd <= kEmMd_SE if (CheckSum == 0xB2E362A8) { } else #elif CurEmMd <= kEmMd_SEFDHD if (CheckSum == 0xB306E171) { } else #elif CurEmMd <= kEmMd_Classic if (CheckSum == 0xA49F9914) { } else #elif CurEmMd <= kEmMd_PB100 if (CheckSum == 0x96645F9C) { } else #elif CurEmMd <= kEmMd_II if (CheckSum == 0x9779D2C4) { } else if (CheckSum == 0x97221136) { /* accept IIx ROM */ } else #elif CurEmMd <= kEmMd_IIx if (CheckSum == 0x97221136) { } else #endif { WarnMsgUnsupportedROM(); } /* Even if ROM is corrupt or unsupported, go ahead and try to run anyway. It shouldn't do any harm. */ /* skip the rom checksum */ #if CurEmMd <= kEmMd_128K do_put_mem_word(226 + ROM, 0x6004); #elif CurEmMd <= kEmMd_Plus do_put_mem_word(3450 + ROM, 0x6022); #elif CurEmMd <= kEmMd_Classic do_put_mem_word(7272 + ROM, 0x6008); #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) do_put_mem_word(0x2AB0 + ROM, 0x6008); #endif #if CurEmMd <= kEmMd_128K #elif CurEmMd <= kEmMd_Plus do_put_mem_word(3752 + ROM, 0x4E71); /* shorten the ram check read */ do_put_mem_word(3728 + ROM, 0x4E71); /* shorten the ram check write */ #elif CurEmMd <= kEmMd_Classic do_put_mem_word(134 + ROM, 0x6002); do_put_mem_word(286 + ROM, 0x6002); #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) do_put_mem_word(0xEE + ROM, 0x6002); do_put_mem_word(0x1AA + ROM, 0x6002); #endif /* do_put_mem_word(862 + ROM, 0x4E71); */ /* shorten set memory */ #if UseSonyPatch Sony_Install(); #endif return trueblnr; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ROMEMDEV.h b/Mini vMac/mnvm_core/ROMEMDEV.h new file mode 100755 index 0000000..d241a93 --- /dev/null +++ b/Mini vMac/mnvm_core/ROMEMDEV.h @@ -0,0 +1 @@ +/* ROMEMDEV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef ROMEMDEV_H #error "header already included" #else #define ROMEMDEV_H #endif EXPORTFUNC blnr ROM_Init(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/RTCEMDEV.c b/Mini vMac/mnvm_core/RTCEMDEV.c new file mode 100755 index 0000000..abdfd9c --- /dev/null +++ b/Mini vMac/mnvm_core/RTCEMDEV.c @@ -0,0 +1 @@ +/* RTCEMDEV.c Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Real Time Clock EMulated DEVice Emulates the RTC found in the Mac Plus. This code adapted from "RTC.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif /* define _RTC_Debug */ #ifdef _RTC_Debug #include #endif #include "RTCEMDEV.h" #define HaveXPRAM (CurEmMd >= kEmMd_Plus) #if HaveXPRAM #define PARAMRAMSize 256 #else #define PARAMRAMSize 20 #endif #if HaveXPRAM #define Group1Base 0x10 #define Group2Base 0x08 #else #define Group1Base 0x00 #define Group2Base 0x10 #endif typedef struct { /* RTC VIA Flags */ ui3b WrProtect; ui3b DataOut; ui3b DataNextOut; /* RTC Data */ ui3b ShiftData; ui3b Counter; ui3b Mode; ui3b SavedCmd; #if HaveXPRAM ui3b Sector; #endif /* RTC Registers */ ui3b Seconds_1[4]; ui3b PARAMRAM[PARAMRAMSize]; } RTC_Ty; LOCALVAR RTC_Ty RTC; /* RTC Functions */ LOCALVAR ui5b LastRealDate; #ifndef RTCinitPRAM #define RTCinitPRAM 1 #endif #ifndef TrackSpeed /* in 0..4 */ #define TrackSpeed 0 #endif #ifndef AlarmOn /* in 0..1 */ #define AlarmOn 0 #endif #ifndef DiskCacheSz /* in 1,2,3,4,6,8,12 */ /* actual cache size is DiskCacheSz * 32k */ #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define DiskCacheSz 1 #else #define DiskCacheSz 4 #endif #endif #ifndef StartUpDisk /* in 0..1 */ #define StartUpDisk 0 #endif #ifndef DiskCacheOn /* in 0..1 */ #define DiskCacheOn 0 #endif #ifndef MouseScalingOn /* in 0..1 */ #define MouseScalingOn 0 #endif #define prb_fontHi 0 #define prb_fontLo 2 #define prb_kbdPrintHi (AutoKeyRate + (AutoKeyThresh << 4)) #define prb_kbdPrintLo 0 #define prb_volClickHi (SpeakerVol + (TrackSpeed << 3) + (AlarmOn << 7)) #define prb_volClickLo (CaretBlinkTime + (DoubleClickTime << 4)) #define prb_miscHi DiskCacheSz #define prb_miscLo \ ((MenuBlink << 2) + (StartUpDisk << 4) \ + (DiskCacheOn << 5) + (MouseScalingOn << 6)) #if dbglog_HAVE && 0 EXPORTPROC DumpRTC(void); GLOBALPROC DumpRTC(void) { int Counter; dbglog_writeln("RTC Parameter RAM"); for (Counter = 0; Counter < PARAMRAMSize; Counter++) { dbglog_writeNum(Counter); dbglog_writeCStr(", "); dbglog_writeHex(RTC.PARAMRAM[Counter]); dbglog_writeReturn(); } } #endif GLOBALFUNC blnr RTC_Init(void) { int Counter; ui5b secs; RTC.Mode = RTC.ShiftData = RTC.Counter = 0; RTC.DataOut = RTC.DataNextOut = 0; RTC.WrProtect = falseblnr; secs = CurMacDateInSeconds; LastRealDate = secs; RTC.Seconds_1[0] = secs & 0xFF; RTC.Seconds_1[1] = (secs & 0xFF00) >> 8; RTC.Seconds_1[2] = (secs & 0xFF0000) >> 16; RTC.Seconds_1[3] = (secs & 0xFF000000) >> 24; for (Counter = 0; Counter < PARAMRAMSize; Counter++) { RTC.PARAMRAM[Counter] = 0; } #if RTCinitPRAM RTC.PARAMRAM[0 + Group1Base] = 168; /* valid */ #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[2 + Group1Base] = 1; /* node id hint for printer port (AppleTalk) */ #endif RTC.PARAMRAM[3 + Group1Base] = 34; /* serial ports config bits: 4-7 A, 0-3 B useFree 0 Use undefined useATalk 1 AppleTalk useAsync 2 Async useExtClk 3 externally clocked */ RTC.PARAMRAM[4 + Group1Base] = 204; /* portA, high */ RTC.PARAMRAM[5 + Group1Base] = 10; /* portA, low */ RTC.PARAMRAM[6 + Group1Base] = 204; /* portB, high */ RTC.PARAMRAM[7 + Group1Base] = 10; /* portB, low */ RTC.PARAMRAM[13 + Group1Base] = prb_fontLo; RTC.PARAMRAM[14 + Group1Base] = prb_kbdPrintHi; #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[15 + Group1Base] = 1; /* printer, if any, connected to modem port because printer port used for appletalk. */ #endif #if prb_volClickHi != 0 RTC.PARAMRAM[0 + Group2Base] = prb_volClickHi; #endif RTC.PARAMRAM[1 + Group2Base] = prb_volClickLo; RTC.PARAMRAM[2 + Group2Base] = prb_miscHi; RTC.PARAMRAM[3 + Group2Base] = prb_miscLo #if 0 != vMacScreenDepth | 0x80 #endif ; #if HaveXPRAM /* extended parameter ram initialized */ #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[12] = 0x4e; RTC.PARAMRAM[13] = 0x75; RTC.PARAMRAM[14] = 0x4d; RTC.PARAMRAM[15] = 0x63; #else RTC.PARAMRAM[12] = 0x42; RTC.PARAMRAM[13] = 0x75; RTC.PARAMRAM[14] = 0x67; RTC.PARAMRAM[15] = 0x73; #endif #endif #if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \ || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x01] = 0x80; RTC.PARAMRAM[0x02] = 0x4F; #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x03] = 0x48; /* video board id */ RTC.PARAMRAM[0x46] = /* 0x42 */ 0x76; /* 'v' */ RTC.PARAMRAM[0x47] = /* 0x32 */ 0x4D; /* 'M' */ /* mode */ #if 0 == vMacScreenDepth RTC.PARAMRAM[0x48] = 0x80; #else RTC.PARAMRAM[0x48] = 0x80; /* 0x81 doesn't quite work right at boot */ #endif #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x77] = 0x01; #endif #if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \ || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) /* start up disk (encoded how?) */ RTC.PARAMRAM[0x78] = 0x00; RTC.PARAMRAM[0x79] = 0x01; RTC.PARAMRAM[0x7A] = 0xFF; RTC.PARAMRAM[0x7B] = 0xFE; #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x80] = 0x09; RTC.PARAMRAM[0x81] = 0x80; #endif #if HaveXPRAM /* extended parameter ram initialized */ do_put_mem_long(&RTC.PARAMRAM[0xE4], CurMacLatitude); do_put_mem_long(&RTC.PARAMRAM[0xE8], CurMacLongitude); do_put_mem_long(&RTC.PARAMRAM[0xEC], CurMacDelta); #endif #endif /* RTCinitPRAM */ return trueblnr; } #ifdef RTC_OneSecond_PulseNtfy IMPORTPROC RTC_OneSecond_PulseNtfy(void); #endif GLOBALPROC RTC_Interrupt(void) { ui5b Seconds = 0; ui5b NewRealDate = CurMacDateInSeconds; ui5b DateDelta = NewRealDate - LastRealDate; if (DateDelta != 0) { Seconds = (RTC.Seconds_1[3] << 24) + (RTC.Seconds_1[2] << 16) + (RTC.Seconds_1[1] << 8) + RTC.Seconds_1[0]; Seconds += DateDelta; RTC.Seconds_1[0] = Seconds & 0xFF; RTC.Seconds_1[1] = (Seconds & 0xFF00) >> 8; RTC.Seconds_1[2] = (Seconds & 0xFF0000) >> 16; RTC.Seconds_1[3] = (Seconds & 0xFF000000) >> 24; LastRealDate = NewRealDate; #ifdef RTC_OneSecond_PulseNtfy RTC_OneSecond_PulseNtfy(); #endif } } LOCALFUNC ui3b RTC_Access_PRAM_Reg(ui3b Data, blnr WriteReg, ui3b t) { if (WriteReg) { if (! RTC.WrProtect) { RTC.PARAMRAM[t] = Data; #ifdef _RTC_Debug printf("Writing Address %2x, Data %2x\n", t, Data); #endif } } else { Data = RTC.PARAMRAM[t]; } return Data; } LOCALFUNC ui3b RTC_Access_Reg(ui3b Data, blnr WriteReg, ui3b TheCmd) { ui3b t = (TheCmd & 0x7C) >> 2; if (t < 8) { if (WriteReg) { if (! RTC.WrProtect) { RTC.Seconds_1[t & 0x03] = Data; } } else { Data = RTC.Seconds_1[t & 0x03]; } } else if (t < 12) { Data = RTC_Access_PRAM_Reg(Data, WriteReg, (t & 0x03) + Group2Base); } else if (t < 16) { if (WriteReg) { switch (t) { case 12 : break; /* Test Write, do nothing */ case 13 : RTC.WrProtect = (Data & 0x80) != 0; break; /* Write_Protect Register */ default : ReportAbnormal("Write RTC Reg unknown"); break; } } else { ReportAbnormal("Read RTC Reg unknown"); } } else { Data = RTC_Access_PRAM_Reg(Data, WriteReg, (t & 0x0F) + Group1Base); } return Data; } LOCALPROC RTC_DoCmd(void) { switch (RTC.Mode) { case 0: /* This Byte is a RTC Command */ #if HaveXPRAM if ((RTC.ShiftData & 0x78) == 0x38) { /* Extended Command */ RTC.SavedCmd = RTC.ShiftData; RTC.Mode = 2; #ifdef _RTC_Debug printf("Extended command %2x\n", RTC.ShiftData); #endif } else #endif { if ((RTC.ShiftData & 0x80) != 0x00) { /* Read Command */ RTC.ShiftData = RTC_Access_Reg(0, falseblnr, RTC.ShiftData); RTC.DataNextOut = 1; } else { /* Write Command */ RTC.SavedCmd = RTC.ShiftData; RTC.Mode = 1; } } break; case 1: /* This Byte is data for RTC Write */ (void) RTC_Access_Reg(RTC.ShiftData, trueblnr, RTC.SavedCmd); RTC.Mode = 0; break; #if HaveXPRAM case 2: /* This Byte is rest of Extended RTC command address */ #ifdef _RTC_Debug printf("Mode 2 %2x\n", RTC.ShiftData); #endif RTC.Sector = ((RTC.SavedCmd & 0x07) << 5) | ((RTC.ShiftData & 0x7C) >> 2); if ((RTC.SavedCmd & 0x80) != 0x00) { /* Read Command */ RTC.ShiftData = RTC.PARAMRAM[RTC.Sector]; RTC.DataNextOut = 1; RTC.Mode = 0; #ifdef _RTC_Debug printf("Reading X Address %2x, Data %2x\n", RTC.Sector, RTC.ShiftData); #endif } else { RTC.Mode = 3; #ifdef _RTC_Debug printf("Writing X Address %2x\n", RTC.Sector); #endif } break; case 3: /* This Byte is data for an Extended RTC Write */ (void) RTC_Access_PRAM_Reg(RTC.ShiftData, trueblnr, RTC.Sector); RTC.Mode = 0; break; #endif } } GLOBALPROC RTCunEnabled_ChangeNtfy(void) { if (RTCunEnabled) { /* abort anything going on */ if (RTC.Counter != 0) { #ifdef _RTC_Debug printf("aborting, %2x\n", RTC.Counter); #endif ReportAbnormal("RTC aborting"); } RTC.Mode = 0; RTC.DataOut = 0; RTC.DataNextOut = 0; RTC.ShiftData = 0; RTC.Counter = 0; } } GLOBALPROC RTCclock_ChangeNtfy(void) { if (! RTCunEnabled) { if (RTCclock) { RTC.DataOut = RTC.DataNextOut; RTC.Counter = (RTC.Counter - 1) & 0x07; if (RTC.DataOut) { RTCdataLine = ((RTC.ShiftData >> RTC.Counter) & 0x01); /* should notify VIA if changed, so can check data direction */ if (RTC.Counter == 0) { RTC.DataNextOut = 0; } } else { RTC.ShiftData = (RTC.ShiftData << 1) | RTCdataLine; if (RTC.Counter == 0) { RTC_DoCmd(); } } } } } GLOBALPROC RTCdataLine_ChangeNtfy(void) { #if dbglog_HAVE if (RTC.DataOut) { if (! RTC.DataNextOut) { /* ignore. The ROM doesn't read from the RTC the way described in the Hardware Reference. It reads the data after setting the clock to one instead of before, and then immediately changes the VIA direction. So the RTC has no way of knowing to stop driving the data line, which certainly can't really be correct. */ } else { ReportAbnormal("write RTC Data unexpected direction"); } } #endif } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/RTCEMDEV.h b/Mini vMac/mnvm_core/RTCEMDEV.h new file mode 100755 index 0000000..174a3e0 --- /dev/null +++ b/Mini vMac/mnvm_core/RTCEMDEV.h @@ -0,0 +1 @@ +/* RTCEMDEV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef RTCEMDEV_H #error "header already included" #else #define RTCEMDEV_H #endif EXPORTFUNC blnr RTC_Init(void); EXPORTPROC RTC_Interrupt(void); EXPORTPROC RTCunEnabled_ChangeNtfy(void); EXPORTPROC RTCclock_ChangeNtfy(void); EXPORTPROC RTCdataLine_ChangeNtfy(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCCEMDEV.c b/Mini vMac/mnvm_core/SCCEMDEV.c new file mode 100755 index 0000000..bfb8899 --- /dev/null +++ b/Mini vMac/mnvm_core/SCCEMDEV.c @@ -0,0 +1 @@ +/* SCCEMDEV.c Copyright (C) 2012 Philip Cummins, Weston Pawlowski, Michael Fort, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Serial Communications Controller EMulated DEVice additions for LocalTalk networking support Copyright 2011-2012, Michael Fort enabled with "EmLocalTalk" -- original description: -- Emulates the Z8530 SCC found in the Mac Plus. But only the minimum amount needed to emulate normal operation in a Mac Plus with nothing connected to the serial ports. (and not even that much is complete yet) This code adapted from "SCC.c" in vMac by Philip Cummins. With additional code by Weston Pawlowski from the Windows port of vMac. Further information was found in the "Zilog SCC/ESCC User's Manual". */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "SCCEMDEV.h" #define SCC_dolog (dbglog_HAVE && 0) #define SCC_TrackMore 0 /* Just to make things a little easier */ #define Bit0 1 #define Bit1 2 #define Bit2 4 #define Bit3 8 #define Bit4 16 #define Bit5 32 #define Bit6 64 #define Bit7 128 /* SCC Interrupts */ #define SCC_A_Rx 8 /* Rx Char Available */ #define SCC_A_Rx_Spec 7 /* Rx Special Condition */ #define SCC_A_Tx_Empty 6 /* Tx Buffer Empty */ #define SCC_A_Ext 5 /* External/Status Change */ #define SCC_B_Rx 4 /* Rx Char Available */ #define SCC_B_Rx_Spec 3 /* Rx Special Condition */ #define SCC_B_Tx_Empty 2 /* Tx Buffer Empty */ #define SCC_B_Ext 1 /* External/Status Change */ typedef struct { blnr TxEnable; blnr RxEnable; blnr TxIE; /* Transmit Interrupt Enable */ blnr TxUnderrun; blnr SyncHunt; blnr TxIP; /* Transmit Interrupt Pending */ #if EmLocalTalk ui3r RxBuff; #endif #if EmLocalTalk /* otherwise TxBufferEmpty always true */ /* though should behave as went false for an instant when write to transmit buffer */ blnr TxBufferEmpty; #endif #if EmLocalTalk || SCC_TrackMore blnr ExtIE; #endif #if SCC_TrackMore blnr WaitRqstEnbl; #endif #if SCC_TrackMore blnr WaitRqstSlct; #endif #if SCC_TrackMore blnr WaitRqstRT; #endif #if SCC_TrackMore blnr PrtySpclCond; #endif #if SCC_TrackMore blnr PrtyEnable; #endif #if SCC_TrackMore blnr PrtyEven; #endif #if SCC_TrackMore blnr RxCRCEnbl; #endif #if SCC_TrackMore blnr TxCRCEnbl; #endif #if SCC_TrackMore blnr RTSctrl; #endif #if SCC_TrackMore blnr SndBrkCtrl; #endif #if SCC_TrackMore blnr DTRctrl; #endif #if EmLocalTalk || SCC_TrackMore blnr AddrSrchMd; #endif #if SCC_TrackMore blnr SyncChrLdInhb; #endif #if SCC_TrackMore ui3r ClockRate; #endif #if SCC_TrackMore ui3r DataEncoding; #endif #if SCC_TrackMore ui3r TRxCsrc; #endif #if SCC_TrackMore ui3r TClkSlct; #endif #if SCC_TrackMore ui3r RClkSlct; #endif #if SCC_TrackMore ui3r RBitsPerChar; #endif #if SCC_TrackMore ui3r TBitsPerChar; #endif #if EmLocalTalk || SCC_TrackMore ui3r RxIntMode; #endif #if EmLocalTalk || SCC_TrackMore blnr FirstChar; #endif #if EmLocalTalk || SCC_TrackMore ui3r SyncMode; #endif #if SCC_TrackMore ui3r StopBits; #endif #if 0 /* AllSent always true */ blnr AllSent; #endif #if 0 /* CTS always false */ blnr CTS; /* input pin, unattached, so false? */ #endif #if 0 /* DCD always false */ blnr DCD; /* Data Carrier Detect */ /* input pin for mouse interrupts. but since not emulating mouse this way, leave false. */ #endif #if EmLocalTalk /* otherwise RxChrAvail always false */ blnr RxChrAvail; #endif #if 0 /* RxOverrun always false */ blnr RxOverrun; #endif #if 0 /* CRCFramingErr always false */ blnr CRCFramingErr; #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ blnr EndOfFrame; #endif #if 0 /* ParityErr always false */ blnr ParityErr; #endif #if 0 /* ZeroCount always false */ blnr ZeroCount; #endif #if 0 /* BreakAbort always false */ blnr BreakAbort; #endif #if 0 /* SyncHuntIE usually false */ blnr SyncHuntIE; #endif #if SCC_TrackMore /* don't care about CTS_IE */ blnr CTS_IE; #endif #if SCC_TrackMore blnr CRCPreset; #endif #if SCC_TrackMore blnr BRGEnbl; #endif #if 0 /* don't care about DCD_IE, always true */ blnr DCD_IE; #endif #if SCC_TrackMore /* don't care about BreakAbortIE */ blnr BreakAbortIE; #endif #if SCC_TrackMore /* don't care about Baud */ ui3r BaudLo; ui3r BaudHi; #endif } Channel_Ty; typedef struct { Channel_Ty a[2]; /* 0 = channel A, 1 = channel B */ int SCC_Interrupt_Type; int PointerBits; ui3b InterruptVector; blnr MIE; /* master interrupt enable */ #if SCC_TrackMore blnr NoVectorSlct; #endif #if 0 /* StatusHiLo always false */ blnr StatusHiLo; #endif } SCC_Ty; LOCALVAR SCC_Ty SCC; #if 0 LOCALVAR int ReadPrint; LOCALVAR int ReadModem; #endif #if EmLocalTalk static int rx_data_offset = 0; /* when data pending, this is used */ #endif EXPORTFUNC blnr SCC_InterruptsEnabled(void) { return SCC.MIE; } /* ---- */ /* Function used to update the interrupt state of the SCC */ LOCALPROC CheckSCCInterruptFlag(void) { #if 0 /* ReceiveAInterrupt always false */ blnr ReceiveAInterrupt = falseblnr /* also dependeds on WR1, bits 3 and 4, but this doesn't change that it's all false */ #if EmLocalTalk /* otherwise RxChrAvail always false */ | SCC.a[0].RxChrAvail #endif #if 0 /* RxOverrun always false */ | SCC.a[0].RxOverrun #endif #if 0 /* CRCFramingErr always false */ | SCC.a[0].CRCFramingErr #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ | SCC.a[0].EndOfFrame #endif #if 0 /* ParityErr always false */ | SCC.a[0].ParityErr #endif ; #endif #if 0 blnr TransmitAInterrupt = SCC.a[0].TxBufferEmpty; /* but probably looking for transitions not current value */ #endif #if 0 blnr ExtStatusAInterrupt = 0 #if 0 /* ZeroCount always false */ | SCC.a[0].ZeroCount #endif /* probably want transition for these, not value */ #if 0 /* DCD always false */ | SCC.a[0].DCD /* DCD IE always true */ #endif #if 0 /* CTS always false */ | SCC.a[0].CTS /* would depend on CTS_IE */ #endif | SCC.a[0].SyncHunt /* SyncHuntIE usually false */ | SCC.a[0].TxUnderrun /* Tx underrun/EOM IE always false */ #if 0 /* BreakAbort always false */ | SCC.a[0].BreakAbort #endif ; #endif ui3b NewSCCInterruptRequest; #if EmLocalTalk blnr ReceiveBInterrupt = falseblnr; blnr RxSpclBInterrupt = falseblnr /* otherwise EndOfFrame always false */ | SCC.a[1].EndOfFrame ; #endif #if EmLocalTalk switch (SCC.a[1].RxIntMode) { case 0: /* disabled */ RxSpclBInterrupt = falseblnr; break; case 1: /* Rx INT on 1st char or special condition */ if (SCC.a[1].RxChrAvail && SCC.a[1].FirstChar) { ReceiveBInterrupt = trueblnr; } break; case 2: /* INT on all Rx char or special condition */ if (SCC.a[1].RxChrAvail) { ReceiveBInterrupt = trueblnr; } break; case 3: /* Rx INT on special condition only */ break; } #endif /* Master Interrupt Enable */ if (! SCC.MIE) { SCC.SCC_Interrupt_Type = 0; } else #if 0 /* External Interrupt Enable */ if (SCC.a[1].ExtIE) { /* DCD Interrupt Enable */ if (SCC.a[1].DCD_IE && 0) { /* dcd unchanged */ SCC.SCC_Interrupt_Type = ??; } } #endif if (SCC.a[0].TxIP && SCC.a[0].TxIE) { SCC.SCC_Interrupt_Type = SCC_A_Tx_Empty; } else #if EmLocalTalk if (ReceiveBInterrupt) { SCC.SCC_Interrupt_Type = SCC_B_Rx; } else if (RxSpclBInterrupt) { SCC.SCC_Interrupt_Type = SCC_B_Rx_Spec; } else #endif if (SCC.a[1].TxIP && SCC.a[1].TxIE) { SCC.SCC_Interrupt_Type = SCC_B_Tx_Empty; } else { SCC.SCC_Interrupt_Type = 0; } NewSCCInterruptRequest = (SCC.SCC_Interrupt_Type != 0) ? 1 : 0; if (NewSCCInterruptRequest != SCCInterruptRequest) { #if SCC_dolog dbglog_WriteSetBool("SCCInterruptRequest change", NewSCCInterruptRequest); dbglog_StartLine(); dbglog_writeCStr("SCC.SCC_Interrupt_Type <- "); dbglog_writeHex(SCC.SCC_Interrupt_Type); dbglog_writeReturn(); #endif SCCInterruptRequest = NewSCCInterruptRequest; #ifdef SCCinterruptChngNtfy SCCinterruptChngNtfy(); #endif } } LOCALPROC SCC_InitChannel(int chan) { /* anything not done by ResetChannel */ SCC.a[chan].SyncHunt = trueblnr; #if 0 /* DCD always false */ SCC.a[chan].DCD = falseblnr; /* input pin, reset doesn't change */ #endif #if 0 /* CTS always false */ SCC.a[chan].CTS = falseblnr; /* input pin, reset doesn't change */ #endif #if 0 /* AllSent always true */ SCC.a[chan].AllSent = trueblnr; #endif #if SCC_TrackMore /* don't care about Baud */ SCC.a[chan].BaudLo = 0; SCC.a[chan].BaudHi = 0; #endif #if 0 /* BreakAbort always false */ SCC.a[chan].BreakAbort = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].BRGEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].TRxCsrc = 0; #endif #if SCC_TrackMore SCC.a[chan].TClkSlct = 1; #endif #if SCC_TrackMore SCC.a[chan].RClkSlct = 0; #endif } LOCALPROC SCC_ResetChannel(int chan) { /* RR 0 */ #if EmLocalTalk SCC.a[chan].RxBuff = 0; #endif #if EmLocalTalk /* otherwise RxChrAvail always false */ SCC.a[chan].RxChrAvail = falseblnr; #endif #if 0 /* ZeroCount always false */ SCC.a[chan].ZeroCount = falseblnr; #endif #if EmLocalTalk /* otherwise TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif SCC.a[chan].TxUnderrun = trueblnr; /* RR 1 */ #if 0 /* ParityErr always false */ SCC.a[chan].ParityErr = falseblnr; #endif #if 0 /* RxOverrun always false */ SCC.a[chan].RxOverrun = falseblnr; #endif #if 0 /* CRCFramingErr always false */ SCC.a[chan].CRCFramingErr = falseblnr; #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ SCC.a[chan].EndOfFrame = falseblnr; #endif /* RR 3 */ #if EmLocalTalk || SCC_TrackMore SCC.a[chan].ExtIE = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].RxCRCEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].TxCRCEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].RTSctrl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].SndBrkCtrl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].DTRctrl = falseblnr; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].AddrSrchMd = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].SyncChrLdInhb = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].WaitRqstEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].WaitRqstSlct = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].WaitRqstRT = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].PrtySpclCond = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].PrtyEnable = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].PrtyEven = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].ClockRate = 0; #endif #if SCC_TrackMore SCC.a[chan].DataEncoding = 0; #endif #if SCC_TrackMore SCC.a[chan].RBitsPerChar = 0; #endif #if SCC_TrackMore SCC.a[chan].TBitsPerChar = 0; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].RxIntMode = 0; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].FirstChar = falseblnr; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].SyncMode = 0; #endif #if SCC_TrackMore SCC.a[chan].StopBits = 0; #endif #if SCC_TrackMore SCC.NoVectorSlct = falseblnr; #endif SCC.a[chan].TxIP = falseblnr; SCC.a[chan].TxEnable = falseblnr; SCC.a[chan].RxEnable = falseblnr; SCC.a[chan].TxIE = falseblnr; #if 0 /* don't care about DCD_IE, always true */ SCC.a[chan].DCD_IE = trueblnr; #endif #if SCC_TrackMore /* don't care about CTS_IE */ SCC.a[chan].CTS_IE = trueblnr; #endif #if SCC_TrackMore SCC.a[chan].CRCPreset = falseblnr; #endif #if 0 /* SyncHuntIE usually false */ SCC.a[chan].SyncHuntIE = trueblnr; #endif #if SCC_TrackMore /* don't care about BreakAbortIE */ SCC.a[chan].BreakAbortIE = trueblnr; #endif SCC.PointerBits = 0; #if 0 if (chan != 0) { ReadPrint = 0; } else { ReadModem = 0; } #endif } GLOBALPROC SCC_Reset(void) { SCCwaitrq = 1; SCC.SCC_Interrupt_Type = 0; SCCInterruptRequest = 0; SCC.PointerBits = 0; SCC.MIE = falseblnr; SCC.InterruptVector = 0; #if 0 /* StatusHiLo always false */ SCC.StatusHiLo = falseblnr; #endif SCC_InitChannel(1); SCC_InitChannel(0); SCC_ResetChannel(1); SCC_ResetChannel(0); } #if EmLocalTalk LOCALVAR blnr CTSpacketPending = falseblnr; LOCALVAR ui3r CTSpacketRxDA; LOCALVAR ui3r CTSpacketRxSA; /* Function used when all the tx data is sent to the SCC as indicated by resetting the TX underrun/EOM latch. If the transmit packet is a unicast RTS LAPD packet, we fake the corresponding CTS LAPD packet. This is okay because it is only a collision avoidance mechanism and the Ethernet device itself and BPF automatically handle collision detection and retransmission. Besides this is what a standard AppleTalk (LocalTalk to EtherTalk) bridge does. */ LOCALPROC process_transmit(void) { /* Check for LLAP packets, which we won't send */ if (LT_TxBuffSz == 3) { /* We will automatically and immediately acknowledge any non-broadcast RTS packets */ if ((LT_TxBuffer[0] != 0xFF) && (LT_TxBuffer[2] == 0x84)) { #if SCC_dolog dbglog_WriteNote("SCC LLAP packet in process_transmit"); #endif if (CTSpacketPending) { ReportAbnormal( "Already CTSpacketPending in process_transmit"); } else { CTSpacketRxDA = LT_TxBuffer[1]; /* rx da = tx sa */ CTSpacketRxSA = LT_TxBuffer[0]; /* rx sa = tx da */ CTSpacketPending = trueblnr; } } } else { LT_TransmitPacket(); } } LOCALPROC SCC_TxBuffPut(ui3r Data) { /* Buffer the data in the transmit buffer */ if (LT_TxBuffSz < LT_TxBfMxSz) { LT_TxBuffer[LT_TxBuffSz] = Data; ++LT_TxBuffSz; } } LOCALVAR ui3b MyCTSBuffer[4]; LOCALPROC GetCTSpacket(void) { /* Get a single buffer worth of packets at a time */ ui3p device_buffer = MyCTSBuffer; #if SCC_dolog dbglog_WriteNote("SCC receiving CTS packet"); #endif /* Create the fake response from the other node */ device_buffer[0] = CTSpacketRxDA; device_buffer[1] = CTSpacketRxSA; device_buffer[2] = 0x85; /* llap cts */ /* Start the receiver */ LT_RxBuffer = device_buffer; LT_RxBuffSz = 3; CTSpacketPending = falseblnr; } /* This function is called once all the normal packet bytes have been received. */ LOCALPROC rx_complete(void) { if (SCC.a[1].EndOfFrame) { ReportAbnormal("EndOfFrame true in rx_complete"); } if (! SCC.a[1].RxChrAvail) { ReportAbnormal("RxChrAvail false in rx_complete"); } if (SCC.a[1].SyncHunt) { ReportAbnormal("SyncHunt true in rx_complete"); } /* Need to wait for rx_eof_pending (end of frame) to clear before preparing the next packet for receive. */ LT_RxBuffer = nullpr; SCC.a[1].EndOfFrame = trueblnr; } LOCALPROC SCC_RxBuffAdvance(void) { ui3r value; /* From the manual: "If status is checked, it must be done before the data is read, because the act of reading the data pops both the data and error FIFOs." */ if (nullpr == LT_RxBuffer) { value = 0x7E; SCC.a[1].RxChrAvail = falseblnr; } else { if (rx_data_offset < LT_RxBuffSz) { value = LT_RxBuffer[rx_data_offset]; } else { ui5r i = rx_data_offset - LT_RxBuffSz; /* if i==0 in first byte of CRC, have not got EOF yet */ if (i == 1) { rx_complete(); } value = 0; } ++rx_data_offset; } SCC.a[1].RxBuff = value; } /* LLAP/SDLC address */ LOCALVAR ui3b my_node_address = 0; LOCALPROC GetNextPacketForMe(void) { unsigned char dst; unsigned char src; label_retry: LT_ReceivePacket(); if (nullpr != LT_RxBuffer) { #if SCC_dolog dbglog_WriteNote("SCC receiving packet from BPF"); #endif /* Is this packet destined for me? */ dst = LT_RxBuffer[0]; src = LT_RxBuffer[1]; if (src == my_node_address) { #if SCC_dolog dbglog_WriteNote("SCC ignore packet from myself"); #endif LT_RxBuffer = nullpr; goto label_retry; } else if ((dst == my_node_address) || (dst == 0xFF) || ! SCC.a[1].AddrSrchMd) { /* ok */ } else { #if SCC_dolog dbglog_WriteNote("SCC ignore packet not for me"); #endif LT_RxBuffer = nullpr; goto label_retry; } } } /* External function, called periodically, to poll for any new LTOE packets. Any new packets are queued into the packet receipt queue. */ GLOBALPROC LocalTalkTick(void) { if (SCC.a[1].RxEnable && (! SCC.a[1].RxChrAvail)) { if (nullpr != LT_RxBuffer) { #if SCC_dolog dbglog_WriteNote("SCC recover abandoned packet"); #endif } else { if (CTSpacketPending) { GetCTSpacket(); } else { GetNextPacketForMe(); } } if (nullpr != LT_RxBuffer) { rx_data_offset = 0; SCC.a[1].EndOfFrame = falseblnr; SCC.a[1].RxChrAvail = trueblnr; SCC.a[1].SyncHunt = falseblnr; SCC_RxBuffAdvance(); /* We can update the rx interrupt if enabled */ CheckSCCInterruptFlag(); } } } #endif #if 0 LOCALPROC SCC_Interrupt(int Type) { if (SCC.MIE) { /* Master Interrupt Enable */ if (Type > SCC.SCC_Interrupt_Type) { SCC.SCC_Interrupt_Type = Type; } CheckSCCInterruptFlag(); } } #endif #if 0 LOCALPROC SCC_Int(void) { /* This should be called at regular intervals */ /* Turn off Sync/Hunt Mode */ if (SCC.a[0].SyncHunt) { SCC.a[0].SyncHunt = falseblnr; #ifdef _SCC_Debug2 vMac_Message("SCC_Int: Disable Sync/Hunt on A"); #endif #if 0 /* SyncHuntIE usually false */ if (SCC.a[0].SyncHuntIE) { SCC_Interrupt(SCC_A_Ext); } #endif } if (SCC.a[1].SyncHunt) { SCC.a[1].SyncHunt = falseblnr; #ifdef _SCC_Debug2 vMac_Message("SCC_Int: Disable Sync/Hunt on B"); #endif #if 0 /* SyncHuntIE usually false */ if (SCC.a[1].SyncHuntIE) { SCC_Interrupt(SCC_B_Ext); } #endif } #if 0 /* Check for incoming data */ if (ModemPort) { if (! SCC.a[0].RxEnable) { /* Rx Disabled */ ReadModem = 0; } if ((ModemBytes > 0) && (ModemCount > ModemBytes - 1)) { SCC.a[0].RxChrAvail = falseblnr; ReadModem = ModemBytes = ModemCount = 0; } if (ReadModem) { ReadModem = 2; SCC.a[0].RxChrAvail = trueblnr; if (SCC.a[0].WR[0] & Bit5 && ! (SCC.a[0].WR[0] & (Bit4 | Bit3))) { /* Int on next Rx char */ SCC_Interrupt(SCC_A_Rx); } else if (SCC.a[0].WR[1] & Bit3 && ! (SCC.a[0].WR[1] & Bit4)) { /* Int on first Rx char */ SCC_Interrupt(SCC_A_Rx); } else if (SCC.a[0].WR[1] & Bit4 && ! (SCC.a[0].WR[1] & Bit3)) { /* Int on all Rx chars */ SCC_Interrupt(SCC_A_Rx); } } } if (PrintPort) { if (! SCC.a[1].RxEnable) { /* Rx Disabled */ ReadPrint = 0; } if ((PrintBytes > 0) && (PrintCount > PrintBytes - 1)) { SCC.a[1].RxChrAvail = falseblnr; ReadPrint = PrintBytes = PrintCount = 0; } if (ReadPrint) { ReadPrint = 2; SCC.a[1].RxChrAvail = trueblnr; if (SCC.a[1].WR[0] & Bit5 && ! (SCC.a[1].WR[0] & (Bit4 | Bit3))) { /* Int on next Rx char */ SCC_Interrupt(SCC_B_Rx); } else if (SCC.a[1].WR[1] & Bit3 && ! (SCC.a[1].WR[1] & Bit4)) { /* Int on first Rx char */ SCC_Interrupt(SCC_B_Rx); } else if (SCC.a[1].WR[1] & Bit4 && ! (SCC.a[1].WR[1] & Bit3)) { /* Int on all Rx chars */ SCC_Interrupt(SCC_B_Rx); } } } #endif } #endif #if SCC_dolog LOCALPROC SCC_DbgLogChanStartLine(int chan) { dbglog_StartLine(); dbglog_writeCStr("SCC chan("); if (chan) { dbglog_writeCStr("B"); } else { dbglog_writeCStr("A"); } /* dbglog_writeHex(chan); */ dbglog_writeCStr(")"); } #endif LOCALFUNC ui3r SCC_GetRR0(int chan) { /* happens on boot always */ return 0 #if 0 /* BreakAbort always false */ | (SCC.a[chan].BreakAbort ? (1 << 7) : 0) #endif | (SCC.a[chan].TxUnderrun ? (1 << 6) : 0) #if 0 /* CTS always false */ | (SCC.a[chan].CTS ? (1 << 5) : 0) #endif | (SCC.a[chan].SyncHunt ? (1 << 4) : 0) #if 0 /* DCD always false */ | (SCC.a[chan].DCD ? (1 << 3) : 0) #endif #if EmLocalTalk | (SCC.a[chan].TxBufferEmpty ? (1 << 2) : 0) #else /* otherwise TxBufferEmpty always true */ | (1 << 2) #endif #if 0 /* ZeroCount always false */ | (SCC.a[chan].ZeroCount ? (1 << 1) : 0) #endif #if EmLocalTalk /* otherwise RxChrAvail always false */ | (SCC.a[chan].RxChrAvail ? (1 << 0) : 0) #endif ; } LOCALFUNC ui3r SCC_GetRR1(int chan) { /* happens in MacCheck */ ui3r value; #if ! EmLocalTalk UnusedParam(chan); #endif value = Bit2 | Bit1 #if 0 /* AllSent always true */ | (SCC.a[chan].AllSent ? (1 << 0) : 0) #else | Bit0 #endif #if 0 /* ParityErr always false */ | (SCC.a[chan].ParityErr ? (1 << 4) : 0) #endif #if 0 /* RxOverrun always false */ | (SCC.a[chan].RxOverrun ? (1 << 5) : 0) #endif #if 0 /* CRCFramingErr always false */ | (SCC.a[chan].CRCFramingErr ? (1 << 6) : 0) #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ | (SCC.a[chan].EndOfFrame ? (1 << 7) : 0) #endif ; return value; } LOCALFUNC ui3r SCC_GetRR2(int chan) { /* happens in MacCheck */ /* happens in Print to ImageWriter */ ui3r value = SCC.InterruptVector; if (chan != 0) { /* B Channel */ #if 0 /* StatusHiLo always false */ if (SCC.StatusHiLo) { /* Status High */ value = value & (Bit0 | Bit1 | Bit2 | Bit3 | Bit7); ReportAbnormal("Status high/low"); switch (SCC.SCC_Interrupt_Type) { case SCC_A_Rx: value |= Bit4 | Bit5; break; case SCC_A_Rx_Spec: value |= Bit4 | Bit5 | Bit6; break; case SCC_A_Tx_Empty: value |= Bit4; break; case SCC_A_Ext: value |= Bit4 | Bit6; break; case SCC_B_Rx: value |= Bit5; break; case SCC_B_Rx_Spec: value |= Bit5 | Bit6; break; case SCC_B_Tx_Empty: value |= 0; break; case SCC_B_Ext: value |= Bit6; break; default: value |= Bit5 | Bit6; break; } } else #endif { /* Status Low */ value = value & (Bit0 | Bit4 | Bit5 | Bit6 | Bit7); switch (SCC.SCC_Interrupt_Type) { case SCC_A_Rx: value |= Bit3 | Bit2; break; case SCC_A_Rx_Spec: value |= Bit3 | Bit2 | Bit1; break; case SCC_A_Tx_Empty: value |= Bit3; break; case SCC_A_Ext: value |= Bit3 | Bit1; break; case SCC_B_Rx: value |= Bit2; break; case SCC_B_Rx_Spec: value |= Bit2 | Bit1; break; case SCC_B_Tx_Empty: value |= 0; break; case SCC_B_Ext: value |= Bit1; break; default: value |= Bit2 | Bit1; break; } } /* SCC.SCC_Interrupt_Type = 0; */ } return value; } LOCALFUNC ui3r SCC_GetRR3(int chan) { ui3r value = 0; UnusedParam(chan); ReportAbnormal("RR 3"); #if 0 if (chan == 0) { value = 0 | (SCC.a[1].TxIP ? (1 << 1) : 0) | (SCC.a[0].TxIP ? (1 << 4) : 0) ; } else { value = 0; } #endif return value; } LOCALFUNC ui3r SCC_GetRR8(int chan) { ui3r value = 0; /* Receive Buffer */ /* happens on boot with appletalk on */ if (SCC.a[chan].RxEnable) { #if EmLocalTalk if (0 != chan) { /* Check the receive state, handling a complete rx if necessary */ value = SCC.a[1].RxBuff; SCC.a[1].FirstChar = falseblnr; SCC_RxBuffAdvance(); } else { value = 0x7E; } #else /* Rx Enable */ #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormal("read rr8 when RxEnable"); #endif /* Input 1 byte from Modem Port/Printer into Data */ #endif } else { /* happens on boot with appletalk on */ } return value; } LOCALFUNC ui3r SCC_GetRR10(int chan) { /* happens on boot with appletalk on */ ui3r value = 0; UnusedParam(chan); #if 0 && EmLocalTalk value = 2; #endif return value; } LOCALFUNC ui3r SCC_GetRR12(int chan) { ui3r value = 0; #if ! SCC_TrackMore UnusedParam(chan); #endif ReportAbnormal("RR 12"); #if SCC_TrackMore /* don't care about Baud */ value = SCC.a[chan].BaudLo; #endif return value; } LOCALFUNC ui3r SCC_GetRR13(int chan) { ui3r value = 0; #if ! SCC_TrackMore UnusedParam(chan); #endif ReportAbnormal("RR 13"); #if SCC_TrackMore /* don't care about Baud */ value = SCC.a[chan].BaudHi; #endif return value; } LOCALFUNC ui3r SCC_GetRR15(int chan) { ui3r value = 0; UnusedParam(chan); ReportAbnormal("RR 15"); #if 0 value = 0 #if 0 /* don't care about DCD_IE, always true */ | (SCC.a[chan].DCD_IE ? Bit3 : 0) #else | Bit3 #endif #if 0 /* SyncHuntIE usually false */ | (SCC.a[chan].SyncHuntIE ? Bit4 : 0) #endif #if SCC_TrackMore /* don't care about CTS_IE */ | (SCC.a[chan].CTS_IE ? Bit5 : 0) #endif #if SCC_TrackMore /* don't care about BreakAbortIE */ | (SCC.a[chan].BreakAbortIE ? Bit7 : 0) #endif ; #endif return value; } #if SCC_dolog LOCALPROC SCC_DbgLogChanCmnd(int chan, char *s) { SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" "); dbglog_writeCStr(s); dbglog_writeReturn(); } #endif #if SCC_dolog LOCALPROC SCC_DbgLogChanChngBit(int chan, char *s, blnr v) { SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" "); dbglog_writeCStr(s); dbglog_writeCStr(" <- "); if (v) { dbglog_writeCStr("1"); } else { dbglog_writeCStr("0"); } dbglog_writeReturn(); } #endif LOCALPROC SCC_PutWR0(ui3r Data, int chan) /* "CRC initialize, initialization commands for the various modes, Register Pointers" */ { switch ((Data >> 6) & 3) { case 1: ReportAbnormal("Reset Rx CRC Checker"); break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Tx CRC Generator"); #endif /* happens on boot with appletalk on */ break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Tx Underrun/EOM Latch"); #endif /* happens on boot with appletalk on */ #if EmLocalTalk /* This is the indication we are done transmitting data for the current packet. */ process_transmit(); #endif #if 0 /* It seems to work better without this */ if (SCC.a[chan].TxEnable) { /* Tx Enabled */ SCC.a[chan].TxUnderrun = falseblnr; if (SCC.a[chan].WR[10] & Bit2) { /* Abort/Flag on Underrun */ /* Send Abort */ SCC.a[chan].TxUnderrun = trueblnr; #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif /* Send Flag */ } } #endif break; case 0: default: /* Null Code */ break; } SCC.PointerBits = Data & 0x07; switch ((Data >> 3) & 7) { case 1: /* Point High */ SCC.PointerBits |= 8; break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Ext/Status Ints"); #endif /* happens on boot always */ SCC.a[chan].SyncHunt = falseblnr; #if 0 /* only in sync mode */ SCC.a[chan].TxUnderrun = falseblnr; #endif #if 0 /* ZeroCount always false */ SCC.a[chan].ZeroCount = falseblnr; #endif #if 0 /* BreakAbort always false */ SCC.a[chan].BreakAbort = falseblnr; #endif break; case 3: ReportAbnormal("Send Abort (SDLC)"); #if EmLocalTalk SCC.a[chan].TxBufferEmpty = trueblnr; #endif #if 0 SCC.a[chan].TxUnderrun = trueblnr; #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif #endif break; case 4: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Enable Int on next Rx char"); #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].FirstChar = trueblnr; #endif /* happens in MacCheck */ break; case 5: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Tx Int Pending"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ SCC.a[chan].TxIP = falseblnr; CheckSCCInterruptFlag(); break; case 6: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Error Reset"); #endif /* happens on boot with appletalk on */ #if EmLocalTalk SCC.a[chan].EndOfFrame = falseblnr; #endif #if 0 /* ParityErr always false */ SCC.a[chan].ParityErr = falseblnr; #endif #if 0 /* RxOverrun always false */ SCC.a[chan].RxOverrun = falseblnr; #endif #if 0 /* CRCFramingErr always false */ SCC.a[chan].CRCFramingErr = falseblnr; #endif break; case 7: /* happens in "Network Watch" program (Cayman Systems) */ #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Highest IUS"); #endif break; case 0: default: /* Null Code */ break; } } LOCALPROC SCC_PutWR1(ui3r Data, int chan) /* "Transmit/Receive interrupt and data transfer mode definition" */ { #if EmLocalTalk || SCC_TrackMore { blnr NewExtIE = (Data & Bit0) != 0; if (SCC.a[chan].ExtIE != NewExtIE) { SCC.a[chan].ExtIE = NewExtIE; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "EXT INT Enable", NewExtIE); #endif /* set to 1 on start up, set to 0 in MacCheck and in Print to ImageWriter */ } } #endif { blnr NewTxIE = (Data & Bit1) != 0; if (SCC.a[chan].TxIE != NewTxIE) { #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Tx Int Enable", NewTxIE); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ SCC.a[chan].TxIE = NewTxIE; CheckSCCInterruptFlag(); } } #if SCC_TrackMore { blnr NewPrtySpclCond = (Data & Bit2) != 0; if (SCC.a[chan].PrtySpclCond != NewPrtySpclCond) { SCC.a[chan].PrtySpclCond = NewPrtySpclCond; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Parity is special condition", NewPrtySpclCond); #endif /* set to 1 in MacCheck and in Print to ImageWriter */ } } #endif #if EmLocalTalk || SCC_TrackMore { ui3r NewRxIntMode = (Data >> 3) & 3; if (SCC.a[chan].RxIntMode != NewRxIntMode) { SCC.a[chan].RxIntMode = NewRxIntMode; switch (NewRxIntMode) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx INT Disable"); #endif /* happens on boot always */ break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx INT on 1st char" " or special condition"); #endif SCC.a[chan].FirstChar = trueblnr; /* happens on boot with appletalk on */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "INT on all Rx char" " or special condition"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ break; case 3: ReportAbnormal( "Rx INT on special condition only"); break; } } } #endif #if SCC_TrackMore { blnr NewWaitRqstRT = (Data & Bit5) != 0; if (SCC.a[chan].WaitRqstRT != NewWaitRqstRT) { SCC.a[chan].WaitRqstRT = NewWaitRqstRT; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Wait/DMA request on receive/transmit", NewWaitRqstRT); #endif /* happens in MacCheck */ } } #endif #if SCC_TrackMore { blnr NewWaitRqstSlct = (Data & Bit6) != 0; if (SCC.a[chan].WaitRqstSlct != NewWaitRqstSlct) { SCC.a[chan].WaitRqstSlct = NewWaitRqstSlct; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Wait/DMA request function", NewWaitRqstSlct); #endif /* happens in MacCheck */ } } #endif #if SCC_TrackMore { blnr NewWaitRqstEnbl = (Data & Bit7) != 0; if (SCC.a[chan].WaitRqstEnbl != NewWaitRqstEnbl) { SCC.a[chan].WaitRqstEnbl = NewWaitRqstEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Wait/DMA request enable", NewWaitRqstEnbl); #endif /* happens in MacCheck */ } } #endif } LOCALPROC SCC_PutWR2(ui3r Data, int chan) /* "Interrupt Vector (accessed through either channel)" */ { /* Only 1 interrupt vector for the SCC, which is stored in channels A and B. B is modified when read. */ /* happens on boot always */ #if ! SCC_dolog UnusedParam(chan); #endif if (SCC.InterruptVector != Data) { #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" InterruptVector <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif SCC.InterruptVector = Data; } if ((Data & Bit0) != 0) { /* interrupt vector 0 */ ReportAbnormal("interrupt vector 0"); } if ((Data & Bit1) != 0) { /* interrupt vector 1 */ ReportAbnormal("interrupt vector 1"); } if ((Data & Bit2) != 0) { /* interrupt vector 2 */ ReportAbnormal("interrupt vector 2"); } if ((Data & Bit3) != 0) { /* interrupt vector 3 */ ReportAbnormal("interrupt vector 3"); } if ((Data & Bit4) != 0) { /* interrupt vector 4 */ /* happens on boot with appletalk on */ } if ((Data & Bit5) != 0) { /* interrupt vector 5 */ /* happens on boot with appletalk on */ } if ((Data & Bit6) != 0) { /* interrupt vector 6 */ ReportAbnormal("interrupt vector 6"); } if ((Data & Bit7) != 0) { /* interrupt vector 7 */ ReportAbnormal("interrupt vector 7"); } } LOCALPROC SCC_PutWR3(ui3r Data, int chan) /* "Receive parameters and control" */ { #if SCC_TrackMore { ui3r NewRBitsPerChar = (Data >> 6) & 3; if (SCC.a[chan].RBitsPerChar != NewRBitsPerChar) { SCC.a[chan].RBitsPerChar = NewRBitsPerChar; switch (NewRBitsPerChar) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 5"); #endif break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 7"); #endif break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 6"); #endif break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 8"); #endif break; } } } #endif if ((Data & Bit5) != 0) { /* Auto Enables */ /* use DCD input as receiver enable, and set RTS output when transmit buffer empty */ ReportAbnormal("Auto Enables"); } if ((Data & Bit4) != 0) { /* Enter Hunt Mode */ #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Enter Hunt Mode"); #endif /* happens on boot with appletalk on */ if (! (SCC.a[chan].SyncHunt)) { SCC.a[chan].SyncHunt = trueblnr; #if 0 /* SyncHuntIE usually false */ if (SCC.a[chan].SyncHuntIE) { SCC_Interrupt((chan == 0) ? SCC_A_Ext : SCC_B_Ext); } #endif } } #if SCC_TrackMore { blnr NewRxCRCEnbl = (Data & Bit3) != 0; if (SCC.a[chan].RxCRCEnbl != NewRxCRCEnbl) { SCC.a[chan].RxCRCEnbl = NewRxCRCEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Rx CRC Enable", NewRxCRCEnbl); #endif /* happens on boot with appletalk on */ } } #endif #if EmLocalTalk || SCC_TrackMore { blnr NewAddrSrchMd = (Data & Bit2) != 0; if (SCC.a[chan].AddrSrchMd != NewAddrSrchMd) { SCC.a[chan].AddrSrchMd = NewAddrSrchMd; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Addr Search Mode (SDLC)", NewAddrSrchMd); #endif /* happens on boot with appletalk on */ } } #endif #if SCC_TrackMore { blnr NewSyncChrLdInhb = (Data & Bit1) != 0; if (SCC.a[chan].SyncChrLdInhb != NewSyncChrLdInhb) { SCC.a[chan].SyncChrLdInhb = NewSyncChrLdInhb; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Sync Char Load Inhibit", NewSyncChrLdInhb); #endif /* happens on boot with appletalk on */ } } #endif { blnr NewRxEnable = (Data & Bit0) != 0; if (SCC.a[chan].RxEnable != NewRxEnable) { SCC.a[chan].RxEnable = NewRxEnable; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Rx Enable", NewRxEnable); #endif /* true on boot with appletalk on */ /* true on Print to ImageWriter */ #if EmLocalTalk if (! NewRxEnable) { #if SCC_dolog if ((0 != chan) && (nullpr != LT_RxBuffer)) { dbglog_WriteNote("SCC abandon packet"); } #endif /* Go back into the idle state if we were waiting for EOF */ SCC.a[chan].EndOfFrame = falseblnr; SCC.a[chan].RxChrAvail = falseblnr; SCC.a[chan].SyncHunt = trueblnr; } else { /* look for a packet */ LocalTalkTick(); } #endif } } } LOCALPROC SCC_PutWR4(ui3r Data, int chan) /* "Transmit/Receive miscellaneous parameters and modes" */ { #if ! (EmLocalTalk || SCC_TrackMore) UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore { blnr NewPrtyEnable = (Data & Bit0) != 0; if (SCC.a[chan].PrtyEnable != NewPrtyEnable) { SCC.a[chan].PrtyEnable = NewPrtyEnable; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Parity Enable", NewPrtyEnable); #endif } } #endif #if SCC_TrackMore { blnr NewPrtyEven = (Data & Bit1) != 0; if (SCC.a[chan].PrtyEven != NewPrtyEven) { SCC.a[chan].PrtyEven = NewPrtyEven; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Parity Enable", NewPrtyEven); #endif } } #endif #if SCC_TrackMore { ui3r NewStopBits = (Data >> 2) & 3; if (SCC.a[chan].StopBits != NewStopBits) { SCC.a[chan].StopBits = NewStopBits; /* SCC_SetStopBits(chan, NewStopBits); */ switch (NewStopBits) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Sync Modes Enable"); #endif break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "1 Stop Bit"); #endif break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "1 1/2 Stop Bits"); #endif break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "2 Stop Bits"); #endif break; } } } #endif #if EmLocalTalk || SCC_TrackMore { ui3r NewSyncMode = (Data >> 4) & 3; if (SCC.a[chan].SyncMode != NewSyncMode) { SCC.a[chan].SyncMode = NewSyncMode; switch (NewSyncMode) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "8 bit sync char"); #endif /* happens on boot always */ break; case 1: ReportAbnormal("16 bit sync char"); break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "SDLC MODE"); #endif /* happens on boot with appletalk on */ #if EmLocalTalk SCC.a[chan].TxBufferEmpty = trueblnr; #endif break; case 3: ReportAbnormal("External sync mode"); break; } } } #endif #if SCC_TrackMore { ui3r NewClockRate = (Data >> 6) & 3; if (SCC.a[chan].ClockRate != NewClockRate) { SCC.a[chan].ClockRate = NewClockRate; switch (NewClockRate) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Clock Rate <- X1"); #endif /* happens on boot with appletalk on */ break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Clock Rate <- X16"); #endif /* happens on boot always */ break; case 2: ReportAbnormal("Clock Rate <- X32"); break; case 3: ReportAbnormal("Clock Rate <- X64"); break; } } } #endif } LOCALPROC SCC_PutWR5(ui3r Data, int chan) /* "Transmit parameters and controls" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if SCC_TrackMore { blnr NewTxCRCEnbl = (Data & Bit0) != 0; if (SCC.a[chan].TxCRCEnbl != NewTxCRCEnbl) { SCC.a[chan].TxCRCEnbl = NewTxCRCEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Tx CRC Enable", NewTxCRCEnbl); #endif /* both values on boot with appletalk on */ } } #endif #if SCC_TrackMore { blnr NewRTSctrl = (Data & Bit1) != 0; if (SCC.a[chan].RTSctrl != NewRTSctrl) { SCC.a[chan].RTSctrl = NewRTSctrl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "RTS Control", NewRTSctrl); #endif /* both values on boot with appletalk on */ /* value of Request To Send output pin, when Auto Enable is off */ } } #endif if ((Data & Bit2) != 0) { /* SDLC/CRC-16 */ ReportAbnormal("SDLC/CRC-16"); } { blnr NewTxEnable = (Data & Bit3) != 0; if (SCC.a[chan].TxEnable != NewTxEnable) { SCC.a[chan].TxEnable = NewTxEnable; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Tx Enable", NewTxEnable); #endif if (NewTxEnable) { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if EmLocalTalk LT_TxBuffSz = 0; #endif } else { #if EmLocalTalk SCC.a[chan].TxBufferEmpty = trueblnr; #endif } } } #if SCC_TrackMore { blnr NewSndBrkCtrl = (Data & Bit4) != 0; if (SCC.a[chan].SndBrkCtrl != NewSndBrkCtrl) { SCC.a[chan].SndBrkCtrl = NewSndBrkCtrl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Send Break Control", NewSndBrkCtrl); #endif /* true in Print to LaserWriter 300 */ } } #endif #if SCC_TrackMore { ui3r NewTBitsPerChar = (Data >> 5) & 3; if (SCC.a[chan].TBitsPerChar != NewTBitsPerChar) { SCC.a[chan].TBitsPerChar = NewTBitsPerChar; switch (NewTBitsPerChar) { case 0: ReportAbnormal("Tx Bits/Character <- 5"); break; case 1: ReportAbnormal("Tx Bits/Character <- 7"); break; case 2: ReportAbnormal("Tx Bits/Character <- 6"); break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Tx Bits/Character <- 8"); #endif /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ break; } } } #endif #if SCC_TrackMore { blnr NewDTRctrl = (Data & Bit7) != 0; if (SCC.a[chan].DTRctrl != NewDTRctrl) { SCC.a[chan].DTRctrl = NewDTRctrl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Data Terminal Ready Control", NewDTRctrl); #endif /* zero happens in MacCheck */ /* value of Data Terminal Ready output pin, when WR14 D2 = 0 (DTR/request function) */ } } #endif } LOCALPROC SCC_PutWR6(ui3r Data, int chan) /* "Sync characters or SDLC address field" */ { /* happens on boot with appletalk on */ #if ! (EmLocalTalk || SCC_dolog) UnusedParam(Data); #endif #if ! SCC_dolog UnusedParam(chan); #endif #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" Sync Char <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif #if EmLocalTalk if (0 != Data) { my_node_address = Data; } #endif } LOCALPROC SCC_PutWR7(ui3r Data, int chan) /* "Sync character or SDLC flag" */ { /* happens on boot with appletalk on */ #if ! SCC_TrackMore UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore if (2 == SCC.a[chan].SyncMode) { if (0x7E != Data) { ReportAbnormal( "unexpect flag character for SDLC"); } } else { ReportAbnormal("WR7 and not SDLC"); } #endif } LOCALPROC SCC_PutWR8(ui3r Data, int chan) /* "Transmit Buffer" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! (EmLocalTalk || SCC_dolog) UnusedParam(Data); #endif #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" Transmit Buffer"); dbglog_writeCStr(" <- "); dbglog_writeHex(Data); dbglog_writeCStr(" '"); dbglog_writeMacChar(Data); dbglog_writeCStr("'"); dbglog_writeReturn(); #endif if (SCC.a[chan].TxEnable) { /* Tx Enable */ /* Output (Data) to Modem(B) or Printer(A) Port */ /* happens on boot with appletalk on */ #if EmLocalTalk if (chan != 0) { SCC_TxBuffPut(Data); } #else #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif SCC.a[chan].TxUnderrun = trueblnr; /* underrun ? */ #endif SCC.a[chan].TxIP = trueblnr; CheckSCCInterruptFlag(); } else { ReportAbnormal( "write when Transmit Buffer not Enabled"); #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = falseblnr; #endif } } LOCALPROC SCC_PutWR9(ui3r Data, int chan) /* "Master interrupt control and reset (accessed through either channel)" */ { /* Only 1 WR9 in the SCC */ UnusedParam(chan); if ((Data & Bit0) != 0) { /* VIS */ ReportAbnormal("VIS"); } #if SCC_TrackMore { blnr NewNoVectorSlct = (Data & Bit1) != 0; if (SCC.NoVectorSlct != NewNoVectorSlct) { SCC.NoVectorSlct = NewNoVectorSlct; #if SCC_dolog dbglog_WriteSetBool("SCC No Vector select", NewNoVectorSlct); #endif /* has both values on boot always */ } } #endif if ((Data & Bit2) != 0) { /* DLC */ ReportAbnormal("DLC"); } { blnr NewMIE = (Data & Bit3) != 0; /* has both values on boot always */ if (SCC.MIE != NewMIE) { SCC.MIE = NewMIE; #if SCC_dolog dbglog_WriteSetBool("SCC Master Interrupt Enable", NewMIE); #endif CheckSCCInterruptFlag(); } } #if 0 /* StatusHiLo always false */ SCC.StatusHiLo = (Data & Bit4) != 0; #else if ((Data & Bit4) != 0) { /* Status high/low */ ReportAbnormal("Status high/low"); } #endif if ((Data & Bit5) != 0) { /* WR9 b5 should be 0 */ ReportAbnormal("WR9 b5 should be 0"); } switch ((Data >> 6) & 3) { case 1: #if SCC_dolog SCC_DbgLogChanCmnd(1, "Channel Reset"); #endif /* happens on boot always */ SCC_ResetChannel(1); CheckSCCInterruptFlag(); break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(0, "Channel Reset"); #endif /* happens on boot always */ SCC_ResetChannel(0); CheckSCCInterruptFlag(); break; case 3: #if SCC_dolog dbglog_WriteNote("SCC Force Hardware Reset"); #endif #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormal("SCC_Reset"); #endif SCC_Reset(); CheckSCCInterruptFlag(); break; case 0: /* No Reset */ default: break; } } LOCALPROC SCC_PutWR10(ui3r Data, int chan) /* "Miscellaneous transmitter/receiver control bits" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! SCC_TrackMore UnusedParam(chan); #endif if ((Data & Bit0) != 0) { /* 6 bit/8 bit sync */ ReportAbnormal("6 bit/8 bit sync"); } if ((Data & Bit1) != 0) { /* loop mode */ ReportAbnormal("loop mode"); } if ((Data & Bit2) != 0) { /* abort/flag on underrun */ ReportAbnormal("abort/flag on underrun"); } if ((Data & Bit3) != 0) { /* mark/flag idle */ ReportAbnormal("mark/flag idle"); } if ((Data & Bit4) != 0) { /* go active on poll */ ReportAbnormal("go active on poll"); } #if SCC_TrackMore { ui3r NewDataEncoding = (Data >> 5) & 3; if (SCC.a[chan].DataEncoding != NewDataEncoding) { SCC.a[chan].DataEncoding = NewDataEncoding; switch (NewDataEncoding) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Data Encoding <- NRZ"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ break; case 1: ReportAbnormal("Data Encoding <- NRZI"); break; case 2: ReportAbnormal("Data Encoding <- FM1"); break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Data Encoding <- FM0"); #endif /* happens on boot with appletalk on */ break; } } } #endif #if SCC_TrackMore { blnr NewCRCPreset = (Data & Bit7) != 0; if (SCC.a[chan].CRCPreset != NewCRCPreset) { SCC.a[chan].CRCPreset = NewCRCPreset; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "CRC preset I/O", NewCRCPreset); #endif /* false happens in MacCheck */ /* true happens in Print to ImageWriter */ } } #endif } LOCALPROC SCC_PutWR11(ui3r Data, int chan) /* "Clock mode control" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ /* happens in MacCheck */ #if ! SCC_TrackMore UnusedParam(chan); #endif #if SCC_TrackMore /* Transmit External Control Selection */ { ui3r NewTRxCsrc = Data & 3; if (SCC.a[chan].TRxCsrc != NewTRxCsrc) { SCC.a[chan].TRxCsrc = NewTRxCsrc; switch (NewTRxCsrc) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "TRxC OUT = XTAL output"); #endif /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ /* happens in MacCheck */ break; case 1: ReportAbnormal("TRxC OUT = transmit clock"); break; case 2: ReportAbnormal( "TRxC OUT = BR generator output"); break; case 3: ReportAbnormal("TRxC OUT = dpll output"); break; } } } #endif if ((Data & Bit2) != 0) { ReportAbnormal("TRxC O/I"); } #if SCC_TrackMore { ui3r NewTClkSlct = (Data >> 3) & 3; if (SCC.a[chan].TClkSlct != NewTClkSlct) { SCC.a[chan].TClkSlct = NewTClkSlct; switch (NewTClkSlct) { case 0: ReportAbnormal("transmit clock = RTxC pin"); break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "transmit clock = TRxC pin"); #endif /* happens in Print to LaserWriter 300 */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "transmit clock = BR generator output"); #endif /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ /* happens in MacCheck */ break; case 3: ReportAbnormal( "transmit clock = dpll output"); break; } } } #endif #if SCC_TrackMore { ui3r NewRClkSlct = (Data >> 5) & 3; if (SCC.a[chan].RClkSlct != NewRClkSlct) { SCC.a[chan].RClkSlct = NewRClkSlct; switch (NewRClkSlct) { case 0: ReportAbnormal("receive clock = RTxC pin"); break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "receive clock = TRxC pin"); #endif /* happens in Print to LaserWriter 300 */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "receive clock = BR generator output"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "receive clock = dpll output"); #endif /* happens on boot with appletalk on */ break; } } } #endif if ((Data & Bit7) != 0) { ReportAbnormal("RTxC XTAL/NO XTAL"); } } LOCALPROC SCC_PutWR12(ui3r Data, int chan) /* "Lower byte of baud rate generator time constant" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! SCC_TrackMore UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore /* don't care about Baud */ if (SCC.a[chan].BaudLo != Data) { SCC.a[chan].BaudLo = Data; #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" BaudLo <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif } #endif #if 0 SCC_SetBaud(chan, SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); /* 380: BaudRate = 300 */ /* 94: BaudRate = 1200 */ /* 46: BaudRate = 2400 */ /* 22: BaudRate = 4800 */ /* 10: BaudRate = 9600 */ /* 4: BaudRate = 19200 */ /* 1: BaudRate = 38400 */ /* 0: BaudRate = 57600 */ #endif } LOCALPROC SCC_PutWR13(ui3r Data, int chan) /* "Upper byte of baud rate generator time constant" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! SCC_TrackMore UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore /* don't care about Baud */ if (SCC.a[chan].BaudHi != Data) { SCC.a[chan].BaudHi = Data; #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" BaudHi <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif } #endif #if 0 SCC_SetBaud(chan, SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); #endif } LOCALPROC SCC_PutWR14(ui3r Data, int chan) /* "Miscellaneous control bits" */ { /* happens on boot with appletalk on */ #if ! (SCC_TrackMore || SCC_dolog) UnusedParam(chan); #endif #if SCC_TrackMore { blnr NewBRGEnbl = (Data & Bit0) != 0; if (SCC.a[chan].BRGEnbl != NewBRGEnbl) { SCC.a[chan].BRGEnbl = NewBRGEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "BR generator enable", NewBRGEnbl); #endif /* both values on boot with appletalk on */ /* true happens in Print to ImageWriter */ } } #endif if ((Data & Bit1) != 0) { /* BR generator source */ ReportAbnormal("BR generator source"); } if ((Data & Bit2) != 0) { /* DTR/request function */ ReportAbnormal("DTR/request function"); } if ((Data & Bit3) != 0) { /* auto echo */ ReportAbnormal("auto echo"); } if ((Data & Bit4) != 0) { /* local loopback */ ReportAbnormal("local loopback"); } switch ((Data >> 5) & 7) { case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "enter search mode"); #endif /* happens on boot with appletalk on */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "reset missing clock"); #endif /* happens on boot with appletalk on */ /* should clear Bit 6 and Bit 7 of RR[10], but since these are never set, don't need to do anything */ break; case 3: ReportAbnormal("disable dpll"); /* should clear Bit 6 and Bit 7 of RR[10], but since these are never set, don't need to do anything */ break; case 4: ReportAbnormal("set source = br generator"); break; case 5: ReportAbnormal("set source = RTxC"); break; case 6: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "set FM mode"); #endif /* happens on boot with appletalk on */ break; case 7: ReportAbnormal("set NRZI mode"); break; case 0: /* No Reset */ default: break; } } LOCALPROC SCC_PutWR15(ui3r Data, int chan) /* "External/Status interrupt control" */ { /* happens on boot always */ #if ! SCC_TrackMore UnusedParam(chan); #endif if ((Data & Bit0) != 0) { /* WR15 b0 should be 0 */ ReportAbnormal("WR15 b0 should be 0"); } if ((Data & Bit1) != 0) { /* zero count IE */ ReportAbnormal("zero count IE"); } if ((Data & Bit2) != 0) { /* WR15 b2 should be 0 */ ReportAbnormal("WR15 b2 should be 0"); } #if 0 /* don't care about DCD_IE, always true */ SCC.a[chan].DCD_IE = (Data & Bit3) != 0; #else if ((Data & Bit3) == 0) { /* DCD_IE */ #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormal("not DCD IE"); #endif } #endif #if 0 /* SyncHuntIE usually false */ SCC.a[chan].SyncHuntIE = (Data & Bit4) != 0; #else if ((Data & Bit4) != 0) { /* SYNC/HUNT IE */ ReportAbnormal("SYNC/HUNT IE"); } #endif #if SCC_TrackMore /* don't care about CTS_IE */ { blnr NewCTS_IE = (Data & Bit5) != 0; if (SCC.a[chan].CTS_IE != NewCTS_IE) { SCC.a[chan].CTS_IE = NewCTS_IE; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "CTS IE", NewCTS_IE); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ } } #endif if ((Data & Bit6) != 0) { /* Tx underrun/EOM IE */ ReportAbnormal("Tx underrun/EOM IE"); } #if SCC_TrackMore { blnr NewBreakAbortIE = (Data & Bit7) != 0; if (SCC.a[chan].BreakAbortIE != NewBreakAbortIE) { SCC.a[chan].BreakAbortIE = NewBreakAbortIE; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "BreakAbort IE", NewBreakAbortIE); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ } } #endif } LOCALFUNC ui3r SCC_GetReg(int chan, ui3r SCC_Reg) { ui3r value; switch (SCC_Reg) { case 0: value = SCC_GetRR0(chan); break; case 1: value = SCC_GetRR1(chan); break; case 2: value = SCC_GetRR2(chan); break; case 3: value = SCC_GetRR3(chan); break; case 4: ReportAbnormal("RR 4"); /* same as RR0 */ value = SCC_GetRR0(chan); break; case 5: ReportAbnormal("RR 5"); /* same as RR1 */ value = SCC_GetRR1(chan); break; case 6: ReportAbnormal("RR 6"); /* same as RR2 */ value = SCC_GetRR2(chan); break; case 7: ReportAbnormal("RR 7"); /* same as RR3 */ value = SCC_GetRR3(chan); break; case 8: value = SCC_GetRR8(chan); break; case 9: ReportAbnormal("RR 9"); /* same as RR13 */ value = SCC_GetRR13(chan); break; case 10: value = SCC_GetRR10(chan); break; case 11: ReportAbnormal("RR 11"); /* same as RR15 */ value = SCC_GetRR15(chan); break; case 12: value = SCC_GetRR12(chan); break; case 13: value = SCC_GetRR13(chan); break; case 14: ReportAbnormal("RR 14"); value = 0; break; case 15: value = SCC_GetRR15(chan); break; default: ReportAbnormal("unexpected SCC_Reg in SCC_GetReg"); value = 0; break; } #if EmLocalTalk /* Always check to see if interrupt state changed after ANY register access */ CheckSCCInterruptFlag(); #endif #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" RR["); dbglog_writeHex(SCC_Reg); dbglog_writeCStr("] -> "); dbglog_writeHex(value); dbglog_writeReturn(); #endif return value; } LOCALPROC SCC_PutReg(ui3r Data, int chan, ui3r SCC_Reg) { #if SCC_dolog && 0 SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" WR["); dbglog_writeHex(SCC_Reg); dbglog_writeCStr("] <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif switch (SCC_Reg) { case 0: SCC_PutWR0(Data, chan); break; case 1: SCC_PutWR1(Data, chan); break; case 2: SCC_PutWR2(Data, chan); break; case 3: SCC_PutWR3(Data, chan); break; case 4: SCC_PutWR4(Data, chan); break; case 5: SCC_PutWR5(Data, chan); break; case 6: SCC_PutWR6(Data, chan); break; case 7: SCC_PutWR7(Data, chan); break; case 8: SCC_PutWR8(Data, chan); break; case 9: SCC_PutWR9(Data, chan); break; case 10: SCC_PutWR10(Data, chan); break; case 11: SCC_PutWR11(Data, chan); break; case 12: SCC_PutWR12(Data, chan); break; case 13: SCC_PutWR13(Data, chan); break; case 14: SCC_PutWR14(Data, chan); break; case 15: SCC_PutWR15(Data, chan); break; default: ReportAbnormal("unexpected SCC_Reg in SCC_PutReg"); break; } #if EmLocalTalk /* Always check to see if interrupt state changed after ANY register access */ CheckSCCInterruptFlag(); #endif } GLOBALFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr) { #if EmLocalTalk /* Determine channel, data, and access type from address. The bus for the 8350 is non-standard, so the Macintosh connects address bus lines to various signals on the 8350 as shown below. The 68K will use the upper byte of the data bus for odd addresses, and the 8350 is only wired to the upper byte, therefore use only odd addresses or you risk resetting the 8350. 68k 8350 ----- ------ a1 a/b a2 d/c a21 wr/rd */ #endif ui3b SCC_Reg; int chan = (~ addr) & 1; /* 0=modem, 1=printer */ if (((addr >> 1) & 1) == 0) { /* Channel Control */ SCC_Reg = SCC.PointerBits; SCC.PointerBits = 0; } else { /* Channel Data */ SCC_Reg = 8; } if (WriteMem) { SCC_PutReg(Data, chan, SCC_Reg); } else { Data = SCC_GetReg(chan, SCC_Reg); } return Data; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCCEMDEV.h b/Mini vMac/mnvm_core/SCCEMDEV.h new file mode 100755 index 0000000..aaeb59e --- /dev/null +++ b/Mini vMac/mnvm_core/SCCEMDEV.h @@ -0,0 +1 @@ +/* SCCEMDEV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef SCCEMDEV_H #error "header already included" #else #define SCCEMDEV_H #endif EXPORTPROC SCC_Reset(void); EXPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr); EXPORTFUNC blnr SCC_InterruptsEnabled(void); #if EmLocalTalk EXPORTPROC LocalTalkTick(void); EXPORTFUNC int InitLocalTalk(void); #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNEMDV.c b/Mini vMac/mnvm_core/SCRNEMDV.c new file mode 100755 index 0000000..367201d --- /dev/null +++ b/Mini vMac/mnvm_core/SCRNEMDV.c @@ -0,0 +1 @@ +/* SCRNEMDV.c Copyright (C) 2006 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* SCReeN EMulated DeVice Emulation of the screen in the Mac Plus. This code descended from "Screen-MacOS.c" in Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "SCRNEMDV.h" #if ! IncludeVidMem #define kMain_Offset 0x5900 #define kAlternate_Offset 0xD900 #define kMain_Buffer (kRAM_Size - kMain_Offset) #define kAlternate_Buffer (kRAM_Size - kAlternate_Offset) #endif GLOBALPROC Screen_EndTickNotify(void) { ui3p screencurrentbuff; #if IncludeVidMem screencurrentbuff = VidMem; #else if (SCRNvPage2 == 1) { screencurrentbuff = get_ram_address(kMain_Buffer); } else { screencurrentbuff = get_ram_address(kAlternate_Buffer); } #endif Screen_OutputFrame(screencurrentbuff); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNEMDV.h b/Mini vMac/mnvm_core/SCRNEMDV.h new file mode 100755 index 0000000..f005f54 --- /dev/null +++ b/Mini vMac/mnvm_core/SCRNEMDV.h @@ -0,0 +1 @@ +/* SCRNEMDV.h Copyright (C) 2006 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef SCRNEMDV_H #error "header already included" #else #define SCRNEMDV_H #endif EXPORTPROC Screen_EndTickNotify(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNMAPR.h b/Mini vMac/mnvm_core/SCRNMAPR.h new file mode 100755 index 0000000..d699f55 --- /dev/null +++ b/Mini vMac/mnvm_core/SCRNMAPR.h @@ -0,0 +1 @@ +/* SCRNMAPR.h Copyright (C) 2012 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* SCReeN MAPpeR */ /* required arguments for this template */ #ifndef ScrnMapr_DoMap /* procedure to be created by this template */ #error "ScrnMapr_DoMap not defined" #endif #ifndef ScrnMapr_Src #error "ScrnMapr_Src not defined" #endif #ifndef ScrnMapr_Dst #error "ScrnMapr_Dst not defined" #endif #ifndef ScrnMapr_SrcDepth #error "ScrnMapr_SrcDepth not defined" #endif #ifndef ScrnMapr_DstDepth #error "ScrnMapr_DstDepth not defined" #endif #ifndef ScrnMapr_Map #error "ScrnMapr_Map not defined" #endif /* optional argument for this template */ #ifndef ScrnMapr_Scale #define ScrnMapr_Scale 1 #endif /* check of parameters */ #if (ScrnMapr_SrcDepth < 0) || (ScrnMapr_SrcDepth > 3) #error "bad ScrnMapr_SrcDepth" #endif #if (ScrnMapr_DstDepth < ScrnMapr_SrcDepth) #error "bad ScrnMapr_Dst" #endif /* calculate a few things local to this template */ #define ScrnMapr_MapElSz \ (ScrnMapr_Scale << (ScrnMapr_DstDepth - ScrnMapr_SrcDepth)) #if 0 == (ScrnMapr_MapElSz & 3) #define ScrnMapr_TranT ui5b #define ScrnMapr_TranLn2Sz 2 #elif 0 == (ScrnMapr_MapElSz & 1) #define ScrnMapr_TranT ui4b #define ScrnMapr_TranLn2Sz 1 #else #define ScrnMapr_TranT ui3b #define ScrnMapr_TranLn2Sz 0 #endif #define ScrnMapr_TranN (ScrnMapr_MapElSz >> ScrnMapr_TranLn2Sz) #define ScrnMapr_ScrnWB (vMacScreenWidth >> (3 - ScrnMapr_SrcDepth)) /* now define the procedure */ LOCALPROC ScrnMapr_DoMap(si4b top, si4b left, si4b bottom, si4b right) { int i; int j; #if (ScrnMapr_TranN > 4) || (ScrnMapr_Scale > 2) int k; #endif ui5r t0; ScrnMapr_TranT *pMap; #if ScrnMapr_Scale > 1 ScrnMapr_TranT *p3; #endif ui4r leftB = left >> (3 - ScrnMapr_SrcDepth); ui4r rightB = (right + (1 << (3 - ScrnMapr_SrcDepth)) - 1) >> (3 - ScrnMapr_SrcDepth); ui4r jn = rightB - leftB; ui4r SrcSkip = ScrnMapr_ScrnWB - jn; ui3b *pSrc = ((ui3b *)ScrnMapr_Src) + leftB + ScrnMapr_ScrnWB * (ui5r)top; ScrnMapr_TranT *pDst = ((ScrnMapr_TranT *)ScrnMapr_Dst) + ((leftB + ScrnMapr_ScrnWB * ScrnMapr_Scale * (ui5r)top) * ScrnMapr_TranN); ui5r DstSkip = SrcSkip * ScrnMapr_TranN; for (i = bottom - top; --i >= 0; ) { #if ScrnMapr_Scale > 1 p3 = pDst; #endif for (j = jn; --j >= 0; ) { t0 = *pSrc++; pMap = &((ScrnMapr_TranT *)ScrnMapr_Map)[t0 * ScrnMapr_TranN]; #if ScrnMapr_TranN > 4 for (k = ScrnMapr_TranN; --k >= 0; ) { *pDst++ = *pMap++; } #else #if ScrnMapr_TranN >= 2 *pDst++ = *pMap++; #endif #if ScrnMapr_TranN >= 3 *pDst++ = *pMap++; #endif #if ScrnMapr_TranN >= 4 *pDst++ = *pMap++; #endif *pDst++ = *pMap; #endif /* ! ScrnMapr_TranN > 4 */ } pSrc += SrcSkip; pDst += DstSkip; #if ScrnMapr_Scale > 1 #if ScrnMapr_Scale > 2 for (k = ScrnMapr_Scale - 1; --k >= 0; ) #endif { pMap = p3; for (j = ScrnMapr_TranN * jn; --j >= 0; ) { *pDst++ = *pMap++; } pDst += DstSkip; } #endif /* ScrnMapr_Scale > 1 */ } } /* undefine template locals and parameters */ #undef ScrnMapr_ScrnWB #undef ScrnMapr_TranN #undef ScrnMapr_TranLn2Sz #undef ScrnMapr_TranT #undef ScrnMapr_MapElSz #undef ScrnMapr_DoMap #undef ScrnMapr_Src #undef ScrnMapr_Dst #undef ScrnMapr_SrcDepth #undef ScrnMapr_DstDepth #undef ScrnMapr_Map #undef ScrnMapr_Scale \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCSIEMDV.c b/Mini vMac/mnvm_core/SCSIEMDV.c new file mode 100755 index 0000000..21e78d4 --- /dev/null +++ b/Mini vMac/mnvm_core/SCSIEMDV.c @@ -0,0 +1 @@ +/* SCSIEMDV.c Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Small Computer System Interface EMulated DeVice Emulates the SCSI found in the Mac Plus. This code adapted from "SCSI.c" in vMac by Philip Cummins. */ /* NCR5380 chip emulation by Yoav Shadmi, 1998 */ #ifndef AllFiles #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "SCSIEMDV.h" #define scsiRd 0x00 #define scsiWr 0x01 #define sCDR 0x00 /* current scsi data register (r/o) */ #define sODR 0x00 /* output data register (w/o) */ #define sICR 0x02 /* initiator command register (r/w) */ #define sMR 0x04 /* mode register (r/w) */ #define sTCR 0x06 /* target command register (r/w) */ #define sCSR 0x08 /* current SCSI bus status (r/o) */ #define sSER 0x08 /* select enable register (w/o) */ #define sBSR 0x0A /* bus and status register (r/o) */ #define sDMAtx 0x0A /* start DMA send (w/o) */ #define sIDR 0x0C /* input data register (r/o) */ #define sTDMArx 0x0C /* start DMA target receive (w/o) */ #define sRESET 0x0E /* reset parity/interrupt (r/o) */ #define sIDMArx 0x0E /* start DMA initiator receive (w/o) */ #define kSCSI_Size 0x00010 LOCALVAR ui3b SCSI[kSCSI_Size]; GLOBALPROC SCSI_Reset(void) { int i; for (i = 0; i < kSCSI_Size; i++) { SCSI[i] = 0; } } LOCALPROC SCSI_BusReset(void) { SCSI[scsiRd + sCDR] = 0; SCSI[scsiWr + sODR] = 0; SCSI[scsiRd + sICR] = 0x80; SCSI[scsiWr + sICR] &= 0x80; SCSI[scsiRd + sMR] &= 0x40; SCSI[scsiWr + sMR] &= 0x40; SCSI[scsiRd + sTCR] = 0; SCSI[scsiWr + sTCR] = 0; SCSI[scsiRd + sCSR] = 0x80; SCSI[scsiWr + sSER] = 0; SCSI[scsiRd + sBSR] = 0x10; SCSI[scsiWr + sDMAtx] = 0; SCSI[scsiRd + sIDR] = 0; SCSI[scsiWr + sTDMArx] = 0; SCSI[scsiRd + sRESET] = 0; SCSI[scsiWr + sIDMArx] = 0; #if 0 SCSI[scsiRd + sODR + dackWr] = 0; SCSI[scsiWr + sIDR + dackRd] = 0; #endif /* The missing piece of the puzzle.. :) */ put_ram_word(0xb22, get_ram_word(0xb22) | 0x8000); } LOCALPROC SCSI_Check(void) { /* The arbitration select/reselect scenario [stub.. doesn't really work...] */ if ((SCSI[scsiWr + sODR] >> 7) == 1) { /* Check if the Mac tries to be an initiator */ if ((SCSI[scsiWr + sMR] & 1) == 1) { /* the Mac set arbitration in progress */ /* stub! tell the mac that there is arbitration in progress... */ SCSI[scsiRd + sICR] |= 0x40; /* ... that we didn't lose arbitration ... */ SCSI[scsiRd + sICR] &= ~ 0x20; /* ... and that there isn't a higher priority ID present... */ SCSI[scsiRd + sCDR] = 0x00; /* ... the arbitration and selection/reselection is complete. the initiator tries to connect to the SCSI device, fails and returns after timeout. */ } } /* check the chip registers, AS SET BY THE CPU */ if ((SCSI[scsiWr + sICR] >> 7) == 1) { /* Check Assert RST */ SCSI_BusReset(); } else { SCSI[scsiRd + sICR] &= ~ 0x80; SCSI[scsiRd + sCSR] &= ~ 0x80; } if ((SCSI[scsiWr + sICR] >> 2) == 1) { /* Check Assert SEL */ SCSI[scsiRd + sCSR] |= 0x02; SCSI[scsiRd + sBSR] = 0x10; } else { SCSI[scsiRd + sCSR] &= ~ 0x02; } } GLOBALFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr) { if (addr < (kSCSI_Size / 2)) { addr *= 2; if (WriteMem) { SCSI[addr + 1] = Data; SCSI_Check(); } else { Data = SCSI[addr]; } } return Data; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCSIEMDV.h b/Mini vMac/mnvm_core/SCSIEMDV.h new file mode 100755 index 0000000..b189024 --- /dev/null +++ b/Mini vMac/mnvm_core/SCSIEMDV.h @@ -0,0 +1 @@ +/* SCSIEMDV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef SCSIEMDV_H #error "header already included" #else #define SCSIEMDV_H #endif EXPORTPROC SCSI_Reset(void); EXPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SNDEMDEV.c b/Mini vMac/mnvm_core/SNDEMDEV.c new file mode 100755 index 0000000..5d2a877 --- /dev/null +++ b/Mini vMac/mnvm_core/SNDEMDEV.c @@ -0,0 +1 @@ +/* SNDEMDEV.c Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* SouND EMulated DEVice Emulation of Sound in the Mac Plus could go here. This code adapted from "Sound.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "SNDEMDEV.h" #if MySoundEnabled #define kSnd_Main_Offset 0x0300 #define kSnd_Alt_Offset 0x5F00 #define kSnd_Main_Buffer (kRAM_Size - kSnd_Main_Offset) #define kSnd_Alt_Buffer (kRAM_Size - kSnd_Alt_Offset) /* approximate volume levels of vMac, so: x * vol_mult[SoundVolume] >> 16 + vol_offset[SoundVolume] = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound; */ LOCALVAR const ui4b vol_mult[] = { 8192, 9362, 10922, 13107, 16384, 21845, 32768 }; LOCALVAR const trSoundSamp vol_offset[] = { #if 3 == kLn2SoundSampSz 112, 110, 107, 103, 96, 86, 64, 0 #elif 4 == kLn2SoundSampSz 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0 #else #error "unsupported kLn2SoundSampSz" #endif }; LOCALVAR const ui4b SubTick_offset[kNumSubTicks] = { 0, 25, 50, 90, 102, 115, 138, 161, 185, 208, 231, 254, 277, 300, 323, 346 }; LOCALVAR const ui3r SubTick_n[kNumSubTicks] = { 25, 25, 40, 12, 13, 23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 24 }; /* One version of free form sound driver spends around 18000 cycles writing offsets 50 to 370, then around another 3000 cycles writing 0 to 50. So be done with 0 to 50 at end of second sixtieth. */ /* Different in system 6.0.4: spends around 23500 cycles writing offsets 90 to 370, then around another 7500 cycles writing 0 to 90. This is nastier, because gets to be a very small gap between where is being read and where written. So read a bit in advance for third subtick. */ /* startup sound spends around 19500 cycles writing offsets 0 to 370. presumably writing offset 0 before it is read. */ LOCALVAR ui5b SoundInvertPhase = 0; LOCALVAR ui4b SoundInvertState = 0; IMPORTFUNC ui4b GetSoundInvertTime(void); GLOBALPROC MacSound_SubTick(int SubTick) { ui4r actL; tpSoundSamp p; ui4r i; ui5b StartOffset = SubTick_offset[SubTick]; ui4r n = SubTick_n[SubTick]; unsigned long addy = #ifdef SoundBuffer (SoundBuffer == 0) ? kSnd_Alt_Buffer : #endif kSnd_Main_Buffer; ui3p addr = addy + (2 * StartOffset) + RAM; ui4b SoundInvertTime = GetSoundInvertTime(); ui3b SoundVolume = SoundVolb0 | (SoundVolb1 << 1) | (SoundVolb2 << 2); #if dbglog_HAVE && 0 dbglog_StartLine(); dbglog_writeCStr("reading sound buffer "); dbglog_writeHex(StartOffset); dbglog_writeCStr(" to "); dbglog_writeHex(StartOffset + n); dbglog_writeReturn(); #endif label_retry: p = MySound_BeginWrite(n, &actL); if (actL > 0) { if (SoundDisable && (SoundInvertTime == 0)) { for (i = 0; i < actL; i++) { #if 0 *p++ = 0x00; /* this is believed more accurate */ #else /* But this avoids more clicks. */ *p++ = kCenterSound; #endif } } else { for (i = 0; i < actL; i++) { /* Copy sound data, high byte of each word */ *p++ = *addr #if 4 == kLn2SoundSampSz << 8 #endif ; /* Move the address on */ addr += 2; } if (SoundInvertTime != 0) { ui5b PhaseIncr = (ui5b)SoundInvertTime * (ui5b)20; p -= actL; for (i = 0; i < actL; i++) { if (SoundInvertPhase < 704) { ui5b OnPortion = 0; ui5b LastPhase = 0; do { if (! SoundInvertState) { OnPortion += (SoundInvertPhase - LastPhase); } SoundInvertState = ! SoundInvertState; LastPhase = SoundInvertPhase; SoundInvertPhase += PhaseIncr; } while (SoundInvertPhase < 704); if (! SoundInvertState) { OnPortion += 704 - LastPhase; } *p = (*p * OnPortion) / 704; } else { if (SoundInvertState) { *p = 0; } } SoundInvertPhase -= 704; p++; } } } if (SoundVolume < 7) { /* Usually have volume at 7, so this is just for completeness. */ ui5b mult = (ui5b)vol_mult[SoundVolume]; trSoundSamp offset = vol_offset[SoundVolume]; p -= actL; for (i = 0; i < actL; i++) { *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset; ++p; } } MySound_EndWrite(actL); n -= actL; if (n > 0) { goto label_retry; } } } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SNDEMDEV.h b/Mini vMac/mnvm_core/SNDEMDEV.h new file mode 100755 index 0000000..ea8d2b1 --- /dev/null +++ b/Mini vMac/mnvm_core/SNDEMDEV.h @@ -0,0 +1 @@ +/* SNDEMDEV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef SNDEMDEV_H #error "header already included" #else #define SNDEMDEV_H #endif #if MySoundEnabled EXPORTPROC MacSound_SubTick(int SubTick); #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SONYEMDV.c b/Mini vMac/mnvm_core/SONYEMDV.c new file mode 100755 index 0000000..eda6079 --- /dev/null +++ b/Mini vMac/mnvm_core/SONYEMDV.c @@ -0,0 +1 @@ +/* SONYEMDV.c Copyright (C) 2009 Philip Cummins, Jesus A. Alvarez, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* SONY floppy disk EMulated DeVice The Sony hardware is not actually emulated. Instead the ROM is patched to replace the Sony disk driver with code that calls Mini vMac extensions implemented in the file. Information neeeded to better support the Disk Copy 4.2 format was found in libdc42.c of the Lisa Emulator Project by Ray A. Arachelian, and adapted to Mini vMac by Jesus A. Alvarez. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "MINEM68K.h" #endif #include "SONYEMDV.h" LOCALVAR ui5b vSonyMountedMask = 0; #define vSonyIsLocked(Drive_No) \ ((vSonyWritableMask & ((ui5b)1 << (Drive_No))) == 0) #define vSonyIsMounted(Drive_No) \ ((vSonyMountedMask & ((ui5b)1 << (Drive_No))) != 0) LOCALFUNC blnr vSonyNextPendingInsert0(tDrive *Drive_No) { /* find next drive to Mount */ ui5b MountPending = vSonyInsertedMask & (~ vSonyMountedMask); if (MountPending != 0) { tDrive i; for (i = 0; i < NumDrives; ++i) { if ((MountPending & ((ui5b)1 << i)) != 0) { *Drive_No = i; return trueblnr; /* only one disk at a time */ } } } return falseblnr; } LOCALFUNC tMacErr CheckReadableDrive(tDrive Drive_No) { tMacErr result; if (Drive_No >= NumDrives) { result = mnvm_nsDrvErr; } else if (! vSonyIsMounted(Drive_No)) { result = mnvm_offLinErr; } else { result = mnvm_noErr; } return result; } LOCALFUNC tMacErr vSonyTransferVM(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { /* Transfer data between emulated disk and emulated memory. Taking into account that the emulated memory may not be contiguous in real memory. (Though it generally is for macintosh emulation.) */ tMacErr result; ui5b contig; ui5r actual; ui3p Buffer; ui5r offset = Sony_Start; ui5r n = Sony_Count; label_1: if (0 == n) { result = mnvm_noErr; } else { Buffer = get_real_address0(n, ! IsWrite, Buffera, &contig); if (0 == contig) { result = mnvm_miscErr; } else { result = vSonyTransfer(IsWrite, Buffer, Drive_No, offset, contig, &actual); offset += actual; Buffera += actual; n -= actual; if (mnvm_noErr == result) { goto label_1; } } } if (nullpr != Sony_ActCount) { *Sony_ActCount = Sony_Count - n; } return result; } LOCALPROC MyMoveBytesVM(CPTR srcPtr, CPTR dstPtr, si5b byteCount) { ui3p src; ui3p dst; ui5b contigSrc; ui5b contigDst; ui5r contig; label_1: if (0 != byteCount) { src = get_real_address0(byteCount, falseblnr, srcPtr, &contigSrc); dst = get_real_address0(byteCount, trueblnr, dstPtr, &contigDst); if ((0 == contigSrc) || (0 == contigDst)) { ReportAbnormal("MyMoveBytesVM fails"); } else { contig = (contigSrc < contigDst) ? contigSrc : contigDst; MyMoveBytes(src, dst, contig); srcPtr += contig; dstPtr += contig; byteCount -= contig; goto label_1; } } } LOCALVAR ui5r ImageDataOffset[NumDrives]; /* size of any header in disk image file */ LOCALVAR ui5r ImageDataSize[NumDrives]; /* size of disk image file contents */ #if Sony_SupportTags LOCALVAR ui5r ImageTagOffset[NumDrives]; /* offset to disk image file tags */ #endif #if Sony_SupportDC42 #define kDC42offset_diskName 0 #define kDC42offset_dataSize 64 #define kDC42offset_tagSize 68 #define kDC42offset_dataChecksum 72 #define kDC42offset_tagChecksum 76 #define kDC42offset_diskFormat 80 #define kDC42offset_formatByte 81 #define kDC42offset_private 82 #define kDC42offset_userData 84 #endif #define ChecksumBlockSize 1024 #if Sony_SupportDC42 && Sony_WantChecksumsUpdated LOCALFUNC tMacErr DC42BlockChecksum(tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *r) { tMacErr result; ui5r n; ui3b Buffer[ChecksumBlockSize]; ui3b *p; ui5b sum = 0; ui5r offset = Sony_Start; ui5r remaining = Sony_Count; while (0 != remaining) { /* read a block */ if (remaining > ChecksumBlockSize) { n = ChecksumBlockSize; } else { n = remaining; } result = vSonyTransfer(falseblnr, Buffer, Drive_No, offset, n, nullpr); if (mnvm_noErr != result) { return result; } offset += n; remaining -= n; /* add to Checksum */ p = Buffer; n >>= 1; /* n = number of words */ while (0 != n) { --n; /* ROR.l sum+word */ sum += do_get_mem_word(p); p += 2; sum = (sum >> 1) | ((sum & 1) << 31); } } *r = sum; return mnvm_noErr; } #endif #if Sony_SupportDC42 && Sony_WantChecksumsUpdated #if Sony_SupportTags #define SizeCheckSumsToUpdate 8 #else #define SizeCheckSumsToUpdate 4 #endif #endif #if Sony_WantChecksumsUpdated LOCALPROC Drive_UpdateChecksums(tDrive Drive_No) { if (! vSonyIsLocked(Drive_No)) { ui5r DataOffset = ImageDataOffset[Drive_No]; #if Sony_SupportDC42 if (kDC42offset_userData == DataOffset) { /* a disk copy 4.2 image */ tMacErr result; ui5r dataChecksum; ui3b Buffer[SizeCheckSumsToUpdate]; ui5r Sony_Count = SizeCheckSumsToUpdate; ui5r DataSize = ImageDataSize[Drive_No]; /* Checksum image data */ result = DC42BlockChecksum(Drive_No, DataOffset, DataSize, &dataChecksum); if (mnvm_noErr != result) { ReportAbnormal("Failed to find dataChecksum"); dataChecksum = 0; } do_put_mem_long(Buffer, dataChecksum); #if Sony_SupportTags { ui5r tagChecksum; ui5r TagOffset = ImageTagOffset[Drive_No]; ui5r TagSize = (0 == TagOffset) ? 0 : ((DataSize >> 9) * 12); if (TagSize < 12) { tagChecksum = 0; } else { /* Checksum of tags doesn't include first block. presumably because of bug in original disk copy program. */ result = DC42BlockChecksum(Drive_No, TagOffset + 12, TagSize - 12, &tagChecksum); if (mnvm_noErr != result) { ReportAbnormal("Failed to find tagChecksum"); tagChecksum = 0; } } do_put_mem_long(Buffer + 4, tagChecksum); } #endif /* write Checksums */ vSonyTransfer(trueblnr, Buffer, Drive_No, kDC42offset_dataChecksum, Sony_Count, nullpr); } #endif } } #endif #define checkheaderoffset 0 #define checkheadersize 128 #define Sony_SupportOtherFormats Sony_SupportDC42 LOCALFUNC tMacErr vSonyNextPendingInsert(tDrive *Drive_No) { tDrive i; tMacErr result; ui5r L; if (! vSonyNextPendingInsert0(&i)) { result = mnvm_nsDrvErr; } else { result = vSonyGetSize(i, &L); if (mnvm_noErr == result) { /* first, set up for default format */ ui5r DataOffset = 0; ui5r DataSize = L; #if Sony_SupportTags ui5r TagOffset = 0; #endif #if Sony_SupportOtherFormats #if IncludeSonyRawMode if (! vSonyRawMode) #endif { ui5r DataOffset0; ui5r DataSize0; ui5r TagOffset0; ui5r TagSize0; ui3b Temp[checkheadersize]; ui5r Sony_Count = checkheadersize; blnr gotFormat = falseblnr; result = vSonyTransfer(falseblnr, Temp, i, checkheaderoffset, Sony_Count, nullpr); if (mnvm_noErr == result) { #if Sony_SupportDC42 /* Detect Disk Copy 4.2 image */ if (0x0100 == do_get_mem_word( &Temp[kDC42offset_private])) { /* DC42 signature found, check sizes */ DataSize0 = do_get_mem_long( &Temp[kDC42offset_dataSize]); TagSize0 = do_get_mem_long( &Temp[kDC42offset_tagSize]); DataOffset0 = kDC42offset_userData; TagOffset0 = DataOffset0 + DataSize0; if (L >= (TagOffset0 + TagSize0)) if (0 == (DataSize0 & 0x01FF)) if ((DataSize0 >> 9) >= 4) if (Temp[kDC42offset_diskName] < 64) /* length of pascal string */ { if (0 == TagSize0) { /* no tags */ gotFormat = trueblnr; } else if ((DataSize0 >> 9) * 12 == TagSize0) { /* 12 byte tags */ gotFormat = trueblnr; } if (gotFormat) { #if Sony_VerifyChecksums /* mostly useful to check the Checksum code */ ui5r dataChecksum; ui5r tagChecksum; ui5r dataChecksum0 = do_get_mem_long( &Temp[kDC42offset_dataChecksum]); ui5r tagChecksum0 = do_get_mem_long( &Temp[kDC42offset_tagChecksum]); result = DC42BlockChecksum(i, DataOffset0, DataSize0, &dataChecksum); if (TagSize0 >= 12) { result = DC42BlockChecksum(i, TagOffset0 + 12, TagSize0 - 12, &tagChecksum); } else { tagChecksum = 0; } if (dataChecksum != dataChecksum0) { ReportAbnormal("bad dataChecksum"); } if (tagChecksum != tagChecksum0) { ReportAbnormal("bad tagChecksum"); } #endif DataOffset = DataOffset0; DataSize = DataSize0; #if Sony_SupportTags TagOffset = (0 == TagSize0) ? 0 : TagOffset0; #endif #if (! Sony_SupportTags) || (! Sony_WantChecksumsUpdated) if (! vSonyIsLocked(i)) { #if ! Sony_WantChecksumsUpdated /* unconditionally revoke */ #else if (0 != TagSize0) #endif { DiskRevokeWritable(i); } } #endif } } } #endif /* Sony_SupportDC42 */ } } if (mnvm_noErr == result) #endif /* Sony_SupportOtherFormats */ { vSonyMountedMask |= ((ui5b)1 << i); ImageDataOffset[i] = DataOffset; ImageDataSize[i] = DataSize; #if Sony_SupportTags ImageTagOffset[i] = TagOffset; #endif *Drive_No = i; } } if (mnvm_noErr != result) { (void) vSonyEject(i); } } return result; } #define MinTicksBetweenInsert 60 /* if call PostEvent too frequently, insert events seem to get lost */ LOCALVAR ui4r DelayUntilNextInsert; LOCALVAR CPTR MountCallBack = 0; /* This checks to see if a disk (image) has been inserted */ GLOBALPROC Sony_Update (void) { if (DelayUntilNextInsert != 0) { --DelayUntilNextInsert; } else { if (MountCallBack != 0) { tDrive i; if (mnvm_noErr == vSonyNextPendingInsert(&i)) { ui5b data = i; if (vSonyIsLocked(i)) { data |= ((ui5b)0x00FF) << 16; } DiskInsertedPsuedoException(MountCallBack, data); DelayUntilNextInsert = MinTicksBetweenInsert; } } } } LOCALFUNC tMacErr Drive_Transfer(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { tMacErr result; QuietEnds(); if (nullpr != Sony_ActCount) { *Sony_ActCount = 0; } result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { if (IsWrite && vSonyIsLocked(Drive_No)) { result = mnvm_vLckdErr; } else { ui5r DataSize = ImageDataSize[Drive_No]; if (Sony_Start > DataSize) { result = mnvm_eofErr; } else { blnr hit_eof = falseblnr; ui5r L = DataSize - Sony_Start; if (L >= Sony_Count) { L = Sony_Count; } else { hit_eof = trueblnr; } result = vSonyTransferVM(IsWrite, Buffera, Drive_No, ImageDataOffset[Drive_No] + Sony_Start, L, Sony_ActCount); if ((mnvm_noErr == result) && hit_eof) { result = mnvm_eofErr; } } } } return result; } LOCALVAR blnr QuitOnEject = falseblnr; GLOBALPROC Sony_SetQuitOnEject(void) { QuitOnEject = trueblnr; } LOCALFUNC tMacErr Drive_Eject(tDrive Drive_No) { tMacErr result; result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { vSonyMountedMask &= ~ ((ui5b)1 << Drive_No); #if Sony_WantChecksumsUpdated Drive_UpdateChecksums(Drive_No); #endif result = vSonyEject(Drive_No); if (QuitOnEject != 0) { if (! AnyDiskInserted()) { ForceMacOff = trueblnr; } } } return result; } #if IncludeSonyNew LOCALFUNC tMacErr Drive_EjectDelete(tDrive Drive_No) { tMacErr result; result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { if (vSonyIsLocked(Drive_No)) { result = mnvm_vLckdErr; } else { vSonyMountedMask &= ~ ((ui5b)1 << Drive_No); result = vSonyEjectDelete(Drive_No); } } return result; } #endif GLOBALPROC Sony_EjectAllDisks(void) { tDrive i; vSonyMountedMask = 0; for (i = 0; i < NumDrives; ++i) { if (vSonyIsInserted(i)) { #if Sony_WantChecksumsUpdated Drive_UpdateChecksums(i); #endif (void) vSonyEject(i); } } } GLOBALPROC Sony_Reset(void) { DelayUntilNextInsert = 0; QuitOnEject = falseblnr; MountCallBack = 0; } /* Mini vMac extension for low level access to disk operations. */ #define kCmndDiskNDrives 1 #define kCmndDiskRead 2 #define kCmndDiskWrite 3 #define kCmndDiskEject 4 #define kCmndDiskGetSize 5 #define kCmndDiskGetCallBack 6 #define kCmndDiskSetCallBack 7 #define kCmndDiskQuitOnEject 8 #define kCmndDiskFeatures 9 #define kCmndDiskNextPendingInsert 10 #if IncludeSonyRawMode #define kCmndDiskGetRawMode 11 #define kCmndDiskSetRawMode 12 #endif #if IncludeSonyNew #define kCmndDiskNew 13 #define kCmndDiskGetNewWanted 14 #define kCmndDiskEjectDelete 15 #endif #if IncludeSonyGetName #define kCmndDiskGetName 16 #endif #define kFeatureCmndDisk_RawMode 0 #define kFeatureCmndDisk_New 1 #define kFeatureCmndDisk_NewName 2 #define kFeatureCmndDisk_GetName 3 #define kParamDiskNumDrives 8 #define kParamDiskStart 8 #define kParamDiskCount 12 #define kParamDiskBuffer 16 #define kParamDiskDrive_No 20 GLOBALPROC ExtnDisk_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 2); result = mnvm_noErr; break; case kCmndDiskNDrives: /* count drives */ put_vm_word(p + kParamDiskNumDrives, NumDrives); result = mnvm_noErr; break; case kCmndDiskRead: { ui5r Sony_ActCount; CPTR Buffera = get_vm_long(p + kParamDiskBuffer); tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); ui5r Sony_Start = get_vm_long(p + kParamDiskStart); ui5r Sony_Count = get_vm_long(p + kParamDiskCount); result = Drive_Transfer(falseblnr, Buffera, Drive_No, Sony_Start, Sony_Count, &Sony_ActCount); put_vm_long(p + kParamDiskCount, Sony_ActCount); } break; case kCmndDiskWrite: { ui5r Sony_ActCount; CPTR Buffera = get_vm_long(p + kParamDiskBuffer); tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); ui5r Sony_Start = get_vm_long(p + kParamDiskStart); ui5r Sony_Count = get_vm_long(p + kParamDiskCount); result = Drive_Transfer(trueblnr, Buffera, Drive_No, Sony_Start, Sony_Count, &Sony_ActCount); put_vm_long(p + kParamDiskCount, Sony_ActCount); } break; case kCmndDiskEject: { tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); result = Drive_Eject(Drive_No); } break; case kCmndDiskGetSize: { tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { put_vm_long(p + kParamDiskCount, ImageDataSize[Drive_No]); result = mnvm_noErr; } } break; case kCmndDiskGetCallBack: put_vm_long(p + kParamDiskBuffer, MountCallBack); result = mnvm_noErr; break; case kCmndDiskSetCallBack: MountCallBack = get_vm_long(p + kParamDiskBuffer); result = mnvm_noErr; break; case kCmndDiskQuitOnEject: QuitOnEject = trueblnr; result = mnvm_noErr; break; case kCmndDiskFeatures: { ui5r v = (0 #if IncludeSonyRawMode | ((ui5b)1 << kFeatureCmndDisk_RawMode) #endif #if IncludeSonyNew | ((ui5b)1 << kFeatureCmndDisk_New) #endif #if IncludeSonyNameNew | ((ui5b)1 << kFeatureCmndDisk_NewName) #endif #if IncludeSonyGetName | ((ui5b)1 << kFeatureCmndDisk_GetName) #endif ); put_vm_long(p + ExtnDat_params + 0, v); result = mnvm_noErr; } break; case kCmndDiskNextPendingInsert: { tDrive i; result = vSonyNextPendingInsert(&i); if (mnvm_noErr == result) { put_vm_word(p + kParamDiskDrive_No, i); } } break; #if IncludeSonyRawMode case kCmndDiskGetRawMode: put_vm_word(p + kParamDiskBuffer, vSonyRawMode); result = mnvm_noErr; break; case kCmndDiskSetRawMode: vSonyRawMode = get_vm_word(p + kParamDiskBuffer); result = mnvm_noErr; break; #endif #if IncludeSonyNew case kCmndDiskNew: { ui5b count = get_vm_long(p + ExtnDat_params + 0); tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 4); /* reserved word at offset 6, should be zero */ result = mnvm_noErr; #if IncludePbufs if (Pbuf_No != NotAPbuf) { result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { vSonyNewDiskWanted = trueblnr; vSonyNewDiskSize = count; #if IncludeSonyNameNew if (vSonyNewDiskName != NotAPbuf) { PbufDispose(vSonyNewDiskName); } vSonyNewDiskName = Pbuf_No; #else PbufDispose(Pbuf_No); #endif } } else #endif { vSonyNewDiskWanted = trueblnr; vSonyNewDiskSize = count; } } break; case kCmndDiskGetNewWanted: put_vm_word(p + kParamDiskBuffer, vSonyNewDiskWanted); result = mnvm_noErr; break; case kCmndDiskEjectDelete: { tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); result = Drive_EjectDelete(Drive_No); } break; #endif #if IncludeSonyGetName case kCmndDiskGetName: { tDrive Drive_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { tPbuf Pbuf_No; result = vSonyGetName(Drive_No, &Pbuf_No); put_vm_word(p + ExtnDat_params + 4, Pbuf_No); } } break; #endif } put_vm_word(p + ExtnDat_result, result); } /* Mini vMac extension that implements most of the logic of the replacement disk driver patched into the emulated ROM. (sony_driver in ROMEMDEV.c) This logic used to be completely contained in the 68k code of the replacement driver, using only the low level disk access extension. */ /* Sony Variable Drive Setting Offsets */ #define kTrack 0 /* Current Track */ #define kWriteProt 2 /* FF if Write Protected, 00 if readable */ #define kDiskInPlace 3 /* 00 = No Disk, 01 = Disk In, 2 = MacOS Read, FC-FF = Just Ejected */ #define kInstalled 4 /* 00 = Unknown, 01 = Installed, FF = Not Installed */ #define kSides 5 /* 00 if Single Sided Drive, FF if Doubled Sided Drive */ #define kQLink 6 /* Link to Next Drive */ #define kQType 10 /* Drive Type (0 = Size Saved, 1 = Very Large) */ #define kQDriveNo 12 /* Drive Number (1 = Internal, 2 = External) */ #define kQRefNum 14 /* Driver Reference Number (-5 for .Sony, FFFB) */ #define kQFSID 16 /* File System ID (0 = MacOS) */ #define kQDrvSz 18 /* size, low-order word */ #define kQDrvSz2 20 /* size, hi-order word */ #define kTwoSideFmt 18 /* FF if double-sided format, 00 if single-sided format */ #define kNewIntf 19 /* FF if new 800K interface or 00 if old 400K interface */ #define kDriveErrs 20 /* Drive Soft Errors */ /* Sony Driver Control Call csCodes */ #define kKillIO 1 #define kVerifyDisk 5 #define kFormatDisk 6 #define kEjectDisk 7 #define kSetTagBuffer 8 #define kTrackCacheControl 9 #define kGetIconID 20 #define kDriveIcon 21 #define kMediaIcon 22 #define kDriveInfo 23 #define kFormatCopy 21315 /* Sony Driver Status Call csCodes */ #define kReturnFormatList 6 #define kDriveStatus 8 #define kMFMStatus 10 #define kDuplicatorVersionSupport 17494 /* Parameter Block Offsets */ #define kqLink 0 #define kqType 4 #define kioTrap 6 #define kioCmdAddr 8 #define kioCompletion 12 #define kioResult 16 #define kioNamePtr 18 #define kioVRefNum 22 #define kioRefNum 24 #define kcsCode 26 #define kcsParam 28 #define kioBuffer 32 /* Buffer to store data into */ #define kioReqCount 36 /* Requested Number of Bytes */ #define kioActCount 40 /* Actual Number of Bytes obtained */ #define kioPosMode 44 /* Positioning Mode */ #define kioPosOffset 46 /* Position Offset */ /* Positioning Modes */ #define kfsAtMark 0 /* At Mark (Ignore PosOffset) */ #define kfsFromStart 1 /* At Start (PosOffset is absolute) */ #define kfsFromLEOF 2 /* From Logical End of File - PosOffset */ #define kfsFromMark 3 /* At Mark + PosOffset */ /* Device Control Entry Offsets */ #define kdCtlPosition 16 #if 0 struct MyDriverDat_R { ui5b zeroes[4]; /* 0 */ ui5b checkval; /* 16 */ ui5b pokeaddr; /* 20 */ ui4b NumDrives; /* 24 */ ui4b DiskExtn; /* 26 */ TMTask NullTask; /* 28 */ /* total size must be <= FirstDriveVarsOffset */ }; typedef struct MyDriverDat_R MyDriverDat_R; #endif #define SonyVarsPtr 0x0134 #define FirstDriveVarsOffset 74 #define EachDriveVarsSize 66 #if CurEmMd <= kEmMd_128K #define MinSonVarsSize 0x000000FA #else #define MinSonVarsSize 0x00000310 #endif #define kcom_checkval 0x841339E2 #if Sony_SupportTags LOCALVAR CPTR TheTagBuffer; #endif LOCALFUNC ui5b DriveVarsLocation(tDrive Drive_No) { CPTR SonyVars = get_vm_long(SonyVarsPtr); if (Drive_No < NumDrives) { return SonyVars + FirstDriveVarsOffset + EachDriveVarsSize * Drive_No; } else { return 0; } } LOCALFUNC tMacErr Sony_Mount(CPTR p) { ui5b data = get_vm_long(p + ExtnDat_params + 0); tMacErr result = mnvm_miscErr; tDrive i = data & 0x0000FFFF; CPTR dvl = DriveVarsLocation(i); if (0 == dvl) { result = mnvm_nsDrvErr; } else if (get_vm_byte(dvl + kDiskInPlace) == 0x00) { ui5b L = ImageDataSize[i] >> 9; /* block count */ if ((L == 800) #if CurEmMd > kEmMd_128K || (L == 1600) #endif ) { #if CurEmMd <= kEmMd_128K put_vm_byte(dvl + kTwoSideFmt, 0x00); /* Drive i Single Format */ put_vm_byte(dvl + kNewIntf, 0x00); /* Drive i doesn't use new interface */ #else if (L == 800) { put_vm_byte(dvl + kTwoSideFmt, 0x00); /* Drive i Single Format */ } else { put_vm_byte(dvl + kTwoSideFmt, 0xFF); /* Drive Double Format */ } put_vm_byte(dvl + kNewIntf, 0xFF); /* Drive i uses new interface */ #endif put_vm_word(dvl + kQType, 0x00); /* Drive Type */ put_vm_word(dvl + kDriveErrs, 0x0000); /* Drive i has no errors */ } else { put_vm_word(dvl + kQRefNum, 0xFFFE); /* Driver */ put_vm_word(dvl + kQType, 0x01); /* Drive Type */ put_vm_word(dvl + kQDrvSz , L); put_vm_word(dvl + kQDrvSz2, L >> 16); } put_vm_byte(dvl + kWriteProt, data >> 16); put_vm_byte(dvl + kDiskInPlace, 0x01); /* Drive Disk Inserted */ put_vm_long(p + ExtnDat_params + 4, i + 1); /* PostEvent Disk Inserted eventMsg */ result = mnvm_noErr; } /* else, if disk already in place, a mistake has been made */ return result; } #if Sony_SupportTags LOCALFUNC tMacErr Sony_PrimeTags(tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, blnr IsWrite) { tMacErr result = mnvm_noErr; ui5r TagOffset = ImageTagOffset[Drive_No]; if ((0 != TagOffset) && (Sony_Count > 0)) { ui5r block = Sony_Start >> 9; ui5r n = Sony_Count >> 9; /* is >= 1 if get here */ TagOffset += block * 12; if (0 != TheTagBuffer) { ui5r count = 12 * n; result = vSonyTransferVM(IsWrite, TheTagBuffer, Drive_No, TagOffset, count, nullpr); if (mnvm_noErr == result) { MyMoveBytesVM(TheTagBuffer + count - 12, 0x02FC, 12); } } else { if (! IsWrite) { /* only need to read the last block tags */ ui5r count = 12; TagOffset += 12 * (n - 1); result = vSonyTransferVM(falseblnr, 0x02FC, Drive_No, TagOffset, count, nullpr); } else { ui5r count = 12; ui4r BufTgFBkNum = get_vm_word(0x0302); do { put_vm_word(0x0302, BufTgFBkNum); result = vSonyTransferVM(trueblnr, 0x02FC, Drive_No, TagOffset, count, nullpr); if (mnvm_noErr != result) { goto label_fail; } BufTgFBkNum += 1; TagOffset += 12; } while (--n != 0); } } } label_fail: return result; } #endif /* Handles I/O to disks */ LOCALFUNC tMacErr Sony_Prime(CPTR p) { tMacErr result; ui5r Sony_Count; ui5r Sony_Start; ui5r Sony_ActCount = 0; CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; ui4r IOTrap = get_vm_word(ParamBlk + kioTrap); CPTR dvl = DriveVarsLocation(Drive_No); if (0 == dvl) { result = mnvm_nsDrvErr; } else if (0xA002 != (IOTrap & 0xF0FE)) { /* not read (0xA002) or write (0xA003) */ result = mnvm_controlErr; } else { blnr IsWrite = (0 != (IOTrap & 0x0001)); ui3b DiskInPlaceV = get_vm_byte(dvl + kDiskInPlace); if (DiskInPlaceV != 0x02) { if (DiskInPlaceV == 0x01) { put_vm_byte(dvl + kDiskInPlace, 0x02); /* Clamp Drive */ } else { result = mnvm_offLinErr; goto label_fail; /* if don't check for this, will go right ahead and boot off a disk that hasn't been mounted yet by Sony_Update. (disks other than the boot disk aren't seen unless mounted by Sony_Update) */ } } #if 0 ui4r PosMode = get_vm_word(ParamBlk + kioPosMode); if (0 != (PosMode & 64)) { #if ExtraAbnormalReports /* This is used when copy to floppy disk with Finder. But not implemented yet. */ ReportAbnormal("read verify mode requested"); #endif PosMode &= ~ 64; } /* Don't use the following code, because according to Apple's Technical Note FL24 the Device Manager takes care of this, and puts the result in dCtlPosition. (The RAMDisk example in Apple's sample code serves to confirm this. Further evidence found in Basilisk II emulator, and disassembly of Mac Plus disk driver.) */ ui5r PosOffset = get_vm_long(ParamBlk + kioPosOffset); switch (PosMode) { case kfsAtMark: Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition); break; case kfsFromStart: Sony_Start = PosOffset; break; #if 0 /* not valid for device driver. actually only kfsFromStart seems to be used. */ case kfsFromLEOF: Sony_Start = ImageDataSize[Drive_No] + PosOffset; break; #endif case kfsFromMark: Sony_Start = PosOffset + get_vm_long(DeviceCtl + kdCtlPosition); break; default: ReportAbnormal("unknown PosMode"); result = mnvm_paramErr; goto label_fail; break; } #endif Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition); Sony_Count = get_vm_long(ParamBlk + kioReqCount); if ((0 != (Sony_Start & 0x1FF)) || (0 != (Sony_Count & 0x1FF))) { /* only whole blocks allowed */ result = mnvm_paramErr; } else if (IsWrite && (get_vm_byte(dvl + kWriteProt) != 0)) { result = mnvm_wPrErr; } else { CPTR Buffera = get_vm_long(ParamBlk + kioBuffer); result = Drive_Transfer(IsWrite, Buffera, Drive_No, Sony_Start, Sony_Count, &Sony_ActCount); #if Sony_SupportTags if (mnvm_noErr == result) { result = Sony_PrimeTags(Drive_No, Sony_Start, Sony_Count, IsWrite); } #endif put_vm_long(DeviceCtl + kdCtlPosition, Sony_Start + Sony_ActCount); } } label_fail: put_vm_word(ParamBlk + kioResult, result); put_vm_long(ParamBlk + kioActCount, Sony_ActCount); if (mnvm_noErr != result) { put_vm_word(0x0142 /* DskErr */, result); } return result; } /* Implements control csCodes for the Sony driver */ LOCALFUNC tMacErr Sony_Control(CPTR p) { tMacErr result; CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); /* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */ ui4r OpCode = get_vm_word(ParamBlk + kcsCode); if (kKillIO == OpCode) { result = mnvm_miscErr; } else if (kSetTagBuffer == OpCode) { #if Sony_SupportTags TheTagBuffer = get_vm_long(ParamBlk + kcsParam); result = mnvm_noErr; #else result = mnvm_controlErr; #endif } else if (kTrackCacheControl == OpCode) { #if CurEmMd <= kEmMd_128K result = mnvm_controlErr; #else #if 0 ui3r Arg1 = get_vm_byte(ParamBlk + kcsParam); ui3r Arg2 = get_vm_byte(ParamBlk + kcsParam + 1); if (0 == Arg1) { /* disable track cache */ } else { /* enable track cache */ } if (Arg2 < 0) { /* remove track cache */ } else if (Arg2 > 0) { /* install track cache */ } #endif result = mnvm_noErr; /* not implemented, but pretend we did it */ #endif } else { tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; CPTR dvl = DriveVarsLocation(Drive_No); if (0 == dvl) { result = mnvm_nsDrvErr; } else if (get_vm_byte(dvl + kDiskInPlace) == 0) { result = mnvm_offLinErr; } else { switch (OpCode) { case kVerifyDisk : result = mnvm_noErr; break; case kEjectDisk : put_vm_byte(dvl + kWriteProt, 0x00); /* Drive Writeable */ put_vm_byte(dvl + kDiskInPlace, 0x00); /* Drive No Disk */ #if 0 put_vm_byte(dvl + kTwoSideFmt, 0x00); /* Drive Single Format (Initially) */ #endif put_vm_word(dvl + kQRefNum, 0xFFFB); /* Drive i uses .Sony */ result = Drive_Eject(Drive_No); break; case kFormatDisk : result = mnvm_noErr; break; case kDriveIcon : if (get_vm_word(dvl + kQType) != 0) { put_vm_long(ParamBlk + kcsParam, my_disk_icon_addr); result = mnvm_noErr; } else { result = mnvm_controlErr; /* Driver can't respond to this Control call (-17) */ } break; #if CurEmMd >= kEmMd_SE case kDriveInfo : { ui5b v; if (get_vm_word(dvl + kQType) != 0) { v = 0x00000001; /* unspecified drive */ } else { #if CurEmMd <= kEmMd_128K v = 0x00000002; /* 400K Drive */ #else v = 0x00000003; /* 800K Drive */ #endif } if (Drive_No != 0) { v += 0x00000900; /* Secondary External Drive */ } put_vm_long(ParamBlk + kcsParam, v); result = mnvm_noErr; /* No error (0) */ } break; #endif default : #if ExtraAbnormalReports if ((kGetIconID != OpCode) && (kMediaIcon != OpCode) && (kDriveInfo != OpCode)) { ReportAbnormal( "unexpected OpCode in Sony_Control"); } #endif result = mnvm_controlErr; /* Driver can't respond to this Control call (-17) */ break; } } } if (mnvm_noErr != result) { put_vm_word(0x0142 /* DskErr */, result); } return result; } /* Handles the DriveStatus call */ LOCALFUNC tMacErr Sony_Status(CPTR p) { tMacErr result; CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); /* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */ ui4r OpCode = get_vm_word(ParamBlk + kcsCode); if (kDriveStatus == OpCode) { tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; CPTR Src = DriveVarsLocation(Drive_No); if (Src == 0) { result = mnvm_nsDrvErr; } else { MyMoveBytesVM(Src, ParamBlk + kcsParam, 22); result = mnvm_noErr; } } else { #if ExtraAbnormalReports if ((kReturnFormatList != OpCode) && (kDuplicatorVersionSupport != OpCode)) { ReportAbnormal("unexpected OpCode in Sony_Control"); } #endif result = mnvm_statusErr; } if (mnvm_noErr != result) { put_vm_word(0x0142 /* DskErr */, result); } return result; } LOCALFUNC tMacErr Sony_Close(CPTR p) { #if 0 CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); #endif UnusedParam(p); return mnvm_closErr; /* Can't Close Driver */ } LOCALFUNC tMacErr Sony_OpenA(CPTR p) { if (MountCallBack != 0) { return mnvm_opWrErr; /* driver already open */ } else { ui5b L = FirstDriveVarsOffset + EachDriveVarsSize * NumDrives; if (L < MinSonVarsSize) { L = MinSonVarsSize; } put_vm_long(p + ExtnDat_params + 0, L); return mnvm_noErr; } } LOCALFUNC tMacErr Sony_OpenB(CPTR p) { si4b i; CPTR dvl; CPTR SonyVars = get_vm_long(p + ExtnDat_params + 4); /* CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 24); (unused) */ #if CurEmMd > kEmMd_128K CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 28); #endif put_vm_long(SonyVars + 16 /* checkval */, kcom_checkval); put_vm_long(SonyVars + 20 /* pokeaddr */, kExtn_Block_Base); put_vm_word(SonyVars + 24 /* NumDrives */, NumDrives); put_vm_word(SonyVars + 26 /* DiskExtn */, kExtnDisk); put_vm_long(SonyVarsPtr, SonyVars); for (i = 0; (dvl = DriveVarsLocation(i)) != 0; ++i) { put_vm_byte(dvl + kDiskInPlace, 0x00); /* Drive i No Disk */ put_vm_byte(dvl + kInstalled, 0x01); /* Drive i Installed */ #if CurEmMd <= kEmMd_128K put_vm_byte(dvl + kSides, 0x00); /* Drive i Single Sided */ #else put_vm_byte(dvl + kSides, 0xFF); /* Drive i Double Sided */ #endif put_vm_word(dvl + kQDriveNo, i + 1); /* Drive i is Drive 1 */ put_vm_word(dvl + kQRefNum, 0xFFFB); /* Drive i uses .Sony */ } { CPTR UTableBase = get_vm_long(0x011C); put_vm_long(UTableBase + 4 * 1, get_vm_long(UTableBase + 4 * 4)); /* use same drive for hard disk as used for sony floppies */ } #if CurEmMd > kEmMd_128K /* driver version in driver i/o queue header */ put_vm_byte(DeviceCtl + 7, 1); #endif #if CurEmMd <= kEmMd_128K /* init Drive Queue */ put_vm_word(0x308, 0); put_vm_long(0x308 + 2, 0); put_vm_long(0x308 + 6, 0); #endif put_vm_long(p + ExtnDat_params + 8, SonyVars + FirstDriveVarsOffset + kQLink); put_vm_word(p + ExtnDat_params + 12, EachDriveVarsSize); put_vm_word(p + ExtnDat_params + 14, NumDrives); put_vm_word(p + ExtnDat_params + 16, 1); put_vm_word(p + ExtnDat_params + 18, 0xFFFB); #if CurEmMd <= kEmMd_128K put_vm_long(p + ExtnDat_params + 20, 0); #else put_vm_long(p + ExtnDat_params + 20, SonyVars + 28 /* NullTask */); #endif #if Sony_SupportTags TheTagBuffer = 0; #endif return mnvm_noErr; } LOCALFUNC tMacErr Sony_OpenC(CPTR p) { MountCallBack = get_vm_long(p + ExtnDat_params + 0) #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) | 0x40000000 #endif ; return mnvm_noErr; } #define kCmndSonyPrime 1 #define kCmndSonyControl 2 #define kCmndSonyStatus 3 #define kCmndSonyClose 4 #define kCmndSonyOpenA 5 #define kCmndSonyOpenB 6 #define kCmndSonyOpenC 7 #define kCmndSonyMount 8 GLOBALPROC ExtnSony_Access(CPTR p) { tMacErr result; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 0); result = mnvm_noErr; break; case kCmndSonyPrime: result = Sony_Prime(p); break; case kCmndSonyControl: result = Sony_Control(p); break; case kCmndSonyStatus: result = Sony_Status(p); break; case kCmndSonyClose: result = Sony_Close(p); break; case kCmndSonyOpenA: result = Sony_OpenA(p); break; case kCmndSonyOpenB: result = Sony_OpenB(p); break; case kCmndSonyOpenC: result = Sony_OpenC(p); break; case kCmndSonyMount: result = Sony_Mount(p); break; default: result = mnvm_controlErr; break; } put_vm_word(p + ExtnDat_result, result); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SONYEMDV.h b/Mini vMac/mnvm_core/SONYEMDV.h new file mode 100755 index 0000000..135fc1d --- /dev/null +++ b/Mini vMac/mnvm_core/SONYEMDV.h @@ -0,0 +1 @@ +/* SONYEMDV.h Copyright (C) 2004 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef SONYEMDV_H #error "header already included" #else #define SONYEMDV_H #endif EXPORTPROC ExtnDisk_Access(CPTR p); EXPORTPROC ExtnSony_Access(CPTR p); EXPORTPROC Sony_SetQuitOnEject(void); EXPORTPROC Sony_EjectAllDisks(void); EXPORTPROC Sony_Reset(void); EXPORTPROC Sony_Update(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/STRCONST.h b/Mini vMac/mnvm_core/STRCONST.h new file mode 100755 index 0000000..4f8a875 --- /dev/null +++ b/Mini vMac/mnvm_core/STRCONST.h @@ -0,0 +1 @@ +/* STRCONST.h Copyright (C) 2006 Paul C. Pratt, Pierre Lemieux You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* STRing CONSTants (for English) Pierre Lemieux provided some corrections and suggestions. */ #define kStrAboutTitle "About" #define kStrAboutMessage "To display information about this program, use the ;]A;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu." #define kStrMoreCommandsTitle "More commands are available in the ^p Control Mode." #define kStrMoreCommandsMessage "To enter the Control Mode, press and hold down the ;]control;} key. You will remain in the Control Mode until you release the ;]control;} key. Type ;]H;} in the Control Mode to list available commands." #define kStrTooManyImagesTitle "Too many Disk Images" #define kStrTooManyImagesMessage "I can not mount that many Disk Images. Try ejecting one." #define kStrImageInUseTitle "Disk Image in use" #define kStrImageInUseMessage "I can not mount the Disk Image because it is already in use by another application or already open in ^p." #define kStrOutOfMemTitle "Not enough Memory" #define kStrOutOfMemMessage "There is not enough memory available to launch ^p." #define kStrNoROMTitle "Unable to locate ROM image" #define kStrNoROMMessage "I can not find the ROM image file ;[^r;{. For more information, see: ;[^w;{." #define kStrCorruptedROMTitle "ROM checksum failed" #define kStrCorruptedROMMessage "The ROM image file ;[^r;{ may be corrupted." #define kStrUnsupportedROMTitle "Unsupported ROM" #define kStrUnsupportedROMMessage "The ROM image file ;[^r;{ loaded successfully, but I don;}t support this ROM version." #define kStrQuitWarningTitle "Please shut down the emulated computer before quitting." #define kStrQuitWarningMessage "To force ^p to quit, at the risk of corrupting the mounted disk image files, use the ;]Q;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu." #define kStrReportAbnormalTitle "Abnormal Situation" #define kStrReportAbnormalMessage "The emulated computer is attempting an operation that wasn;}t expected to happen in normal use." #define kStrBadArgTitle "Unknown argument" #define kStrBadArgMessage "I did not understand one of the command line arguments, and ignored it." #define kStrOpenFailTitle "Open failed" #define kStrOpenFailMessage "I could not open the disk image." #define kStrNoReadROMTitle "Unable to read ROM image" #define kStrNoReadROMMessage "I found the ROM image file ;[^r;{, but I can not read it." #define kStrShortROMTitle "ROM image too short" #define kStrShortROMMessage "The ROM image file ;[^r;{ is shorter than it should be." /* state of a boolean option */ #define kStrOn "on" #define kStrOff "off" /* state of a key */ #define kStrPressed "pressed" #define kStrReleased "released" /* state of Stopped */ #define kStrStoppedOn kStrOn #define kStrStoppedOff kStrOff /* About Screen */ #define kStrProgramInfo "^v" #define kStrSponsorIs "^v. This variation is made for:" #define kStrWorkOfMany "Copyright ^y. ^p contains the work of many people. This version is maintained by:" #define kStrForMoreInfo "For more information, see:" #define kStrLicense "^p is distributed under the terms of the GNU Public License, version 2." #define kStrDisclaimer " ^p is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;ls without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." /* Help Screen */ #define kStrHowToLeaveControl "To leave the Control Mode, release the ;]control;} key." #define kStrHowToPickACommand "Otherwise, type a letter. Available commands are:" #define kStrCmdAbout "About (version information)" #define kStrCmdOpenDiskImage "Open disk image;ll" #define kStrCmdQuit "Quit" #define kStrCmdSpeedControl "Speed control;ll (^s)" #define kStrCmdMagnifyToggle "Magnify toggle (^g)" #define kStrCmdFullScrnToggle "Full screen toggle (^f)" #define kStrCmdCtrlKeyToggle "emulated ;]control;} Key toggle (^k)" #define kStrCmdReset "Reset" #define kStrCmdInterrupt "Interrupt" #define kStrCmdHelp "Help (show this page)" /* Speed Control Screen */ #define kStrCurrentSpeed "Current speed: ^s" #define kStrSpeedAllOut "All out" #define kStrSpeedStopped "stopped toggle (^h)" #define kStrSpeedBackToggle "run in Background toggle (^b)" #define kStrSpeedAutoSlowToggle "autosloW toggle (^l)" #define kStrSpeedExit "Exit speed control" #define kStrNewSpeed "Speed: ^s" #define kStrSpeedValueAllOut kStrSpeedAllOut #define kStrNewStopped "Stopped is ^h." #define kStrNewRunInBack "Run in background is ^b." #define kStrNewAutoSlow "AutoSlow is ^l." #define kStrNewMagnify "Magnify is ^g." #define kStrNewFullScreen "Full Screen is ^f." #define kStrNewCntrlKey "Emulated ;]control;} key ^k." #define kStrCmdCancel "cancel" #define kStrConfirmReset "Are you sure you want to reset the emulated computer? Unsaved changes will be lost, and there is a risk of corrupting the mounted disk image files. Type a letter:" #define kStrResetDo "reset" #define kStrResetNo kStrCmdCancel #define kStrHaveReset "Have reset the emulated computer" #define kStrCancelledReset "Reset cancelled" #define kStrConfirmInterrupt "Are you sure you want to interrupt the emulated computer? This will invoke any installed debugger. Type a letter:" #define kStrInterruptDo "interrupt" #define kStrInterruptNo kStrCmdCancel #define kStrHaveInterrupted "Have interrupted the emulated computer" #define kStrCancelledInterrupt "Interrupt cancelled" #define kStrConfirmQuit "Are you sure you want to quit ^p? You should shut down the emulated computer before quitting to prevent corrupting the mounted disk image files. Type a letter:" #define kStrQuitDo "quit" #define kStrQuitNo kStrCmdCancel #define kStrCancelledQuit "Quit cancelled" #define kStrModeConfirmReset "Control Mode : Confirm Reset" #define kStrModeConfirmInterrupt "Control Mode : Confirm Interrupt" #define kStrModeConfirmQuit "Control Mode : Confirm Quit" #define kStrModeSpeedControl "Control Mode : Speed Control" #define kStrModeControlBase "Control Mode (Type ;]H;} for help)" #define kStrModeControlHelp "Control Mode" #define kStrModeMessage "Message (Type ;]C;} to continue)" #define kStrMenuFile "File" #define kStrMenuSpecial "Special" #define kStrMenuHelp "Help" #define kStrMenuItemAbout "About ^p" #define kStrMenuItemOpen "Open Disk Image" #define kStrMenuItemQuit "Quit" #define kStrMenuItemMore "More Commands" #define kStrAppMenuItemHide "Hide ^p" #define kStrAppMenuItemHideOthers "Hide Others" #define kStrAppMenuItemShowAll "Show All" #define kStrAppMenuItemQuit "Quit ^p" \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SYSDEPNS.h b/Mini vMac/mnvm_core/SYSDEPNS.h new file mode 100755 index 0000000..b1f62c4 --- /dev/null +++ b/Mini vMac/mnvm_core/SYSDEPNS.h @@ -0,0 +1 @@ +/* SYSDEPNS.h Copyright (C) 2006 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* SYStem DEPeNdencies. */ #ifdef SYSDEPNS_H #error "header already included" #else #define SYSDEPNS_H #endif #include "CNFGGLOB.h" typedef ui3b *ui3p; typedef ui4b *ui4p; typedef ui5b *ui5p; /* Largest efficiently supported representation types. uimr should be large enough to hold number of elements of any array we will deal with. */ typedef ui5r uimr; typedef si5r simr; #define blnr int #define trueblnr 1 #define falseblnr 0 #define nullpr ((void *) 0) #define anyp ui3p /* pascal string, single byte characters */ #define ps3p ui3p #define LOCALVAR static #ifdef AllFiles #define GLOBALVAR LOCALVAR #define EXPORTVAR(t, v) #else #define GLOBALVAR #define EXPORTVAR(t, v) extern t v; #endif #define LOCALFUNC static #define FORWARDFUNC LOCALFUNC #ifdef AllFiles #define GLOBALFUNC LOCALFUNC #define EXPORTFUNC LOCALFUNC #else #define GLOBALFUNC #define EXPORTFUNC extern #endif #define IMPORTFUNC EXPORTFUNC #define TYPEDEFFUNC typedef #define LOCALPROC LOCALFUNC void #define GLOBALPROC GLOBALFUNC void #define EXPORTPROC EXPORTFUNC void #define IMPORTPROC IMPORTFUNC void #define FORWARDPROC FORWARDFUNC void #define TYPEDEFPROC TYPEDEFFUNC void \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIAEMDEV.c b/Mini vMac/mnvm_core/VIAEMDEV.c new file mode 100755 index 0000000..837b0d2 --- /dev/null +++ b/Mini vMac/mnvm_core/VIAEMDEV.c @@ -0,0 +1 @@ +/* VIAEMDEV.c Copyright (C) 2008 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ /* Versatile Interface Adapter EMulated DEVice Emulates the VIA found in the Mac Plus. This code adapted from vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "VIAEMDEV.h" #ifdef VIA1_iA0_ChangeNtfy IMPORTPROC VIA1_iA0_ChangeNtfy(void); #endif #ifdef VIA1_iA1_ChangeNtfy IMPORTPROC VIA1_iA1_ChangeNtfy(void); #endif #ifdef VIA1_iA2_ChangeNtfy IMPORTPROC VIA1_iA2_ChangeNtfy(void); #endif #ifdef VIA1_iA3_ChangeNtfy IMPORTPROC VIA1_iA3_ChangeNtfy(void); #endif #ifdef VIA1_iA4_ChangeNtfy IMPORTPROC VIA1_iA4_ChangeNtfy(void); #endif #ifdef VIA1_iA5_ChangeNtfy IMPORTPROC VIA1_iA5_ChangeNtfy(void); #endif #ifdef VIA1_iA6_ChangeNtfy IMPORTPROC VIA1_iA6_ChangeNtfy(void); #endif #ifdef VIA1_iA7_ChangeNtfy IMPORTPROC VIA1_iA7_ChangeNtfy(void); #endif #ifdef VIA1_iB0_ChangeNtfy IMPORTPROC VIA1_iB0_ChangeNtfy(void); #endif #ifdef VIA1_iB1_ChangeNtfy IMPORTPROC VIA1_iB1_ChangeNtfy(void); #endif #ifdef VIA1_iB2_ChangeNtfy IMPORTPROC VIA1_iB2_ChangeNtfy(void); #endif #ifdef VIA1_iB3_ChangeNtfy IMPORTPROC VIA1_iB3_ChangeNtfy(void); #endif #ifdef VIA1_iB4_ChangeNtfy IMPORTPROC VIA1_iB4_ChangeNtfy(void); #endif #ifdef VIA1_iB5_ChangeNtfy IMPORTPROC VIA1_iB5_ChangeNtfy(void); #endif #ifdef VIA1_iB6_ChangeNtfy IMPORTPROC VIA1_iB6_ChangeNtfy(void); #endif #ifdef VIA1_iB7_ChangeNtfy IMPORTPROC VIA1_iB7_ChangeNtfy(void); #endif #ifdef VIA1_iCB2_ChangeNtfy IMPORTPROC VIA1_iCB2_ChangeNtfy(void); #endif #define Ui3rPowOf2(p) (1 << (p)) #define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0) #define VIA1_ORA_CanInOrOut (VIA1_ORA_CanIn | VIA1_ORA_CanOut) #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 7) #ifdef VIA1_iA7 #error "VIA1_iA7 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 6) #ifdef VIA1_iA6 #error "VIA1_iA6 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 5) #ifdef VIA1_iA5 #error "VIA1_iA5 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 4) #ifdef VIA1_iA4 #error "VIA1_iA4 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 3) #ifdef VIA1_iA3 #error "VIA1_iA3 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 2) #ifdef VIA1_iA2 #error "VIA1_iA2 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 1) #ifdef VIA1_iA1 #error "VIA1_iA1 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 0) #ifdef VIA1_iA0 #error "VIA1_iA0 defined but not used" #endif #endif #define VIA1_ORB_CanInOrOut (VIA1_ORB_CanIn | VIA1_ORB_CanOut) #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 7) #ifdef VIA1_iB7 #error "VIA1_iB7 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 6) #ifdef VIA1_iB6 #error "VIA1_iB6 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 5) #ifdef VIA1_iB5 #error "VIA1_iB5 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 4) #ifdef VIA1_iB4 #error "VIA1_iB4 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 3) #ifdef VIA1_iB3 #error "VIA1_iB3 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 2) #ifdef VIA1_iB2 #error "VIA1_iB2 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 1) #ifdef VIA1_iB1 #error "VIA1_iB1 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 0) #ifdef VIA1_iB0 #error "VIA1_iB0 defined but not used" #endif #endif typedef struct { ui5b T1C_F; /* Timer 1 Counter Fixed Point */ ui5b T2C_F; /* Timer 2 Counter Fixed Point */ ui3b ORB; /* Buffer B */ /* ui3b ORA_H; Buffer A with Handshake */ ui3b DDR_B; /* Data Direction Register B */ ui3b DDR_A; /* Data Direction Register A */ ui3b T1L_L; /* Timer 1 Latch Low */ ui3b T1L_H; /* Timer 1 Latch High */ ui3b T2L_L; /* Timer 2 Latch Low */ ui3b SR; /* Shift Register */ ui3b ACR; /* Auxiliary Control Register */ ui3b PCR; /* Peripheral Control Register */ ui3b IFR; /* Interrupt Flag Register */ ui3b IER; /* Interrupt Enable Register */ ui3b ORA; /* Buffer A */ } VIA1_Ty; LOCALVAR VIA1_Ty VIA1_D; #define kIntCA2 0 /* One_Second */ #define kIntCA1 1 /* Vertical_Blanking */ #define kIntSR 2 /* Keyboard_Data_Ready */ #define kIntCB2 3 /* Keyboard_Data */ #define kIntCB1 4 /* Keyboard_Clock */ #define kIntT2 5 /* Timer_2 */ #define kIntT1 6 /* Timer_1 */ #define VIA1_dolog (dbglog_HAVE && 0) /* VIA1_Get_ORA : VIA Get Port A Data */ /* This function queries VIA Port A interfaced hardware about their status */ LOCALFUNC ui3b VIA1_Get_ORA(ui3b Selection) { ui3b Value = (~ VIA1_ORA_CanIn) & Selection & VIA1_ORA_FloatVal; #if Ui3rTestBit(VIA1_ORA_CanIn, 7) if (Ui3rTestBit(Selection, 7)) { Value |= (VIA1_iA7 << 7); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 6) if (Ui3rTestBit(Selection, 6)) { Value |= (VIA1_iA6 << 6); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 5) if (Ui3rTestBit(Selection, 5)) { Value |= (VIA1_iA5 << 5); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 4) if (Ui3rTestBit(Selection, 4)) { Value |= (VIA1_iA4 << 4); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 3) if (Ui3rTestBit(Selection, 3)) { Value |= (VIA1_iA3 << 3); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 2) if (Ui3rTestBit(Selection, 2)) { Value |= (VIA1_iA2 << 2); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 1) if (Ui3rTestBit(Selection, 1)) { Value |= (VIA1_iA1 << 1); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 0) if (Ui3rTestBit(Selection, 0)) { Value |= (VIA1_iA0 << 0); } #endif return Value; } /* VIA1_Get_ORB : VIA Get Port B Data */ /* This function queries VIA Port B interfaced hardware about their status */ LOCALFUNC ui3b VIA1_Get_ORB(ui3b Selection) { ui3b Value = (~ VIA1_ORB_CanIn) & Selection & VIA1_ORB_FloatVal; #if Ui3rTestBit(VIA1_ORB_CanIn, 7) if (Ui3rTestBit(Selection, 7)) { Value |= (VIA1_iB7 << 7); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 6) if (Ui3rTestBit(Selection, 6)) { Value |= (VIA1_iB6 << 6); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 5) if (Ui3rTestBit(Selection, 5)) { Value |= (VIA1_iB5 << 5); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 4) if (Ui3rTestBit(Selection, 4)) { Value |= (VIA1_iB4 << 4); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 3) if (Ui3rTestBit(Selection, 3)) { Value |= (VIA1_iB3 << 3); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 2) if (Ui3rTestBit(Selection, 2)) { Value |= (VIA1_iB2 << 2); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 1) if (Ui3rTestBit(Selection, 1)) { Value |= (VIA1_iB1 << 1); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 0) if (Ui3rTestBit(Selection, 0)) { Value |= (VIA1_iB0 << 0); } #endif return Value; } #define ViaORcheckBit(p, x) \ (Ui3rTestBit(Selection, p) && \ ((v = (Data >> p) & 1) != x)) LOCALPROC VIA1_Put_ORA(ui3b Selection, ui3b Data) { #if 0 != VIA1_ORA_CanOut ui3b v; #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 7) if (ViaORcheckBit(7, VIA1_iA7)) { VIA1_iA7 = v; #ifdef VIA1_iA7_ChangeNtfy VIA1_iA7_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 6) if (ViaORcheckBit(6, VIA1_iA6)) { VIA1_iA6 = v; #ifdef VIA1_iA6_ChangeNtfy VIA1_iA6_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 5) if (ViaORcheckBit(5, VIA1_iA5)) { VIA1_iA5 = v; #ifdef VIA1_iA5_ChangeNtfy VIA1_iA5_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 4) if (ViaORcheckBit(4, VIA1_iA4)) { VIA1_iA4 = v; #ifdef VIA1_iA4_ChangeNtfy VIA1_iA4_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 3) if (ViaORcheckBit(3, VIA1_iA3)) { VIA1_iA3 = v; #ifdef VIA1_iA3_ChangeNtfy VIA1_iA3_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 2) if (ViaORcheckBit(2, VIA1_iA2)) { VIA1_iA2 = v; #ifdef VIA1_iA2_ChangeNtfy VIA1_iA2_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 1) if (ViaORcheckBit(1, VIA1_iA1)) { VIA1_iA1 = v; #ifdef VIA1_iA1_ChangeNtfy VIA1_iA1_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 0) if (ViaORcheckBit(0, VIA1_iA0)) { VIA1_iA0 = v; #ifdef VIA1_iA0_ChangeNtfy VIA1_iA0_ChangeNtfy(); #endif } #endif } LOCALPROC VIA1_Put_ORB(ui3b Selection, ui3b Data) { #if 0 != VIA1_ORB_CanOut ui3b v; #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 7) if (ViaORcheckBit(7, VIA1_iB7)) { VIA1_iB7 = v; #ifdef VIA1_iB7_ChangeNtfy VIA1_iB7_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 6) if (ViaORcheckBit(6, VIA1_iB6)) { VIA1_iB6 = v; #ifdef VIA1_iB6_ChangeNtfy VIA1_iB6_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 5) if (ViaORcheckBit(5, VIA1_iB5)) { VIA1_iB5 = v; #ifdef VIA1_iB5_ChangeNtfy VIA1_iB5_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 4) if (ViaORcheckBit(4, VIA1_iB4)) { VIA1_iB4 = v; #ifdef VIA1_iB4_ChangeNtfy VIA1_iB4_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 3) if (ViaORcheckBit(3, VIA1_iB3)) { VIA1_iB3 = v; #ifdef VIA1_iB3_ChangeNtfy VIA1_iB3_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 2) if (ViaORcheckBit(2, VIA1_iB2)) { VIA1_iB2 = v; #ifdef VIA1_iB2_ChangeNtfy VIA1_iB2_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 1) if (ViaORcheckBit(1, VIA1_iB1)) { VIA1_iB1 = v; #ifdef VIA1_iB1_ChangeNtfy VIA1_iB1_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 0) if (ViaORcheckBit(0, VIA1_iB0)) { VIA1_iB0 = v; #ifdef VIA1_iB0_ChangeNtfy VIA1_iB0_ChangeNtfy(); #endif } #endif } LOCALPROC VIA1_SetDDR_A(ui3b Data) { ui3b floatbits = VIA1_D.DDR_A & ~ Data; ui3b unfloatbits = Data & ~ VIA1_D.DDR_A; if (floatbits != 0) { VIA1_Put_ORA(floatbits, VIA1_ORA_FloatVal); } VIA1_D.DDR_A = Data; if (unfloatbits != 0) { VIA1_Put_ORA(unfloatbits, VIA1_D.ORA); } if ((Data & ~ VIA1_ORA_CanOut) != 0) { ReportAbnormal("Set VIA1_D.DDR_A unexpected direction"); } } LOCALPROC VIA1_SetDDR_B(ui3b Data) { ui3b floatbits = VIA1_D.DDR_B & ~ Data; ui3b unfloatbits = Data & ~ VIA1_D.DDR_B; if (floatbits != 0) { VIA1_Put_ORB(floatbits, VIA1_ORB_FloatVal); } VIA1_D.DDR_B = Data; if (unfloatbits != 0) { VIA1_Put_ORB(unfloatbits, VIA1_D.ORB); } if ((Data & ~ VIA1_ORB_CanOut) != 0) { ReportAbnormal("Set VIA1_D.DDR_B unexpected direction"); } } LOCALPROC VIA1_CheckInterruptFlag(void) { ui3b NewInterruptRequest = ((VIA1_D.IFR & VIA1_D.IER) != 0) ? 1 : 0; if (NewInterruptRequest != VIA1_InterruptRequest) { VIA1_InterruptRequest = NewInterruptRequest; #ifdef VIA1_interruptChngNtfy VIA1_interruptChngNtfy(); #endif } } LOCALVAR ui3b VIA1_T1_Active = 0; LOCALVAR ui3b VIA1_T2_Active = 0; LOCALVAR blnr VIA1_T1IntReady = falseblnr; LOCALPROC VIA1_Clear(void) { VIA1_D.ORA = 0; VIA1_D.DDR_A = 0; VIA1_D.ORB = 0; VIA1_D.DDR_B = 0; VIA1_D.T1L_L = VIA1_D.T1L_H = 0x00; VIA1_D.T2L_L = 0x00; VIA1_D.T1C_F = 0; VIA1_D.T2C_F = 0; VIA1_D.SR = VIA1_D.ACR = 0x00; VIA1_D.PCR = VIA1_D.IFR = VIA1_D.IER = 0x00; VIA1_T1_Active = VIA1_T2_Active = 0x00; VIA1_T1IntReady = falseblnr; } GLOBALPROC VIA1_Zap(void) { VIA1_Clear(); VIA1_InterruptRequest = 0; } GLOBALPROC VIA1_Reset(void) { VIA1_SetDDR_A(0); VIA1_SetDDR_B(0); VIA1_Clear(); VIA1_CheckInterruptFlag(); } LOCALPROC VIA1_SetInterruptFlag(ui3b VIA_Int) { VIA1_D.IFR |= ((ui3b)1 << VIA_Int); VIA1_CheckInterruptFlag(); } LOCALPROC VIA1_ClrInterruptFlag(ui3b VIA_Int) { VIA1_D.IFR &= ~ ((ui3b)1 << VIA_Int); VIA1_CheckInterruptFlag(); } #ifdef _VIA_Debug #include #endif GLOBALPROC VIA1_ShiftInData(ui3b v) { /* external hardware generates 8 pulses on CB1, writes 8 bits to CB2 */ ui3b ShiftMode = (VIA1_D.ACR & 0x1C) >> 2; if (ShiftMode != 3) { if (ShiftMode == 0) { /* happens on reset */ } else { ReportAbnormal("VIA Not ready to shift in"); } } else { VIA1_D.SR = v; VIA1_SetInterruptFlag(kIntSR); VIA1_SetInterruptFlag(kIntCB1); } } GLOBALFUNC ui3b VIA1_ShiftOutData(void) { /* external hardware generates 8 pulses on CB1, reads 8 bits from CB2 */ if (((VIA1_D.ACR & 0x1C) >> 2) != 7) { ReportAbnormal("VIA Not ready to shift out"); return 0; } else { VIA1_SetInterruptFlag(kIntSR); VIA1_SetInterruptFlag(kIntCB1); VIA1_iCB2 = (VIA1_D.SR & 1); return VIA1_D.SR; } } #define CyclesPerViaTime (10 * kMyClockMult) #define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime) LOCALVAR blnr VIA1_T1Running = trueblnr; LOCALVAR iCountt VIA1_T1LastTime = 0; GLOBALPROC VIA1_DoTimer1Check(void) { if (VIA1_T1Running) { iCountt NewTime = GetCuriCount(); iCountt deltaTime = (NewTime - VIA1_T1LastTime); if (deltaTime != 0) { ui5b Temp = VIA1_D.T1C_F; /* Get Timer 1 Counter */ ui5b deltaTemp = (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); /* may overflow */ ui5b NewTemp = Temp - deltaTemp; if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) || ((Temp <= deltaTemp) && (Temp != 0))) { if ((VIA1_D.ACR & 0x40) != 0) { /* Free Running? */ /* Reload Counter from Latches */ ui4b v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L; ui4b ntrans = 1 + ((v == 0) ? 0 : (((deltaTemp - Temp) / v) >> 16)); NewTemp += (((ui5b)v * ntrans) << 16); #if Ui3rTestBit(VIA1_ORB_CanOut, 7) if ((VIA1_D.ACR & 0x80) != 0) { /* invert ? */ if ((ntrans & 1) != 0) { VIA1_iB7 ^= 1; #ifdef VIA1_iB7_ChangeNtfy VIA1_iB7_ChangeNtfy(); #endif } } #endif VIA1_SetInterruptFlag(kIntT1); #if VIA1_dolog && 1 dbglog_StartLine(); dbglog_writeCStr("VIA1 Timer 1 Interrupt"); dbglog_writeReturn(); #endif } else { if (VIA1_T1_Active == 1) { VIA1_T1_Active = 0; VIA1_SetInterruptFlag(kIntT1); #if VIA1_dolog && 1 dbglog_StartLine(); dbglog_writeCStr("VIA1 Timer 1 Interrupt"); dbglog_writeReturn(); #endif } } } VIA1_D.T1C_F = NewTemp; VIA1_T1LastTime = NewTime; } VIA1_T1IntReady = falseblnr; if ((VIA1_D.IFR & (1 << kIntT1)) == 0) { if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) { ui5b NewTemp = VIA1_D.T1C_F; /* Get Timer 1 Counter */ ui5b NewTimer; #ifdef _VIA_Debug fprintf(stderr, "posting Timer1Check, %d, %d\n", Temp, GetCuriCount()); #endif if (NewTemp == 0) { NewTimer = (0x00010000UL * CyclesScaledPerViaTime); } else { NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) * CyclesPerViaTime; } ICT_add(kICT_VIA1_Timer1Check, NewTimer); VIA1_T1IntReady = trueblnr; } } } } LOCALPROC CheckT1IntReady(void) { if (VIA1_T1Running) { blnr NewT1IntReady = falseblnr; if ((VIA1_D.IFR & (1 << kIntT1)) == 0) { if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) { NewT1IntReady = trueblnr; } } if (VIA1_T1IntReady != NewT1IntReady) { VIA1_T1IntReady = NewT1IntReady; if (NewT1IntReady) { VIA1_DoTimer1Check(); } } } } GLOBALFUNC ui4b VIA1_GetT1InvertTime(void) { ui4b v; if ((VIA1_D.ACR & 0xC0) == 0xC0) { v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L; } else { v = 0; } return v; } LOCALVAR blnr VIA1_T2Running = trueblnr; LOCALVAR blnr VIA1_T2C_ShortTime = falseblnr; LOCALVAR iCountt VIA1_T2LastTime = 0; GLOBALPROC VIA1_DoTimer2Check(void) { if (VIA1_T2Running) { iCountt NewTime = GetCuriCount(); ui5b Temp = VIA1_D.T2C_F; /* Get Timer 2 Counter */ iCountt deltaTime = (NewTime - VIA1_T2LastTime); ui5b deltaTemp = (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); /* may overflow */ ui5b NewTemp = Temp - deltaTemp; if (VIA1_T2_Active == 1) { if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) || ((Temp <= deltaTemp) && (Temp != 0))) { VIA1_T2C_ShortTime = falseblnr; VIA1_T2_Active = 0; VIA1_SetInterruptFlag(kIntT2); #if VIA1_dolog && 1 dbglog_StartLine(); dbglog_writeCStr("VIA1 Timer 2 Interrupt"); dbglog_writeReturn(); #endif } else { ui5b NewTimer; #ifdef _VIA_Debug fprintf(stderr, "posting Timer2Check, %d, %d\n", Temp, GetCuriCount()); #endif if (NewTemp == 0) { NewTimer = (0x00010000UL * CyclesScaledPerViaTime); } else { NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) * CyclesPerViaTime; } ICT_add(kICT_VIA1_Timer2Check, NewTimer); } } VIA1_D.T2C_F = NewTemp; VIA1_T2LastTime = NewTime; } } #define kORB 0x00 #define kORA_H 0x01 #define kDDR_B 0x02 #define kDDR_A 0x03 #define kT1C_L 0x04 #define kT1C_H 0x05 #define kT1L_L 0x06 #define kT1L_H 0x07 #define kT2_L 0x08 #define kT2_H 0x09 #define kSR 0x0A #define kACR 0x0B #define kPCR 0x0C #define kIFR 0x0D #define kIER 0x0E #define kORA 0x0F GLOBALFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr) { switch (addr) { case kORB : #if VIA1_CB2modesAllowed != 0x01 if ((VIA1_D.PCR & 0xE0) == 0) #endif { VIA1_ClrInterruptFlag(kIntCB2); } VIA1_ClrInterruptFlag(kIntCB1); if (WriteMem) { VIA1_D.ORB = Data; VIA1_Put_ORB(VIA1_D.DDR_B, VIA1_D.ORB); } else { Data = (VIA1_D.ORB & VIA1_D.DDR_B) | VIA1_Get_ORB(~ VIA1_D.DDR_B); } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kORB", Data, WriteMem); #endif break; case kDDR_B : if (WriteMem) { VIA1_SetDDR_B(Data); } else { Data = VIA1_D.DDR_B; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kDDR_B", Data, WriteMem); #endif break; case kDDR_A : if (WriteMem) { VIA1_SetDDR_A(Data); } else { Data = VIA1_D.DDR_A; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kDDR_A", Data, WriteMem); #endif break; case kT1C_L : if (WriteMem) { VIA1_D.T1L_L = Data; } else { VIA1_ClrInterruptFlag(kIntT1); VIA1_DoTimer1Check(); Data = (VIA1_D.T1C_F & 0x00FF0000) >> 16; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1C_L", Data, WriteMem); #endif break; case kT1C_H : if (WriteMem) { VIA1_D.T1L_H = Data; VIA1_ClrInterruptFlag(kIntT1); VIA1_D.T1C_F = (Data << 24) + (VIA1_D.T1L_L << 16); if ((VIA1_D.ACR & 0x40) == 0) { VIA1_T1_Active = 1; } VIA1_T1LastTime = GetCuriCount(); VIA1_DoTimer1Check(); } else { VIA1_DoTimer1Check(); Data = (VIA1_D.T1C_F & 0xFF000000) >> 24; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1C_H", Data, WriteMem); #endif break; case kT1L_L : if (WriteMem) { VIA1_D.T1L_L = Data; } else { Data = VIA1_D.T1L_L; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1L_L", Data, WriteMem); #endif break; case kT1L_H : if (WriteMem) { VIA1_D.T1L_H = Data; } else { Data = VIA1_D.T1L_H; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1L_H", Data, WriteMem); #endif break; case kT2_L : if (WriteMem) { VIA1_D.T2L_L = Data; } else { VIA1_ClrInterruptFlag(kIntT2); VIA1_DoTimer2Check(); Data = (VIA1_D.T2C_F & 0x00FF0000) >> 16; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT2_L", Data, WriteMem); #endif break; case kT2_H : if (WriteMem) { VIA1_D.T2C_F = (Data << 24) + (VIA1_D.T2L_L << 16); VIA1_ClrInterruptFlag(kIntT2); VIA1_T2_Active = 1; if ((VIA1_D.T2C_F < (128UL << 16)) && (VIA1_D.T2C_F != 0)) { VIA1_T2C_ShortTime = trueblnr; VIA1_T2Running = trueblnr; /* Running too many instructions during a short timer interval can crash when playing sounds in System 7. So in this case don't let timer pause. */ } VIA1_T2LastTime = GetCuriCount(); VIA1_DoTimer2Check(); } else { VIA1_DoTimer2Check(); Data = (VIA1_D.T2C_F & 0xFF000000) >> 24; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT2_H", Data, WriteMem); #endif break; case kSR: #ifdef _VIA_Debug fprintf(stderr, "VIA1_D.SR: %d, %d, %d\n", WriteMem, ((VIA1_D.ACR & 0x1C) >> 2), Data); #endif if (WriteMem) { VIA1_D.SR = Data; } VIA1_ClrInterruptFlag(kIntSR); switch ((VIA1_D.ACR & 0x1C) >> 2) { case 3 : /* Shifting In */ break; case 6 : /* shift out under o2 clock */ if ((! WriteMem) || (VIA1_D.SR != 0)) { ReportAbnormal("VIA shift mode 6, non zero"); } else { #ifdef _VIA_Debug fprintf(stderr, "posting Foo2Task\n"); #endif if (VIA1_iCB2 != 0) { VIA1_iCB2 = 0; #ifdef VIA1_iCB2_ChangeNtfy VIA1_iCB2_ChangeNtfy(); #endif } } #if 0 /* possibly should do this. seems not to affect anything. */ VIA1_SetInterruptFlag(kIntSR); /* don't wait */ #endif break; case 7 : /* Shifting Out */ break; } if (! WriteMem) { Data = VIA1_D.SR; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kSR", Data, WriteMem); #endif break; case kACR: if (WriteMem) { #if 1 if ((VIA1_D.ACR & 0x10) != ((ui3b)Data & 0x10)) { /* shift direction has changed */ if ((Data & 0x10) == 0) { /* no longer an output, set data to float value */ if (VIA1_iCB2 == 0) { VIA1_iCB2 = 1; #ifdef VIA1_iCB2_ChangeNtfy VIA1_iCB2_ChangeNtfy(); #endif } } } #endif VIA1_D.ACR = Data; if ((VIA1_D.ACR & 0x20) != 0) { /* Not pulse counting? */ ReportAbnormal( "Set VIA1_D.ACR T2 Timer pulse counting"); } switch ((VIA1_D.ACR & 0xC0) >> 6) { /* case 1: happens in early System 6 */ case 2: ReportAbnormal( "Set VIA1_D.ACR T1 Timer mode 2"); break; } CheckT1IntReady(); switch ((VIA1_D.ACR & 0x1C) >> 2) { case 0: /* this isn't sufficient */ VIA1_ClrInterruptFlag(kIntSR); break; case 1: case 2: case 4: case 5: ReportAbnormal( "Set VIA1_D.ACR shift mode 1,2,4,5"); break; default: break; } if ((VIA1_D.ACR & 0x03) != 0) { ReportAbnormal( "Set VIA1_D.ACR T2 Timer latching enabled"); } } else { Data = VIA1_D.ACR; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kACR", Data, WriteMem); #endif break; case kPCR: if (WriteMem) { VIA1_D.PCR = Data; #define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0) if (! Ui3rSetContains(VIA1_CB2modesAllowed, (VIA1_D.PCR >> 5) & 0x07)) { ReportAbnormal("Set VIA1_D.PCR CB2 Control mode?"); } if ((VIA1_D.PCR & 0x10) != 0) { ReportAbnormal( "Set VIA1_D.PCR CB1 INTERRUPT CONTROL?"); } if (! Ui3rSetContains(VIA1_CA2modesAllowed, (VIA1_D.PCR >> 1) & 0x07)) { ReportAbnormal( "Set VIA1_D.PCR CA2 INTERRUPT CONTROL?"); } if ((VIA1_D.PCR & 0x01) != 0) { ReportAbnormal( "Set VIA1_D.PCR CA1 INTERRUPT CONTROL?"); } } else { Data = VIA1_D.PCR; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kPCR", Data, WriteMem); #endif break; case kIFR: if (WriteMem) { VIA1_D.IFR = VIA1_D.IFR & ((~ Data) & 0x7F); /* Clear Flag Bits */ VIA1_CheckInterruptFlag(); CheckT1IntReady(); } else { Data = VIA1_D.IFR; if ((VIA1_D.IFR & VIA1_D.IER) != 0) { Data |= 0x80; } } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kIFR", Data, WriteMem); #endif break; case kIER : if (WriteMem) { if ((Data & 0x80) == 0) { VIA1_D.IER = VIA1_D.IER & ((~ Data) & 0x7F); /* Clear Enable Bits */ #if 0 != VIA1_IER_Never0 /* of course, will be 0 initially, this just checks not cleared later. */ if ((Data & VIA1_IER_Never0) != 0) { ReportAbnormal("IER Never0 clr"); } #endif } else { VIA1_D.IER = VIA1_D.IER | (Data & 0x7F); /* Set Enable Bits */ #if 0 != VIA1_IER_Never1 if ((VIA1_D.IER & VIA1_IER_Never1) != 0) { ReportAbnormal("IER Never1 set"); } #endif } VIA1_CheckInterruptFlag(); } else { Data = VIA1_D.IER | 0x80; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kIER", Data, WriteMem); #endif break; case kORA : case kORA_H : if ((VIA1_D.PCR & 0xE) == 0) { VIA1_ClrInterruptFlag(kIntCA2); } VIA1_ClrInterruptFlag(kIntCA1); if (WriteMem) { VIA1_D.ORA = Data; VIA1_Put_ORA(VIA1_D.DDR_A, VIA1_D.ORA); } else { Data = (VIA1_D.ORA & VIA1_D.DDR_A) | VIA1_Get_ORA(~ VIA1_D.DDR_A); } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kORA", Data, WriteMem); #endif break; } return Data; } GLOBALPROC VIA1_ExtraTimeBegin(void) { if (VIA1_T1Running) { VIA1_DoTimer1Check(); /* run up to this moment */ VIA1_T1Running = falseblnr; } if (VIA1_T2Running & (! VIA1_T2C_ShortTime)) { VIA1_DoTimer2Check(); /* run up to this moment */ VIA1_T2Running = falseblnr; } } GLOBALPROC VIA1_ExtraTimeEnd(void) { if (! VIA1_T1Running) { VIA1_T1Running = trueblnr; VIA1_T1LastTime = GetCuriCount(); VIA1_DoTimer1Check(); } if (! VIA1_T2Running) { VIA1_T2Running = trueblnr; VIA1_T2LastTime = GetCuriCount(); VIA1_DoTimer2Check(); } } /* VIA Interrupt Interface */ #ifdef VIA1_iCA1_PulseNtfy GLOBALPROC VIA1_iCA1_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCA1); } #endif #ifdef VIA1_iCA2_PulseNtfy GLOBALPROC VIA1_iCA2_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCA2); } #endif #ifdef VIA1_iCB1_PulseNtfy GLOBALPROC VIA1_iCB1_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCB1); } #endif #ifdef VIA1_iCB2_PulseNtfy GLOBALPROC VIA1_iCB2_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCB2); } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIAEMDEV.h b/Mini vMac/mnvm_core/VIAEMDEV.h new file mode 100755 index 0000000..1773257 --- /dev/null +++ b/Mini vMac/mnvm_core/VIAEMDEV.h @@ -0,0 +1 @@ +/* VIAEMDEV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file 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 license for more details. */ #ifdef VIAEMDEV_H #error "header already included" #else #define VIAEMDEV_H #endif EXPORTPROC VIA1_Zap(void); EXPORTPROC VIA1_Reset(void); EXPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr); EXPORTPROC VIA1_ExtraTimeBegin(void); EXPORTPROC VIA1_ExtraTimeEnd(void); #ifdef VIA1_iCA1_PulseNtfy EXPORTPROC VIA1_iCA1_PulseNtfy(void); #endif #ifdef VIA1_iCA2_PulseNtfy EXPORTPROC VIA1_iCA2_PulseNtfy(void); #endif #ifdef VIA1_iCB1_PulseNtfy EXPORTPROC VIA1_iCB1_PulseNtfy(void); #endif #ifdef VIA1_iCB2_PulseNtfy EXPORTPROC VIA1_iCB2_PulseNtfy(void); #endif EXPORTPROC VIA1_DoTimer1Check(void); EXPORTPROC VIA1_DoTimer2Check(void); EXPORTFUNC ui4b VIA1_GetT1InvertTime(void); EXPORTPROC VIA1_ShiftInData(ui3b v); EXPORTFUNC ui3b VIA1_ShiftOutData(void); \ No newline at end of file