diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..9b3a92d
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,197 @@
+name: Create Release
+
+on: push
+
+jobs:
+ # Maybe this should go after the successful build :P
+ create-release:
+ name: Create Release Job
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1.0.0
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: Release ${{ github.ref }}-testing
+ draft: true
+ prerelease: true
+ # Workaround to preserve the release_url generated above for our next job
+ - name: Store Release URL
+ env:
+ UPLOAD_URL: ${{ toJson( steps.create_release.outputs.upload_url )}}
+ run: |
+ echo "$UPLOAD_URL" > release_url.txt
+ echo "UPLOAD_URL= $UPLOAD_URL"
+ - name: Upload URL for later use
+ uses: actions/upload-artifact@v1
+ with:
+ name: data
+ path: release_url.txt
+
+ build-and-upload:
+ name: Build
+ needs: create-release
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ macos-latest, ubuntu-latest ]
+ # not working
+ #os: [ windows-latest ]
+ steps:
+ - name: Download Release Data
+ uses: actions/download-artifact@v1
+ with:
+ name: data
+ - name: Set Release Data in Outputs
+ id: release_data
+ shell: bash
+ run: |
+ URL=`cat data/release_url.txt | tr -d '"'`
+ echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
+ echo ::set-output name=URL::$URL
+ echo "SOURCE_TAG::${GITHUB_REF#refs/tags/}"
+ echo "URL::$URL"
+ - uses: actions/checkout@v1
+ - uses: ilammy/msvc-dev-cmd@v1
+
+ - name: Prep MacOSX
+ if: matrix.os == 'macos-latest'
+ shell: bash
+ run: |
+ export MACOSX_DEPLOYMENT_TARGET=10.14
+ # see: https://gist.github.com/fabianfett/fd811d7921eb856bb100c5c15565077f
+ #sudo xcode-select -s /Applications/Xcode_11.app/Contents/Developer
+ xcode-select -p
+ brew update
+
+ # BREW PACKAGES - Note we only seem to need to get the ones we link against for Mojave
+ # dylibbundler--0.4.5.mojave.bottle.1.tar.gz
+ # sdl2--2.0.10.mojave.bottle.1.tar.gz <--
+ # freetype--2.10.1.mojave.bottle.1.tar.gz <--
+ # sdl2_image--2.0.5.mojave.bottle.1.tar.gz <--
+ # pkg-config--0.29.2.mojave.bottle.tar.gz
+
+ brew install dylibbundler
+ brew install pkg-config
+
+ curl -L https://bintray.com/homebrew/bottles/download_file?file_path=sdl2-2.0.10.mojave.bottle.tar.gz -o sdl2-2.0.10.mojave.bottle.tar.gz
+ brew install -f sdl2-2.0.10.mojave.bottle.tar.gz
+ curl -L https://bintray.com/homebrew/bottles/download_file?file_path=sdl2_image-2.0.5.mojave.bottle.tar.gz -o sdl2_image-2.0.5.mojave.bottle.tar.gz
+ brew install -f sdl2_image-2.0.5.mojave.bottle.tar.gz
+ #curl -L https://bintray.com/homebrew/bottles/download_file?file_path=freetype-2.10.1.mojave.bottle.tar.gz -o freetype-2.10.1.mojave.bottle.tar.gz
+ #brew install -f freetype-2.10.1.mojave.bottle.tar.gz
+
+ # - name: Prep windows
+ # if: matrix.os == 'windows-latest'
+ # shell: bash
+ # run: |
+ # pacman -S re2c mingw-w64-i686-cmake mingw-w64-i686-SDL2 mingw-w64-i686-SDL2_image mingw-w64-i686-freetype
+
+ - name: Prep Ubuntu
+ if: matrix.os == 'ubuntu-latest'
+ shell: bash
+ run: |
+ sudo apt-get -y update
+ #sudo apt-get -y upgrade
+ sudo apt-get -y install libpcap0.8-dev libfreetype6-dev libsdl2-dev libsdl2-image-dev
+
+ - name: Build windows
+ if: matrix.os == 'windows-latest'
+ run: |
+ mkdir build
+ cd build
+ cmake ..
+ dir
+ msbuild ALL_BUILD.vcxproj
+
+ - name: Build MacOS/Ubuntu
+ if: matrix.os != 'windows-latest'
+ shell: bash
+ run: |
+ echo "${{ matrix.os }} BUILD"
+ mkdir build ; cd build
+ cmake ..
+ make
+ pwd ; ls -al
+
+ # - name: Package NonWindows
+ # if: matrix.os != 'windows-latest'
+ # run: |
+ # zip --junk-paths merlin32.zip Source/merlin32 README.md
+ - name: Set VERSION
+ id: version
+ run: |
+ VERSION=`cat build/src/version.txt`
+ echo ::set-output name=VERSION::$VERSION
+ echo "VERSION::$VERSION"
+
+ - name: Package MacOS
+ if: matrix.os == 'macos-latest'
+ run: cd build ; sh ../scripts/package-osx.sh
+
+ - name: Package Ubuntu
+ if: matrix.os == 'ubuntu-latest'
+ env:
+ PACKAGE_NAME: gsplus-ubuntu
+ run: |
+ mkdir -p $PACKAGE_NAME
+ mkdir -p $PACKAGE_NAME/doc
+ cp build/src/GSplus $PACKAGE_NAME/gsplus
+ cp build/src/to_pro $PACKAGE_NAME/to_pro
+ cp src/assets/config.txt $PACKAGE_NAME
+ cp LICENSE.txt $PACKAGE_NAME/doc/
+ cp doc/gsplusmanual.pdf $PACKAGE_NAME/doc/
+ cp doc/README.txt $PACKAGE_NAME/doc/
+ tar -cvjf $PACKAGE_NAME.tar.bz2 $PACKAGE_NAME
+
+ - name: Package .deb
+ if: matrix.os == 'ubuntu-latest'
+ env:
+ PACKAGE_NAME: gsplus_${{ steps.version.outputs.VERSION }}-0
+ run: |
+ #PACKAGE_NAME: gsplus_$VERSION-0
+ mkdir -p $PACKAGE_NAME/usr/local/bin
+ mkdir -p $PACKAGE_NAME/DEBIAN
+ cp build/src/GSplus $PACKAGE_NAME/usr/local/bin/gsplus
+ cp build/src/assets/control $PACKAGE_NAME/DEBIAN
+ dpkg-deb --build $PACKAGE_NAME
+ ls -al
+ pwd
+
+ - name: Upload Release Asset MacOSX
+ if: matrix.os == 'macos-latest'
+ #id: upload-release-asset
+ uses: actions/upload-release-asset@v1.0.1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.release_data.outputs.URL }}
+ asset_path: ./build/GSplus-Install.dmg
+ asset_name: ${{ format('gsplus-macos-{0}.dmg', steps.version.outputs.VERSION ) }}
+ asset_content_type: application/x-apple-diskimage
+
+ - name: Upload Release Asset Ubuntu
+ if: matrix.os == 'ubuntu-latest'
+ uses: actions/upload-release-asset@v1.0.1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.release_data.outputs.URL }}
+ asset_path: ./gsplus-ubuntu.tar.bz2
+ asset_name: ${{ format('gsplus-ubuntu-{0}.tar.bz2', steps.version.outputs.VERSION ) }}
+ asset_content_type: application/x-bzip2
+
+ - name: Upload Release Asset .deb
+ if: matrix.os == 'ubuntu-latest'
+ uses: actions/upload-release-asset@v1.0.1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.release_data.outputs.URL }}
+ asset_path: ${{ format('./gsplus_{0}-0.deb', steps.version.outputs.VERSION ) }}
+ asset_name: ${{ format('gsplus_{0}-0.deb', steps.version.outputs.VERSION ) }}
+ asset_content_type: application/vnd.debian.binary-package
diff --git a/.gitignore b/.gitignore
index d52c73c..a1abe3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,5 @@ images/
screens/
# build tools that are often kept/tested locally as well as on the ci machines
+build/
yoursway-create-dmg/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..14d180e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "cmake/sdl2"]
+ path = cmake/sdl2
+ url = https://gitlab.com/aminosbh/sdl2-cmake-modules.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ee2b5eb
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.10)
+
+# set the project name and version
+project(gsplus VERSION 0.15)
+
+add_subdirectory(src)
+
+
+
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 33eb373..a145d24 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -1,6 +1,6 @@
GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey
-Copyright (C) 2016 - 2018 Dagen Brock
+Copyright (C) 2016 - 2020 Dagen Brock
Copyright (C) 2010 - 2014 GSport contributors
Copyright (C) 2003 Kent Dickey
diff --git a/assets/Info.plist b/assets/Info.plist
deleted file mode 100644
index e0b8c7a..0000000
--- a/assets/Info.plist
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- gsplus
- CFBundleGetInfoString
- 0.14, Copyright 2018 Dagen Brock
- CFBundleIconFile
- gsp-icons.icns
- CFBundleIdentifier
- com.dagenbrock.gsplus
- CFBundleDocumentTypes
-
-
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 0.14
- CFBundleSignature
- gsplus
- CFBundleVersion
- 0.14
- NSHumanReadableCopyright
- Copyright 2018 Dagen Brock
- LSMinimumSystemVersion
- 10.3
-
-
diff --git a/cmake/sdl2 b/cmake/sdl2
new file mode 160000
index 0000000..ad006a3
--- /dev/null
+++ b/cmake/sdl2
@@ -0,0 +1 @@
+Subproject commit ad006a3daae65a612ed87415037e32188b81071e
diff --git a/doc/Developer-QuickStart-MacOSX.txt b/doc/Developer-QuickStart-MacOSX.txt
index b5e41c6..99f8257 100644
--- a/doc/Developer-QuickStart-MacOSX.txt
+++ b/doc/Developer-QuickStart-MacOSX.txt
@@ -23,3 +23,7 @@ git clone git@github.com:digarok/gsplus.git
cd gsplus/src
ln -s vars_osx_sdl2 vars
make clean ; make
+
+
+# Packaging
+brew install dylibbundler
diff --git a/make_dist_mac.sh b/make_dist_mac.sh
deleted file mode 100755
index 502e993..0000000
--- a/make_dist_mac.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-DEXTRAS=gsplus-osx/
-DDIR=$DEXTRAS/GSplus.app
-ADIR=assets
-mkdir -p $DEXTRAS/license
-mkdir -p $DDIR/Contents/MacOS
-mkdir -p $DDIR/Contents/Resources
-
-cp gsplus $DDIR/Contents/MacOS
-cp config.txt $DDIR/Contents/MacOS
-cp $ADIR/Info.plist $DDIR/Contents
-cp $ADIR/gsp-icons.icns $DDIR/Contents/Resources
-dylibbundler -od -b -x $DDIR/Contents/MacOS/gsplus -d $DDIR/Contents/libs/
-
-# files to include in dmg
-cp doc/gsplusmanual.pdf $DEXTRAS
-cp doc/README.txt $DEXTRAS
-cp LICENSE.txt $DEXTRAS/license
-cp COPYRIGHT.txt $DEXTRAS/license
-
-# packaging now in DMG script
diff --git a/make_dmg_mac.sh b/make_dmg_mac.sh
deleted file mode 100755
index f0181bb..0000000
--- a/make_dmg_mac.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-git clone https://github.com/andreyvit/yoursway-create-dmg.git
-cd yoursway-create-dmg
-
-test -f GSplus-Install.dmg && rm GSplus-Install.dmg
-./create-dmg \
- --volname "GSplus" \
- --volicon "../assets/gsp-dmg-icons.icns" \
- --background "../assets/gsback.png" \
- --window-pos 200 120 \
- --window-size 710 600 \
- --icon-size 64 \
- --icon GSplus.app 250 210 \
- --hide-extension GSplus.app \
- --app-drop-link 440 210 \
- --icon README.txt 225 350 \
- --icon gsplusmanual.pdf 350 350 \
- --icon license 470 350 \
- GSplus-Install.dmg \
- ../gsplus-osx/
-cp GSplus-Install.dmg ..
diff --git a/scripts/package-osx.sh b/scripts/package-osx.sh
new file mode 100755
index 0000000..efc2708
--- /dev/null
+++ b/scripts/package-osx.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+# run me from `build` subdirectory
+
+# Create package directory and put any remaining files in place
+PDIR=package-osx
+rm -rf $PDIR #start empty
+mkdir $PDIR
+cp -r ../build/src/GSplus.app $PDIR
+
+DDIR=$PDIR/GSplus.app
+
+mkdir -p $PDIR/license
+cp ../LICENSE.txt $PDIR/license
+cp ../COPYRIGHT.txt $PDIR/license
+cp ../doc/gsplusmanual.pdf $PDIR
+cp ../doc/README.txt $PDIR
+
+# Bundle dynamic libraries
+dylibbundler -od -b -x $DDIR/Contents/MacOS/gsplus -d $DDIR/Contents/libs/
+
+
+
+
+
+# taken out DMG CI/CD for now as it requires keychain/UI interaction :(
+#exit
+
+# Make DMG
+git clone https://github.com/digarok/create-dmg.git
+cd create-dmg
+
+test -f GSplus-Install.dmg && rm GSplus-Install.dmg
+./create-dmg \
+ --volname "GSplus" \
+ --volicon "../../assets/gsp-dmg-icons.icns" \
+ --background "../../assets/gsback.png" \
+ --window-pos 200 120 \
+ --window-size 710 600 \
+ --icon-size 64 \
+ --icon GSplus.app 250 210 \
+ --hide-extension GSplus.app \
+ --app-drop-link 440 210 \
+ --icon README.txt 225 350 \
+ --icon gsplusmanual.pdf 350 350 \
+ --icon license 470 350 \
+ --skip-jenkins \
+ GSplus-Install.dmg \
+ ../package-osx/
+mv GSplus-Install.dmg ..
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..3bf9d96
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,265 @@
+
+INCLUDE (CheckFunctionExists)
+INCLUDE (CheckLibraryExists)
+INCLUDE (CheckTypeSize)
+INCLUDE (CheckIncludeFile)
+INCLUDE (CheckCSourceCompiles)
+
+INCLUDE (FindPkgConfig)
+INCLUDE (TestBigEndian)
+
+
+set(PACKAGE_NAME "GSplus")
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD_REQUIRED TRUE)
+
+set(__MSVC__ ${MSVC})
+set(__CLANG__ FALSE)
+set(__GCC__ FALSE)
+
+if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
+ set(__CLANG__ TRUE)
+endif()
+
+if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
+ set(__GCC__ TRUE)
+endif()
+
+if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
+endif()
+
+if(__CLANG__)
+ add_compile_options(
+ -Wall -fomit-frame-pointer
+ )
+endif()
+
+
+if(__GCC__)
+ add_compile_options(
+ -Wall -fomit-frame-pointer
+ )
+endif()
+
+
+TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
+if(NOT IS_BIG_ENDIAN)
+ add_definitions(-DGSPLUS_LITTLE_ENDIAN)
+endif()
+
+
+pkg_check_modules(SDL2 sdl2)
+pkg_check_modules(FREETYPE2 freetype2)
+
+
+find_program(PERL perl)
+
+if (PERL-NOTFOUND)
+ message(FATAL_ERROR "unable to find perl")
+endif()
+
+
+#
+# run ccmake, cmake -LH, or cmake -D...
+#
+set(DRIVER "SDL" CACHE STRING "Driver (SDL, X11, WIN32, FB, or HEADLESS")
+option(WITH_DEBUGGER "Enable the debugger" OFF)
+option(WITH_HOST_FST "Enable host fst support" ON)
+option(TOGGLE_STATUS "Enable F10 Toggle Status support (win32/x11)" OFF)
+option(WITH_RAWNET "Enable Uthernet emulation" OFF)
+option(WITH_ATBRIDGE "Enable AT Bridge" OFF)
+option(WITH_BACKTRACE "Enable PC Backtracing" OFF)
+option(WITH_STATIC "Enable static link" OFF)
+set(READLINE "AUTO" CACHE STRING "Readline library (AUTO, NONE, READLINE, LIBEDIT)")
+
+set(CMAKE_REQUIRED_INCLUDES string.h)
+check_function_exists(strcasecmp HAVE_STRCASECMP)
+check_function_exists(strncasecmp HAVE_STRNCASECMP)
+check_function_exists(strcasestr HAVE_STRCASESTR)
+
+configure_file(string_extra.h.in string_extra.h)
+configure_file(version.h.in version.h)
+configure_file(version.txt.in version.txt)
+configure_file(assets/control.in assets/control)
+
+set(generated_headers 8inst_c.h 16inst_c.h 8inst_s.h 16inst_s.h size_c.h size_s.h 8size_s.h 16size_s.h)
+add_custom_command(
+ OUTPUT 8inst_c.h 16inst_c.h 8inst_s.h ${CMAKE_CURRENT_BINARY_DIR}/16inst_s.h
+ COMMAND perl make_inst c 8 instable.h > ${CMAKE_CURRENT_BINARY_DIR}/8inst_c.h
+ COMMAND perl make_inst c 16 instable.h > ${CMAKE_CURRENT_BINARY_DIR}/16inst_c.h
+ COMMAND perl make_inst s 8 instable.h > ${CMAKE_CURRENT_BINARY_DIR}/8inst_s.h
+ COMMAND perl make_inst s 16 instable.h > ${CMAKE_CURRENT_BINARY_DIR}/16inst_s.h
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/instable.h
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+
+add_custom_command(
+ OUTPUT size_c.h size_s.h 8size_s.h 16size_s.h
+ COMMAND perl make_size c size_tab.h > ${CMAKE_CURRENT_BINARY_DIR}/size_c.h
+ COMMAND perl make_size s size_tab.h > ${CMAKE_CURRENT_BINARY_DIR}/size_s.h
+ COMMAND perl make_size 8 size_tab.h > ${CMAKE_CURRENT_BINARY_DIR}/8size_s.h
+ COMMAND perl make_size 16 size_tab.h > ${CMAKE_CURRENT_BINARY_DIR}/16size_s.h
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/size_tab.h
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+
+if (WITH_STATIC)
+ if(__CLANG__ OR __GCC__)
+ #add_link_options(-static) # 3.13
+ link_libraries(-static)
+ endif()
+endif()
+
+
+add_executable(to_pro to_pro.c)
+#add_executable(partls partls.c)
+
+add_subdirectory(atbridge)
+#add_subdirectory(tfe)
+add_subdirectory(rawnet)
+
+if (DRIVER MATCHES "SDL")
+ set(driver_code sdl2_driver.c sdl2snd_driver.c)
+elseif(DRIVER MATCHES "X11")
+ set(driver_code xdriver.c)
+elseif(DRIVER MATCHES "FB")
+ set(driver_code fbdriver.c)
+elseif(DRIVER MATCHES "WIN32")
+ set(driver_code win32snd_driver.c win_console.c win_generic.c)
+elseif(DRIVER MATCHES "HEADLESS")
+ set(driver_code headless_driver.c)
+else()
+ message(FATAL_ERROR "Invalid driver ${DRIVER}")
+endif()
+
+if (WIN32)
+ set(host_fst_code host_common.c host_mli.c win32_host_fst.c win32_host_common.c)
+else()
+ set(host_fst_code host_common.c host_mli.c host_fst.c unix_host_common.c)
+endif()
+
+set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "" FORCE)
+
+# https://cmake.org/cmake/help/latest/prop_tgt/MACOSX_BUNDLE_INFO_PLIST.html
+set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_VERSION}, Copyright 2020 Dagen Brock")
+set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2020 Dagen Brock")
+set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION})
+set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
+set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
+set(MACOSX_BUNDLE_ICON_FILE gsp-icons.icns)
+set(MACOSX_BUNDLE_GUI_IDENTIFIER com.dagenbrock.gsplus)
+
+
+# https://cmake.org/Wiki/CMake:Bundles_And_Frameworks
+# OS X properties.
+add_executable(GSplus WIN32 MACOSX_BUNDLE
+ adb.c clock.c config.c engine_c.c scc.c iwm.c
+ joystick_driver.c moremem.c paddles.c parallel.c printer.cpp sim65816.c
+ smartport.c sound.c sound_driver.c video.c scc_socket_driver.c glog.c
+ imagewriter.cpp scc_imagewriter.c scc_llap.c options.c
+
+ string_extra.c
+ dis.c
+ debug.c
+ #$<$:debug.c>
+
+ $<$:${host_fst_code}>
+ ${driver_code}
+ ${generated_headers}
+
+
+ $<$:scc_windriver.c>
+ $<$:win32.rc>
+ $<$:assets/config.txt>
+ $<$:assets/gsp-icons.icns>
+ $<$:assets/GSBug.Templates>
+ $<$:assets/NList.Data>
+ $<$:fix_mac_menu.m>
+)
+
+
+SET_SOURCE_FILES_PROPERTIES(
+ assets/gsp-icons.icns
+ PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources
+)
+
+SET_SOURCE_FILES_PROPERTIES(
+ assets/GSBug.Templates
+ assets/NList.Data
+ assets/config.txt
+ PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources
+)
+
+
+if(APPLE)
+ add_custom_command(TARGET GSplus POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${CMAKE_CURRENT_BINARY_DIR}/rawnet/vmnet_helper"
+ "${CMAKE_CURRENT_BINARY_DIR}/GSplus.app/Contents/MacOS/vmnet_helper"
+ )
+ add_dependencies(GSplus vmnet_helper)
+endif()
+# SET_SOURCE_FILES_PROPERTIES(vmnet_helper PROPERTIES MACOSX_PACKAGE_LOCATION MacOS)
+
+
+if (WITH_RAWNET)
+ target_link_libraries(GSplus rawnet)
+endif()
+
+if (WITH_ATBRIDGE)
+ target_link_libraries(GSplus atbridge)
+endif()
+
+if (WIN32)
+ target_link_libraries(GSplus comdlg32 Shlwapi IPHlpApi
+ winmm gdi32 dsound comctl32 ws2_32 shell32
+ )
+endif()
+
+if (DRIVER MATCHES "SDL")
+ target_link_libraries(GSplus ${SDL2_LDFLAGS} ${FREETYPE2_LDFLAGS} SDL2_image)
+ target_compile_options(GSplus PUBLIC ${SDL2_CFLAGS} ${FREETYPE2_CFLAGS} -DHAVE_SDL)
+endif()
+
+if (APPLE)
+ target_link_libraries(GSplus "-framework Cocoa")
+endif()
+
+if (TOGGLE_STATUS)
+ target_compile_definitions(GSplus PUBLIC TOGGLE_STATUS)
+endif()
+
+if (WITH_BACKTRACE)
+ target_compile_definitions(GSplus PUBLIC GSPLUS_BACKTRACE)
+endif()
+
+if (WITH_DEBUGGER)
+ target_compile_definitions(GSplus PRIVATE GSPLUS_DEBUGGER)
+endif()
+
+
+
+#if (APPLE AND DRIVER MATCHES "SDL")
+# target_compile_options(GSplus PRIVATE -F${CMAKE_CURRENT_SOURCE_DIR} )
+# target_link_libraries(GSplus -F${CMAKE_CURRENT_SOURCE_DIR} "-framework SDL2" -Wl,-rpath,@executable_path/../Frameworks)
+#endif()
+
+
+if (APPLE)
+ add_custom_target(bundle
+ DEPENDS GSplus
+ COMMAND dylibbundler -od -b -x GSplus.app/Contents/MacOS/GSplus -d GSplus.app/Contents/libs
+ COMMENT bundling libraries...
+ )
+ add_custom_target(setuid
+ COMMAND sudo chown root GSplus.app/Contents/MacOS/vmnet_helper
+ COMMAND sudo chmod +s GSplus.app/Contents/MacOS/vmnet_helper
+ USES_TERMINAL)
+ add_dependencies(setuid vmnet_helper)
+endif()
diff --git a/src/assets/GSBug.Templates b/src/assets/GSBug.Templates
new file mode 100644
index 0000000..b1bba95
--- /dev/null
+++ b/src/assets/GSBug.Templates
@@ -0,0 +1,2556 @@
+;
+; template: Template Master Index
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+
+_START Templates
+ADB
+AppleShareFST
+Controls
+Dialogs
+Events
+Fonts
+GSOS
+HighSierraFST
+LineEdit
+Lists
+Locator
+Menus
+MiscTool
+NoteSeq
+NoteSyn
+Print
+ProDOS16
+ProDOSFST
+QDAux
+QuickDraw
+Resources
+SANE
+Sound
+StdFile
+TextEdit
+Windows
+_END
+
+;
+; template: Apple Desktop Bus Tool Set
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START ADB
+ReadConfigRec
+ScaleRec
+SetConfigRec
+SynchRec
+_END
+
+_START ReadConfigRec
+rcADBAddr BYTE
+rcLayoutOrLang BYTE
+rcRepeatDelay BYTE
+_END
+
+_START SetConfigRec
+scADBAddr BYTE
+scLayoutOrLang BYTE
+scRepeatDelay BYTE
+_END
+
+_START SynchRec
+synchMode BYTE
+synchKybdMouseAddr BYTE
+synchLayoutOrLang BYTE
+synchRepeatDelay BYTE
+_END
+
+_START ScaleRec
+xDivide WORD
+yDivide WORD
+xOffset WORD
+yOffset WORD
+xMultiply WORD
+yMultiply WORD
+_END
+
+
+;
+; template: Control Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Controls
+BarColors
+BoxColors
+BttnColors
+CheckCtlRec
+CtlRec
+EditLineCtlRec
+EditTextCtlRec
+GrowCtlRec
+IconButtonCtlRec
+LimitBlk
+ListCtlRec
+PictureCtlRec
+PopUpCtlRec
+RadioColors
+RadioCtlRec
+ScrollCtlRec
+SimpleButtonCtlRec
+StatTextCtlRec
+_END
+
+; generic extended control record
+_START CtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+ctlReserved BYTE 16
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+; extended control records
+_START SimpleButtonCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+keyEquiv
+>key1 BYTE
+>key2 BYTE
+>keymodifiers WORD
+>keyCareBits WORD
+ctlReserved BYTE 10
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START CheckCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+keyEquiv
+>key1 BYTE
+>key2 BYTE
+>keymodifiers WORD
+>keyCareBits WORD
+ctlReserved BYTE 10
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START IconButtonCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+keyEquiv
+>key1 BYTE
+>key2 BYTE
+>keymodifiers WORD
+>keyCareBits WORD
+ctlReserved BYTE 10
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+iconRef LONG
+displayMode WORD
+_END
+
+_START EditLineCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+ctlReserved BYTE 16
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START ListCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+ctlMemDraw LONG
+ctlMemHeight WORD
+ctlMemSize WORD
+ctlListRef LONG
+ctlListBar LONG
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START PictureCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+ctlReserved BYTE 16
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START PopUpCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+menuRef LONG
+menuEnd LONG
+popUpRect WORD 4
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+titleWidth WORD
+_END
+
+_START RadioCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+keyEquiv
+>key1 BYTE
+>key2 BYTE
+>keymodifiers WORD
+>keyCareBits WORD
+ctlReserved BYTE 10
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START ScrollCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+thumbRect WORD 4
+pageRegion WORD 4
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START GrowCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+ctlReserved BYTE 16
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START StatTextCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+ctlJust WORD
+ctlReserved BYTE 14
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+_END
+
+_START EditTextCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+textFlags LONG
+textLength LONG
+blockList
+>cachedHandle LONG
+>cachedOffset LONG
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+viewRect WORD 4
+totalHeight LONG
+lineSuper
+>cachedHandle LONG
+>cachedOffset LONG
+>cachedIndex WORD
+>itemsPerBlock WORD
+styleSuper
+>cachedHandle LONG
+>cachedOffset LONG
+>cachedIndex WORD
+>itemsPerBlock WORD
+styleList LONG
+rulerList LONG
+lineAtEndFlag WORD
+selectionStart LONG
+selectionEnd LONG
+selectionActive WORD
+selectionState WORD
+caretTime LONG
+nullStyleActive WORD
+nullStyle
+>fontID LONG
+>foreColor WORD
+>backColor WORD
+>userData LONG
+topTextOffset LONG
+topTextVPos WORD
+vertScrollBar LONG
+vertScrollPos LONG
+vertScrollMax LONG
+vertScrollAmount WORD
+horzScrollBar LONG
+horzScrollPos LONG
+horxScrollMax LONG
+horzScrollAmount WORD
+growBoxHandle LONG
+maximumChars LONG
+maximumLines LONG
+maxCharsPerLine WORD
+maximumHeight WORD
+textDrawMode WORD
+wordBreakHook LONG
+wordWrapHook LONG
+keyFilter LONG
+theFilterRect WORD 4
+theBufferVPos WORD
+theBufferHPos WORD
+theKeyRecord
+>theChar WORD
+>theModifiers WORD
+>theInputHandle LONG
+>cursorOffset LONG
+>theOpcode WORD
+cachedSelcOffset LONG
+cachedSelcVPos WORD
+cachedSelcHPos WORD
+mouseRect WORD 4
+mouseTime LONG
+mouseKind WORD
+lastClick WORD 2
+savedHPos WORD
+anchorPoint LONG
+_END
+
+_START BarColors
+barOutline WORD
+barNorArrow WORD
+barSelArrow WORD
+barArrowBack WORD
+barNorThumb WORD
+barSelThumb WORD
+barPageRgn WORD
+barInactive WORD
+_END
+
+_START BoxColors
+boxReserved WORD
+boxNor WORD
+boxSel WORD
+boxTitle WORD
+_END
+
+_START BttnColors
+bttnOutline WORD
+bttnNorBack WORD
+bttnSelBack WORD
+bttnNorText WORD
+bttnSelText WORD
+_END
+
+_START LimitBlk
+boundRect WORD 4
+slopRect WORD 4
+axisParam WORD
+dragPatt LONG
+_END
+
+_START RadioColors
+radReserved WORD
+radNor WORD
+radSel WORD
+radTitle WORD
+_END
+
+
+;
+; template: Dialog Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Dialogs
+AlertTemplate
+DialogTemplate
+ItemTemplate
+UserCtlItemPB
+_END
+
+_START AlertTemplate
+atBoundsRect WORD 4
+atAlertID WORD
+atStage1 BYTE
+atStage2 BYTE
+atStage3 BYTE
+atStage4 BYTE
+atItemList LONG
+_END
+
+_START DialogTemplate
+dtBoundsRect WORD 4
+dtVisible WORD
+dtRefCon LONG
+dtItemList LONG
+_END
+
+_START ItemTemplate
+itemID WORD
+itemRect WORD 4
+itemType WORD
+itemDescr LONG
+itemValue WORD
+itemFlag WORD
+itemColor LONG
+_END
+
+_START UserCtlItemPB
+defProcParm LONG
+titleParm LONG
+param1 WORD
+param2 WORD
+_END
+
+
+;
+; template: Event Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Events
+EventRecord
+_END
+
+_START EventRecord
+what WORD
+message LONG
+when LONG
+where WORD 2
+modifiers WORD
+_END
+
+
+;
+; template: Font Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Fonts
+FontID
+FontStatRec
+_END
+
+_START FontID
+famNum WORD
+fontStyle BYTE
+fontSize BYTE
+_END
+
+_START FontStatRec
+resultID
+>famNum WORD
+>fontStyle BYTE
+>fontSize BYTE
+resultStats WORD
+_END
+
+
+;
+; template: LineEdit Tool Set
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START LineEdit
+LERec
+_END
+
+_START LERec
+leLineHandle LONG
+leLength WORD
+leMaxLength WORD
+leDestRect WORD 4
+leViewRect WORD 4
+lePort LONG
+leLineHite WORD
+leBaseHite WORD
+leSelStart WORD
+leSelEnd WORD
+leActFlg WORD
+leCarAct WORD
+leCarOn WORD
+leCarTime LONG
+leHiliteHook LONG
+leCaretHook LONG
+leJust WORD
+lePWChar WORD
+_END
+
+
+;
+; template: List Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Lists
+LColorTable
+ListRec
+MemRec
+_END
+
+_START ListRec
+listRect WORD 4
+listSize WORD
+listView WORD
+listType WORD
+listStart WORD
+listCtl LONG
+listDraw LONG
+listMemHeight WORD
+listMemSize WORD
+listPointer LONG
+listRefCon LONG
+listScrollClr LONG
+_END
+
+; ListCtlRec can be found in the Control Manager templates.
+
+_START MemRec
+memPtr LONG
+memFlag BYTE
+_END
+
+_START LColorTable
+listFrameClr WORD
+listNorTextClr WORD
+listSelTextClr WORD
+listNorBackClr WORD
+listSelBackClr WORD
+_END
+
+
+;
+; template: Menu Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Menus
+Menu
+MenuBarTemplate
+MenuItemTemplate
+MenuTemplate
+_END
+
+_START Menu
+menuID WORD
+menuWidth WORD
+menuHeight WORD
+menuProc LONG
+menuFlag BYTE
+menuRes BYTE
+firstItem BYTE
+numOfItems BYTE
+titleWidth WORD
+titleName LONG
+menuCache LONG
+_END
+
+_START MenuItemTemplate
+version WORD
+itemID WORD
+itemChar BYTE
+itemAltChar BYTE
+itemCheck WORD
+itemFlag WORD
+itemTitleRef LONG
+_END
+
+_START MenuTemplate
+version WORD
+menuID WORD
+menuFlag WORD
+menuTitleRef LONG
+itemRefArray LONG
+_END
+
+_START MenuBarTemplate
+version WORD
+menuBarFlag WORD
+menuRefArray LONG
+_END
+
+
+;
+; template: Miscellaneous Tool Set
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START MiscTool
+ClampRec
+FWRec
+InterruptStateRec
+MouseRec
+QueueHeader
+TimeRec
+_END
+
+_START QueueHeader
+reserved LONG
+reserved WORD
+signature WORD
+_END
+
+_START InterruptStateRec
+irq_A WORD
+irq_X WORD
+irq_Y WORD
+irq_S WORD
+irq_D WORD
+irq_P BYTE
+irq_DB BYTE
+irq_e BYTE
+irq_K BYTE
+irq_PC WORD
+irq_state BYTE
+irq_shadow WORD
+irq_mslot BYTE
+_END
+
+_START TimeRec
+second BYTE
+minute BYTE
+hour BYTE
+year BYTE
+day BYTE
+month BYTE
+extra BYTE
+weekday BYTE
+_END
+
+_START MouseRec
+mouseMode BYTE
+mouseStatus BYTE
+yPos WORD
+xPos WORD
+_END
+
+_START ClampRec
+yMaxClamp WORD
+yMinClamp WORD
+xMaxClamp WORD
+xMinClamp WORD
+_END
+
+_START FWRec
+yRegExit WORD
+xRegExit WORD
+aRegExit WORD
+status WORD
+_END
+
+
+;
+; template: Note Sequencer
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START NoteSeq
+InstTable
+_END
+
+_START InstTable
+instNumber WORD
+instArray LONG
+_END
+
+
+;
+; template: Note Synthesizer
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START NoteSyn
+Envelope
+GCBRecord
+Instrument
+WaveEntry
+_END
+
+_START Envelope
+breakpoint0 BYTE
+increment0 WORD
+breakpoint1 BYTE
+increment1 WORD
+breakpoint2 BYTE
+increment2 WORD
+breakpoint3 BYTE
+increment3 WORD
+breakpoint4 BYTE
+increment4 WORD
+breakpoint5 BYTE
+increment5 WORD
+breakpoint6 BYTE
+increment6 WORD
+breakpoint7 BYTE
+increment7 WORD
+_END
+
+_START Instrument
+envelope
+>breakpoint0 BYTE
+>increment0 WORD
+>breakpoint1 BYTE
+>increment1 WORD
+>breakpoint2 BYTE
+>increment2 WORD
+>breakpoint3 BYTE
+>increment3 WORD
+>breakpoint4 BYTE
+>increment4 WORD
+>breakpoint5 BYTE
+>increment5 WORD
+>breakpoint6 BYTE
+>increment6 WORD
+>breakpoint7 BYTE
+>increment7 WORD
+releaseSegment BYTE
+priorityIncrement BYTE
+pitchBendRange BYTE
+vibratoDepth BYTE
+vibratoSpeed BYTE
+inSpare BYTE
+aWaveCount BYTE
+bWaveCount BYTE
+aWaveList...
+bWaveList...
+_END
+
+_START WaveEntry
+topKey BYTE
+waveAddress BYTE
+waveSize BYTE
+DOCMode BYTE
+relPitch WORD
+_END
+
+_START GCBRecord
+synthID BYTE
+genNum BYTE
+semiTone BYTE
+volume BYTE
+pitchbend BYTE
+vibratoDepth BYTE
+reserved BYTE 10
+_END
+
+
+;
+; template: Print Manager
+; 7/7/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Print
+PrInfoRec
+PrJobRec
+PrRec
+PrStatusRec
+PrStyleRec
+_END
+
+_START PrRec
+prVersion WORD
+prInfo
+>iDev WORD
+>iVRes WORD
+>iHRes WORD
+>rPage WORD 4
+rPaper WORD 4
+prStl
+>wDev WORD
+>internA WORD 3
+>feed WORD
+>paperType WORD
+>crWidth WORD
+>reduction WORD
+>internB WORD
+prInfoPT BYTE 14
+prXInfo BYTE 24
+prJob
+>iFstPage WORD
+>iLstPage WORD
+>iCopies WORD
+>bJDocLoop BYTE
+>fFromUser BYTE
+>pIdleProc LONG
+>pFileName LONG
+>iFileVol WORD
+>bFileVers BYTE
+>bJobX BYTE
+printX BYTE 38
+iReserved WORD
+_END
+
+_START PrInfoRec
+iDev WORD
+iVRes WORD
+iHRes WORD
+rPage WORD 4
+_END
+
+_START PrStyleRec
+wDev WORD
+internA WORD 3
+feed WORD
+paperType WORD
+crWidth WORD
+reduction WORD
+internB WORD
+_END
+
+_START PrJobRec
+iFstPage WORD
+iLstPage WORD
+iCopies WORD
+bJDocLoop BYTE
+fFromUser BYTE
+pIdleProc LONG
+pFileName LONG
+iFileVol WORD
+bFileVers BYTE
+bJobX BYTE
+_END
+
+_START PrStatusRec
+iTotPages WORD
+iCurPage WORD
+iTotCopies WORD
+iCurCopy WORD
+iTotBands WORD
+iCurBand WORD
+iPgDirty WORD
+fImaging WORD
+hPrint LONG
+pPrPort LONG
+hPic LONG
+_END
+
+
+;
+; template: QuickDraw II
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START QuickDraw
+BufDimRec
+Font
+FontGlobalsRecord
+FontInfoRecord
+GrafPort
+LocInfo
+PaintParam
+PenStateRecord
+ROMFontRecord
+_END
+
+_START BufDimRec
+buffer_sizing_record
+maxWidth WORD
+textBufHeight WORD
+textBufferWords WORD
+fontWidth WORD
+_END
+
+_START Font
+font_record
+offseToMF WORD
+family WORD
+style WORD
+size WORD
+version WORD
+fbrExtent WORD
+highowTLoc WORD
+_END
+
+_START FontGlobalsRecord
+fgFontID WORD
+fgStyle WORD
+fgSize WORD
+fgVersion WORD
+fgWidMax WORD
+fgFBRExtent WORD
+_END
+
+_START FontInfoRecord
+ascent WORD
+descent WORD
+widMax WORD
+leading WORD
+_END
+
+_START GrafPort
+portInfo
+>portSCB WORD
+>ptrToPixImage LONG
+>width WORD
+>boundsRect WORD 4
+portRect WORD 4
+clipRgn LONG
+visRgn LONG
+bkPat BYTE 32
+pnLoc WORD 2
+pnSize WORD 2
+pnMode WORD
+pnPat BYTE 32
+pnMask BYTE 8
+pnVis WORD
+fontHandle LONG
+fontID LONG
+fontFlags WORD
+txSize WORD
+txFace WORD
+txMode WORD
+spExtra LONG
+chExtra LONG
+fgColor WORD
+bgColor WORD
+picSave LONG
+rgnSave LONG
+polySave LONG
+grafProcs LONG
+arcRot WORD
+userField LONG
+sysField LONG
+_END
+
+_START LocInfo
+portSCB WORD
+ptrToPixImage LONG
+width WORD
+boundsRect WORD 4
+_END
+
+_START PaintParam
+PaintPixels_parameter_block
+ptrToSourceLocInfo LONG
+ptrToDestLocInfo LONG
+ptrToSourceRect LONG
+ptrToDestPoint LONG
+mode WORD
+maskHandle LONG
+_END
+
+_START PenStateRecord
+psPenLoc WORD 2
+psPnSize WORD 2
+psPnMode WORD
+psPnPat BYTE 32
+psPnMask BYTE 8
+_END
+
+_START ROMFontRecord
+rfFamNum WORD
+rfFamStyle WORD
+rfSize WORD
+rfFontHandle LONG
+rfNamePtr LONG
+rfFBRExtent WORD
+_END
+
+;
+; template: QuickDraw II Auxiliary
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START QDAux
+IconRecord
+_END
+
+_START IconRecord
+iconType WORD
+iconSize WORD
+iconHeight WORD
+iconWidth WORD
+image/mask
+_END
+
+
+;
+; template: SANE
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START SANE
+HaltDPage
+_END
+
+_START HaltDPage
+returnAddrs BYTE 6
+callerDpage WORD
+callerDB WORD
+opword WORD
+cAddress LONG
+bAddress LONG
+aAddress LONG
+haltVector LONG
+environment WORD
+pendingExceptions WORD
+pendingXlo BYTE
+pendingXhiYlo BYTE
+pendingYhi BYTE
+_END
+
+
+;
+; template: Resource Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Resources
+FreeBlockRec
+MapRec
+ResHeaderRec
+ResRefRec
+_END
+
+_START ResHeaderRec
+rFileVersion LONG
+rFileToMap LONG
+rFileMapSize LONG
+rFileMemo BYTE 128
+_END
+
+_START MapRec
+mapNext LONG
+mapFlag WORD
+mapOffset LONG
+mapSize LONG
+mapToIndex WORD
+mapFileNum WORD
+mapID WORD
+mapIndexSize LONG
+mapIndexUsed LONG
+mapFreeListSize WORD
+mapFreeListUsed WORD
+mapFreeList/Index
+_END
+
+_START FreeBlockRec
+blkOffset LONG
+blkSize LONG
+_END
+
+_START ResRefRec
+resType WORD
+resID LONG
+resOffset LONG
+resAttr WORD
+resSize LONG
+resHandle LONG
+_END
+
+
+;
+; template: Sound Tool Set
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Sound
+DOCRegParamBlock
+SoundParamBlock
+_END
+
+_START SoundParamBlock
+waveStart LONG
+waveSize WORD
+freqOffset WORD
+docBuffer WORD
+bufferSize WORD
+nextWavePtr LONG
+volSetting WORD
+_END
+
+_START DOCRegParamBlock
+oscGenTYpe WORD
+freqLow1 BYTE
+freqHigh1 BYTE
+vol1 BYTE
+tablePtr1 BYTE
+control1 BYTE
+tableSize1 BYTE
+freqLow2 BYTE
+freqHigh2 BYTE
+vol2 BYTE
+tablePtr2 BYTE
+control2 BYTE
+tableSize2 BYTE
+_END
+
+
+;
+; template: Standard File Operations Tool Set
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START StdFile
+ReplyRecord
+ReplyRecord2
+_END
+
+_START ReplyRecord
+good WORD
+fileType WORD
+auxFileType WORD
+fileName BYTE 16
+fullPathname BYTE 129
+_END
+
+_START ReplyRecord2
+good WORD
+type WORD
+auxType LONG
+nameRefDesc WORD
+nameRef LONG
+pathRefDesc WORD
+pathRef LONG
+_END
+
+
+;
+; template: Text Edit
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START TextEdit
+KeyRecord
+StyleItem
+SuperBlock
+SuperHandle
+SuperItem
+TabItem
+TEColorTable
+TEFormat
+TEParamBlock
+TERecord
+TERuler
+TEStyle
+TextBlock
+TextList
+_END
+
+_START TEColorTable
+contentColor WORD
+outlineColor WORD
+vertColorDescriptor WORD
+vertColorRef LONG
+horzColorDescriptor WORD
+horzColorRef LONG
+growColorDescriptor WORD
+growColorRef LONG
+_END
+
+_START TEFormat
+version WORD
+rulerListLength LONG
+theRulerList
+styleListLength
+theStyleList
+numberOfStyles
+theStyles
+_END
+
+_START TEParamBlock
+pCount WORD
+ID LONG
+rect WORD 4
+procRef LONG
+flags WORD
+moreFlags WORD
+refCon LONG
+textFlags LONG
+indentRect WORD 4
+vertBar LONG
+vertAmount WORD
+horzBar LONG
+horzAmount WORD
+styleRef LONG
+textDescriptor WORD
+textRef LONG
+textLength LONG
+maxChars LONG
+maxLines LONG
+maxCharsPerLine WORD
+maxHeight WORD
+colorRef LONG
+drawMode WORD
+filterProc LONG
+_END
+
+_START TERecord
+; same as EditTextCtlRec
+ctlNext LONG
+ctlOwner LONG
+ctlRect WORD 4
+ctlFlag BYTE
+ctlHilite BYTE
+ctlValue WORD
+ctlProc LONG
+ctlAction LONG
+ctlData LONG
+ctlRefCon LONG
+ctlColor LONG
+textFlags LONG
+textLength LONG
+blockList
+>cachedHandle LONG
+>cachedOffset LONG
+ctlID LONG
+ctlMoreFlags WORD
+ctlVersion WORD
+viewRect WORD 4
+totalHeight LONG
+lineSuper
+>cachedHandle LONG
+>cachedOffset LONG
+>cachedIndex WORD
+>itemsPerBlock WORD
+styleSuper
+>cachedHandle LONG
+>cachedOffset LONG
+>cachedIndex WORD
+>itemsPerBlock WORD
+styleList LONG
+rulerList LONG
+lineAtEndFlag WORD
+selectionStart LONG
+selectionEnd LONG
+selectionActive WORD
+selectionState WORD
+caretTime LONG
+nullStyleActive WORD
+nullStyle
+>fontID LONG
+>foreColor WORD
+>backColor WORD
+>userData LONG
+topTextOffset LONG
+topTextVPos WORD
+vertScrollBar LONG
+vertScrollPos LONG
+vertScrollMax LONG
+vertScrollAmount WORD
+horzScrollBar LONG
+horzScrollPos LONG
+horxScrollMax LONG
+horzScrollAmount WORD
+growBoxHandle LONG
+maximumChars LONG
+maximumLines LONG
+maxCharsPerLine WORD
+maximumHeight WORD
+textDrawMode WORD
+wordBreakHook LONG
+wordWrapHook LONG
+keyFilter LONG
+theFilterRect WORD 4
+theBufferVPos WORD
+theBufferHPos WORD
+theKeyRecord
+>theChar WORD
+>theModifiers WORD
+>theInputHandle LONG
+>cursorOffset LONG
+>theOpcode WORD
+cachedSelcOffset LONG
+cachedSelcVPos WORD
+cachedSelcHPos WORD
+mouseRect WORD 4
+mouseTime LONG
+mouseKind WORD
+lastClick WORD 2
+savedHPos WORD
+anchorPoint LONG
+_END
+
+_START TERuler
+leftMargin WORD
+leftIndent WORD
+rightMargin WORD
+just WORD
+extraLS WORD
+flags WORD
+userData LONG
+tabType WORD
+theTabs
+tabTerminator
+_END
+
+_START TEStyle
+fontID LONG
+foreColor WORD
+backColor WORD
+userData LONG
+_END
+
+_START KeyRecord
+theChar WORD
+theModifiers WORD
+theInputHandle LONG
+cursorOffset LONG
+theOpCode WORD
+_END
+
+_START StyleItem
+length LONG
+offset LONG
+_END
+
+_START SuperBlock
+nextHandle LONG
+prevHandle LONG
+textLength LONG
+reserved LONG
+theItems
+_END
+
+_START SuperHandle
+cachedHandle LONG
+cachedOffset LONG
+cachedIndex WORD
+itemsPerBlock WORD
+_END
+
+_START SuperItem
+length LONG
+data LONG
+_END
+
+_START TabItem
+tabKind WORD
+tabData WORD
+_END
+
+_START TextBlock
+nextHandle LONG
+prevHandle LONG
+textLength LONG
+flags WORD
+reserved WORD
+theText
+_END
+
+_START TextList
+cachedHandle LONG
+cachedOffset LONG
+_END
+
+
+;
+; template: Tool Locator
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Locator
+StartStopRec
+ToolSpec
+ToolTable
+_END
+
+_START ToolTable
+numTools WORD
+toolArray
+>toolNumber1 WORD
+>minVersion1 WORD
+>toolNumber2 WORD
+>minVersion2 WORD
+>toolNumber3 WORD
+>minVersion3 WORD
+>toolNumber4 WORD
+>minVersion4 WORD
+>toolNumber5 WORD
+>minVersion5 WORD
+>toolNumber6 WORD
+>minVersion6 WORD
+>toolNumber7 WORD
+>minVersion7 WORD
+>toolNumber8 WORD
+>minVersion8 WORD
+>toolNumber9 WORD
+>minVersion9 WORD
+>toolNumber10 WORD
+>minVersion10 WORD
+>toolNumber11 WORD
+>minVersion11 WORD
+>toolNumber12 WORD
+>minVersion12 WORD
+>toolNumber13 WORD
+>minVersion13 WORD
+>toolNumber14 WORD
+>minVersion14 WORD
+>toolNumber15 WORD
+>minVersion15 WORD
+>toolNumber16 WORD
+>minVersion16 WORD
+>toolNumber17 WORD
+>minVersion17 WORD
+>toolNumber18 WORD
+>minVersion18 WORD
+>toolNumber19 WORD
+>minVersion19 WORD
+>toolNumber20 WORD
+>minVersion20 WORD
+>toolNumber21 WORD
+>minVersion21 WORD
+>toolNumber22 WORD
+>minVersion22 WORD
+>toolNumber23 WORD
+>minVersion23 WORD
+>toolNumber24 WORD
+>minVersion24 WORD
+>toolNumber25 WORD
+>minVersion25 WORD
+>toolNumber26 WORD
+>minVersion26 WORD
+>toolNumber27 WORD
+>minVersion27 WORD
+>toolNumber28 WORD
+>minVersion28 WORD
+>toolNumber29 WORD
+>minVersion29 WORD
+>toolNumber30 WORD
+>minVersion30 WORD
+>toolNumber31 WORD
+>minVersion31 WORD
+>toolNumber32 WORD
+>minVersion32 WORD
+>toolNumber33 WORD
+>minVersion33 WORD
+>toolNumber34 WORD
+>minVersion34 WORD
+>toolNumber35 WORD
+>minVersion35 WORD
+>toolNumber36 WORD
+>minVersion36 WORD
+>toolNumber37 WORD
+>minVersion37 WORD
+>toolNumber38 WORD
+>minVersion38 WORD
+>toolNumber39 WORD
+>minVersion39 WORD
+>toolNumber40 WORD
+>minVersion40 WORD
+_END
+
+_START StartStopRec
+flags WORD
+videoMode WORD
+resFileID WORD
+dPageHandle LONG
+numTools WORD
+toolArray
+>toolNumber1 WORD
+>minVersion1 WORD
+>toolNumber2 WORD
+>minVersion2 WORD
+>toolNumber3 WORD
+>minVersion3 WORD
+>toolNumber4 WORD
+>minVersion4 WORD
+>toolNumber5 WORD
+>minVersion5 WORD
+>toolNumber6 WORD
+>minVersion6 WORD
+>toolNumber7 WORD
+>minVersion7 WORD
+>toolNumber8 WORD
+>minVersion8 WORD
+>toolNumber9 WORD
+>minVersion9 WORD
+>toolNumber10 WORD
+>minVersion10 WORD
+>toolNumber11 WORD
+>minVersion11 WORD
+>toolNumber12 WORD
+>minVersion12 WORD
+>toolNumber13 WORD
+>minVersion13 WORD
+>toolNumber14 WORD
+>minVersion14 WORD
+>toolNumber15 WORD
+>minVersion15 WORD
+>toolNumber16 WORD
+>minVersion16 WORD
+>toolNumber17 WORD
+>minVersion17 WORD
+>toolNumber18 WORD
+>minVersion18 WORD
+>toolNumber19 WORD
+>minVersion19 WORD
+>toolNumber20 WORD
+>minVersion20 WORD
+>toolNumber21 WORD
+>minVersion21 WORD
+>toolNumber22 WORD
+>minVersion22 WORD
+>toolNumber23 WORD
+>minVersion23 WORD
+>toolNumber24 WORD
+>minVersion24 WORD
+>toolNumber25 WORD
+>minVersion25 WORD
+>toolNumber26 WORD
+>minVersion26 WORD
+>toolNumber27 WORD
+>minVersion27 WORD
+>toolNumber28 WORD
+>minVersion28 WORD
+>toolNumber29 WORD
+>minVersion29 WORD
+>toolNumber30 WORD
+>minVersion30 WORD
+>toolNumber31 WORD
+>minVersion31 WORD
+>toolNumber32 WORD
+>minVersion32 WORD
+>toolNumber33 WORD
+>minVersion33 WORD
+>toolNumber34 WORD
+>minVersion34 WORD
+>toolNumber35 WORD
+>minVersion35 WORD
+>toolNumber36 WORD
+>minVersion36 WORD
+>toolNumber37 WORD
+>minVersion37 WORD
+>toolNumber38 WORD
+>minVersion38 WORD
+>toolNumber39 WORD
+>minVersion39 WORD
+>toolNumber40 WORD
+>minVersion40 WORD
+_END
+
+_START ToolSpec
+toolNumber WORD
+minVersion WORD
+_END
+
+
+;
+; template: Window Manager
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START Windows
+Paramlist
+WindColor
+WindRec
+WmTaskRec
+_END
+
+_START WindRec
+wNext LONG
+port
+>portInfo
+>>portSCB WORD
+>>ptrToPixImage LONG
+>>width WORD
+>>boundsRect WORD 4
+>portRect WORD 4
+>clipRgn LONG
+>visRgn LONG
+>bkPat BYTE 32
+>pnLoc WORD 2
+>pnSize WORD 2
+>pnMode WORD
+>pnPat BYTE 32
+>pnMask BYTE 8
+>pnVis WORD
+>fontHandle LONG
+>fontID LONG
+>fontFlags WORD
+>txSize WORD
+>txFace WORD
+>txMode WORD
+>spExtra LONG
+>chExtra LONG
+>fgColor WORD
+>bgColor WORD
+>picSave LONG
+>rgnSave LONG
+>polySave LONG
+>grafProcs LONG
+>arcRot WORD
+>userField LONG
+>sysField LONG
+wDefProc LONG
+wRefCon LONG
+wContDraw LONG
+wReserved LONG
+wStrucRgn LONG
+wContRgn LONG
+wUpdateRgn LONG
+wControls LONG
+wFrameCtrls LONG
+wFrame WORD
+wCustom
+_END
+
+_START WindColor
+frameColor WORD
+titleColor WORD
+tBarColor WORD
+growColor WORD
+infoColor WORD
+_END
+
+_START Paramlist
+paramLength WORD
+wFrameBits WORD
+wTitle LONG
+wRefCon LONG
+wZoom WORD 4
+wColor LONG
+wYOrigin WORD
+wXOrigin WORD
+wDataH WORD
+wDataW WORD
+wMaxH WORD
+wMaxW WORD
+wScrollVer WORD
+wScrollHor WORD
+wPageVer WORD
+wPageHor WORD
+wInfoRefCon LONG
+wInfoHeight WORD
+wFrameDefProc LONG
+wInfoDefProc LONG
+wContDefProc LONG
+wPosition WORD 4
+wPlane LONG
+wStorage LONG
+_END
+
+_START WmTaskRec
+wmWhat WORD
+wmMessage LONG
+wmWhen LONG
+wmWhere LONG
+wmModifiers WORD
+wmTaskData LONG
+wmTaskMask LONG
+wmLastClickTick LONG
+wmClickCount WORD
+wmTaskData2 LONG
+wmTaskData3 LONG
+wmTaskData4 LONG
+wmLastClickPt WORD 2
+_END
+
+
+;
+; template: GS/OS
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START GSOS
+ChangePathRecGS
+CreateRecGS
+DAccessRecGS
+DevNumRecGS
+DInfoRecGS
+DIORecGS
+DirEntryRecGS
+DRenameRecGS
+EOFRecGS
+ExpandPathRecGS
+FileInfoRecGS
+FormatRecGS
+FSTInfoRecGS
+GetNameRecGS
+InterruptRecGS
+IORecGS
+LevelRecGS
+NameRecGS
+NewLineRecGS
+NotifyProcRecGS
+OpenRecGS
+OSShutdownRecGS
+PositionRecGS
+PrefixRecGS
+QuitRecGS
+RefInfoRecGS
+RefNumRecGS
+SessionStatusRecGS
+SetPositionRecGS
+SetPrefixRecGS
+StdRefNumRecGS
+SysPrefsRecGS
+VersionRecGS
+VolumeRecGS
+_END
+
+_START ChangePathRecGS
+pCount WORD
+pathname GSSTRING
+newPathname GSSTRING
+_END
+
+_START CreateRecGS
+pCount WORD
+pathname GSSTRING
+access WORD
+fileType WORD
+auxType LONG
+storageType WORD
+eof LONG
+resourceEOF LONG
+_END
+
+_START DAccessRecGS
+pCount WORD
+devNum WORD
+code WORD
+list LONG
+requestCount LONG
+transferCount LONG
+_END
+
+_START DevNumRecGS
+pCount WORD
+devName GSSTRING
+devNum WORD
+_END
+
+_START DInfoRecGS
+pCount WORD
+devNum WORD
+devName LONG
+characteristics WORD
+totalBlocks LONG
+slotNum WORD
+unitNum WORD
+version WORD
+deviceID WORD
+headLink WORD
+forwardLink WORD
+extenededDIBPtr LONG
+_END
+
+_START DIORecGS
+pCount WORD
+devNum WORD
+buffer LONG
+requestCount LONG
+startingBlock LONG
+blockSize WORD
+transferCount LONG
+_END
+
+_START DirEntryRecGS
+pCount WORD
+refNum WORD
+flags WORD
+base WORD
+displacement WORD
+name LONG
+entryNum WORD
+fileType WORD
+eof LONG
+blockCount LONG
+createDateTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+modDateTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+access WORD
+auxType LONG
+fileSysID WORD
+optionList LONG
+resourceEOF LONG
+resourceBlocks LONG
+_END
+
+_START DRenameRecGS
+pCount WORD
+devNum WORD
+strPtr GSSTRING
+_END
+
+_START ExpandPathRecGS
+pCount WORD
+inputPath GSSTRING
+outputPath LONG
+flags WORD
+_END
+
+_START FileInfoRecGS
+pCount WORD
+pathname GSSTRING
+fileType WORD
+auxType LONG
+storageType WORD
+createDateTime
+modDateTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+optionList LONG
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+eof LONG
+blocksUsed LONG
+resourceEOF LONG
+resourceBlocks LONG
+_END
+
+_START FormatRecGS
+pCount WORD
+devName GSSTRING
+volName GSSTRING
+fileSysID WORD
+reqFileSysID WORD
+_END
+
+_START FSTInfoRecGS
+pCount WORD
+fstNum WORD
+fileSysID WORD
+fstName LONG
+version WORD
+attributes WORD
+blockSize WORD
+maxVolSize LONG
+maxFileSize LONG
+_END
+
+_START InterruptRecGS
+pCount WORD
+intNum WORD
+vrn WORD
+intCode LONG
+_END
+
+_START IORecGS
+pCount WORD
+refNum WORD
+dataBuffer LONG
+requestCount LONG
+transferCount LONG
+cachePriority WORD
+_END
+
+_START LevelRecGS
+pCount WORD
+level WORD
+_END
+
+_START NameRecGS
+pCount WORD
+pathname GSSTRING
+_END
+
+_START NotifyProcRecGS
+pCount WORD
+procPointer LONG
+_END
+
+_START GetNameRecGS
+pCount WORD
+pathname LONG
+_END
+
+_START NewLineRecGS
+pCount WORD
+refNum WORD
+enableMask WORD
+numChars WORD
+newlineTable LONG
+_END
+
+_START OpenRecGS
+pCount WORD
+refNum WORD
+pathname GSSTRING
+requestAccess WORD
+access WORD
+fileType WORD
+auxType LONG
+storageType WORD
+createDateTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+modDateTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+optionList LONG
+eof LONG
+blocksUsed LONG
+resourceEOF LONG
+resourceBlocks LONG
+_END
+
+_START OSShutdownRecGS
+pCount WORD
+shutdownFlag WORD
+_END
+
+_START PositionRecGS
+pCount WORD
+reNum WORD
+position LONG
+_END
+
+_START EOFRecGS
+pCount WORD
+reNum WORD
+eof LONG
+_END
+
+_START PrefixRecGS
+pCount WORD
+prefixNum WORD
+prefixPtr LONG
+_END
+
+_START SetPrefixRecGS
+pCount WORD
+prefixNum WORD
+prefixPtr GSSTRING
+_END
+
+_START QuitRecGS
+pCount WORD
+pathname GSSTRING
+flags WORD
+_END
+
+_START RefNumRecGS
+pCount WORD
+pathname GSSTRING
+refNum WORD
+access WORD
+resNum WORD
+caseSense WORD
+displacement WORD
+_END
+
+_START StdRefNumRecGS
+pCount WORD
+prefixNum WORD
+refNum WORD
+_END
+
+_START SessionStatusRecGS
+pCount WORD
+status WORD
+_END
+
+_START SetPositionRecGS
+pCount WORD
+refNum WORD
+base WORD
+displacement LONG
+_END
+
+_START SysPrefsRecGS
+pCount WORD
+preferences WORD
+_END
+
+_START VersionRecGS
+pCount WORD
+version WORD
+_END
+
+_START VolumeRecGS
+pCount WORD
+devName GSSTRING
+volName LONG
+totalBlocks LONG
+freeBlocks LONG
+fileSysID WORD
+blockSize WORD
+_END
+
+_START RefInfoRecGS
+pCount WORD
+refNum WORD
+access WORD
+pathname LONG
+_END
+
+
+;
+; template: AppleShare FST
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START AppleShareFST
+ASOptionListRec
+BufferControlRec
+ByteRangeLockRec
+CopyFileRec
+DesktopRec
+GetCommentRec
+GetPrivilegesRec
+GetServerNameRec
+GetUserPathRec
+SetCommentRec
+SetPrivilegesRec
+SpecialOpenForkRec
+UserInfoRec
+_END
+
+_START BufferControlRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+refNum WORD
+flags WORD
+_END
+
+_START SpecialOpenForkRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+pathname LONG
+accessMode WORD
+forkNum WORD
+_END
+
+_START ByteRangeLockRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+refNum WORD
+lockFlag WORD
+fileOffset LONG
+rangeLength LONG
+rangeStart LONG
+_END
+
+_START GetPrivilegesRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+pathname LONG
+accessRights
+>reserved BYTE
+>world BYTE
+>group BYTE
+>owner BYTE
+ownerName LONG
+groupName LONG
+_END
+
+_START SetPrivilegesRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+pathname LONG
+accessRights
+>userSummary BYTE
+>world BYTE
+>group BYTE
+>owner BYTE
+ownerName LONG
+groupName LONG
+_END
+
+_START UserInfoRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+deviceNum WORD
+userName LONG
+primaryGroupName LONG
+_END
+
+_START CopyFileRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+sourcePathname LONG
+destPathname LONG
+_END
+
+_START GetUserPathRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+prefix LONG
+_END
+
+_START DesktopRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+desktopRefNum WORD
+pathname LONG
+_END
+
+_START GetCommentRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+desktopRefNum WORD
+pathname LONG
+comment LONG
+_END
+
+_START SetCommentRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+desktopRefNum WORD
+pathname LONG
+comment LONG
+_END
+
+_START GetServerNameRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+pathname LONG
+serverName LONG
+zoneName LONG
+_END
+
+_START ASOptionListRec
+bufferSize WORD
+dataSize WORD
+theFileSysID WORD
+finderInfo BYTE 32
+parentDirID LONG
+accessRights LONG
+_END
+
+
+;
+; template: ProDOS FST
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START ProDOSFST
+CharCaseRec
+TimeStampRec
+_END
+
+_START TimeStampRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+timeOption WORD
+_END
+
+_START CharCaseRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+caseOption WORD
+_END
+
+
+;
+; template: High Sierra FST
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START HighSierraFST
+GetMapSizeRec
+GetMapTableRec
+MapEnableRec
+SetMapTableRec
+_END
+
+_START MapEnableRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+enable WORD
+_END
+
+_START GetMapSizeRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+mapSize WORD
+_END
+
+_START GetMapTableRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+bufferPtr LONG
+_END
+
+_START SetMapTableRec
+pCount WORD
+fstNum WORD
+commandNum WORD
+mapPtr LONG
+_END
+
+
+;
+; template: ProDOS 16
+; 2/28/90 by J. Luther
+; Copyright (c) Apple Computer, Inc. 1990
+; All Rights reserved
+;
+
+_START ProDOS16
+BlockRec
+DevNumRec
+DInfoRec
+DirEntryRec
+EOFRec
+EraseDiskRec
+ExpandPathRec
+FileIORec
+FileRec
+FormatRec
+InterruptRec
+MarkRec
+NewLineRec
+OpenRec
+PathnameRec
+PrefixRec
+QuitRec
+VolumeRec
+_END
+
+_START BlockRec
+blockDevNum WORD
+blockDataBuffer LONG
+blockNum LONG
+_END
+
+_START DevNumRec
+devName LONG
+devNum WORD
+_END
+
+_START DInfoRec
+devNum WORD
+devName LONG
+_END
+
+_START DirEntryRec
+refNum WORD
+reserved WORD
+base WORD
+displacement WORD
+nameBuffer LONG
+entryNum WORD
+fileType WORD
+endOfFile LONG
+blockCount LONG
+createTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+modTime
+>seconds BYTE
+>minutes BYTE
+>hour BYTE
+>year BYTE
+>day BYTE
+>month BYTE
+>null BYTE
+>weekday BYTE
+access WORD
+auxType LONG
+fileSysID WORD
+_END
+
+_START EOFRec
+eofRefNum WORD
+eofPosition WORD
+_END
+
+_START FileIORec
+fileRefNum WORD
+dataBuffer LONG
+requestCount LONG
+transferCount LONG
+_END
+
+_START FileRec
+pathName LONG
+fAccess WORD
+fileType WORD
+auxType LONG
+storageType WORD
+createDate WORD
+createTime WORD
+modDate WORD
+modTime WORD
+blocksUsed LONG
+_END
+
+_START FormatRec
+devName LONG
+volName LONG
+fileSysID WORD
+_END
+
+_START EraseDiskRec
+devName LONG
+volName LONG
+fileSysID WORD
+_END
+
+_START InterruptRec
+intNum WORD
+intCode LONG
+_END
+
+_START MarkRec
+markRefNum WORD
+position LONG
+_END
+
+_START NewLineRec
+newLRefNum WORD
+enableMask WORD
+newLineChar WORD
+_END
+
+_START OpenRec
+openRefNum WORD
+openPathname LONG
+ioBuffer LONG
+_END
+
+_START PathnameRec
+pathname LONG
+newPathname LONG
+_END
+
+_START PrefixRec
+prefixNum WORD
+prefix LONG
+_END
+
+_START QuitRec
+quitPathname LONG
+flags WORD
+_END
+
+_START VolumeRec
+deviceName LONG
+volName LONG
+totalBlocks LONG
+freeBlocks LONG
+fileSysID WORD
+_END
+
+_START ExpandPathRec
+inputPath LONG
+outputPath LONG
+flags WORD
+_END
+
diff --git a/src/assets/NList.Data b/src/assets/NList.Data
new file mode 100644
index 0000000..b251735
--- /dev/null
+++ b/src/assets/NList.Data
@@ -0,0 +1,2653 @@
+fff9 | NLIST Data File: Last mod 17-Oct-93 DAL (Loma Prieta + 4)
+fffa | Based on Apple IIgs System Disk 6.0.1+UserTool#1,2
+fffb | Dave Lyons
+fffc | dlyons@apple.com
+0040 P8:ALLOC_INTERRUPT(2:IntNum/1,CodePtr)
+0041 P8:DEALLOC_INTERRUPT(1:IntNum/1)
+0042 P8:ATLK:AppleTalk(Async/1,Cmd/1,Result,...)
+0043 P8:ATLK:SpecialOpenFork(4or84:pn,ioBuff,Ref/1,Mode/1)
+0044 P8:ATLK:ByteRangeLock(4:Ref/1,Flag/1,Off/3,Len/3)
+0065 P8:QUIT(4:Type/1,Path,zz/1,zz)
+0080 P8:READ_BLOCK(3:Unit/1,Buff,BlkNum)
+0081 P8:WRITE_BLOCK(3:Unit/1,Buff,BlkNum)
+0082 P8:GET_TIME()
+00C0 P8:CREATE(7:pn,acc/1,type/1,aux,stt/1,cD,cT)
+00C1 P8:DESTROY(1:pn)
+00C2 P8:RENAME(2:pn1,pn2)
+00C3 P8:SetFileInfo(7:pn,a/1,t/1,aux,nul/3,mD,mT)
+00C4 P8:GetFileInfo(10:pn,a/1,t/1,x,s/1,b,mDTcDT)
+00C5 P8:ONLINE(2:UnitNum/1,Buff)
+00C6 P8:SET_PREFIX(1:pn)
+00C7 P8:GET_PREFIX(1:Buff)
+00C8 P8:OPEN(3:pn,ioBuff,Ref/1)
+00C9 P8:NEWLINE(3:Ref/1,Mask/1,Char/1)
+00CA P8:READ(4:Ref/1,Where,reqCount,xfrCount)
+00CB P8:WRITE(4:Ref/1,Where,reqCount,xfrCount)
+00CC P8:CLOSE(1:Ref/1)
+00CD P8:FLUSH(1:Ref/1)
+00CE P8:SET_MARK(2:Ref/1,Position/3)
+00CF P8:GET_MARK(2:Ref/1,Position/3)
+00D0 P8:SET_EOF(2:Ref/1,Position/3)
+00D1 P8:GET_EOF(2:Ref/1,Position/3)
+00D2 P8:SET_BUF(2:Ref/1,ioBuff)
+00D3 P8:GET_BUF(2:Ref/1,ioBuff)
+* ProDOS 16 / GS/OS
+0001 P16:CREATE(@Path,Acc,Typ,Aux/4,StT,CrD,CrT)
+0002 P16:DESTROY(@Path)
+0004 P16:CHANGE_PATH(@Path1,@Path2)
+0005 P16:SET_FILE_INFO(@P,a,t,xt/4,z,cD,cT,mD,mT)
+0006 P16:GET_FILE_INFO(@P,a,t,xt/4,s,cDT,mDT,b/4)
+0008 P16:VOLUME(@DevN,@VolN,Blks/4,FreeBlks/4,fsID)
+0009 P16:SET_PREFIX(Pfx#,@Prefix)
+000A P16:GET_PREFIX(Pfx#,@Buff)
+000B P16:CLEAR_BACKUP_BIT(@Path)
+0010 P16:OPEN(Ref,@Path,xxx/4)
+0011 P16:NEWLINE(Ref,Mask,Char)
+0012 P16:READ(Ref,@Where,Count/4,xfCount/4)
+0013 P16:WRITE(Ref,@Where,Count/4,xfCount/4)
+0014 P16:CLOSE(Ref)
+0015 P16:FLUSH(Ref)
+0016 P16:SET_MARK(Ref,Pos/4)
+0017 P16:GET_MARK(Ref,Pos/4)
+0018 P16:SET_EOF(Ref,EOF/4)
+0019 P16:GET_EOF(Ref,EOF/4)
+001A P16:SET_LEVEL(Level)
+001B P16:GET_LEVEL(Level)
+001C P16:GET_DIR_ENTRY(Ref#,z,Bs,Dis,@Bf,dEnt/36)
+0020 P16:GET_DEV_NUM(@DevName,Dev#)
+0021 P16:GET_LAST_DEV(Dev#)
+0022 P16:READ_BLOCK(Dev#,@Where,Blk#/4)
+0023 P16:WRITE_BLOCK(Dev#,@Where,Blk#/4)
+0024 P16:FORMAT(@DevName,@VolName,fsID)
+0025 P16:ERASE_DISK(@DevName,@VolName,fsID)
+0027 P16:GET_NAME(@Buff)
+0028 P16:GET_BOOT_VOL(@Buff)
+0029 P16:QUIT(@Path,Flags)
+002A P16:GET_VERSION(Version)
+002C P16:D_INFO(Dev#,@DevName)
+0031 P16:ALLOC_INTERRUPT(Int#,@Code)
+0032 P16:DEALLOCATE_INTERRUPT(Int#)
+0101 Shell:Get_LInfo (...)
+0102 Shell:Set_LInfo (...)
+0103 Shell:Get_Lang(Lang)
+0104 Shell:Set_Lang(Lang)
+0105 Shell:Error(Error)
+0106 Shell:Set_Variable(@VarName,Val/4)
+0107 Shell:Version(Vers/4)
+0108 Shell:Read_Indexed(@VarName,Val/4,Index)
+0109 Shell:Init_Wildcard(@File,Flags)
+010A Shell:Next_Wildcard(@NextFile)
+010B Shell:Read_Variable(@VarName,Value/4)
+010C Shell:ChangeVector(res,vec,@proc,@old)
+010D Shell:Execute(Flag,@CmdStr)
+010E Shell:FastFile(act,ind,flg,H,L/4,@n,...)
+010F Shell:Direction(Dev,Direct)
+0110 Shell:Redirect(Dev,ApndFlg,@File)
+0113 Shell:Stop(StopFlag)
+0114 Shell:ExpandDevices(@name)
+0115 Shell:UnsetVariable(@var)
+0116 Shell:Export(@var,flags)
+0117 Shell:PopVariables()
+0118 Shell:PushVariables()
+0119 Shell:SetStopFlag(stopFlag)
+011A Shell:ConsoleOut(Char)
+011B Shell:SetIODevices(OutT,@out,ErrT,@err,InT,@in)
+011C Shell:GetIODevices(OutT,@out,ErrT,@err,InT,@in)
+011D Shell:GetCommand(idx,restart,rsv,cmd,name/16)
+2001 GS/OS:Create(1-7:@P,Acc,Typ,Aux/4,Stg,EOF/4,rEOF/4)
+2002 GS/OS:Destroy(1:@P)
+2003 GS/OS:OSShutdown(1:Flags)
+2004 GS/OS:ChangePath(2-3:@P1,@P2,TrustMeFlag)
+2005 GS/OS:SetFileInfo(2-12:@P,A,T,X/4,,c/8,m/8,@Opt,,,,)
+2006 GS/OS:GetFileInfo(2-12:@P,A,T,X/4,S,c/8,m/8,@Opt,EOF/4,B/4,rEOF/4,rB/4)
+2007 GS/OS:JudgeName(3-6:fileSysID,Descr,@Rules,MaxLen,@Path,Result)
+2008 GS/OS:Volume(2-8:@DevN,@vnOut,blks/4,free/4,fSys,BlkSz,char,devID)
+2009 GS/OS:SetPrefix(1-2:pfxNum,@Pfx)
+200A GS/OS:GetPrefix(2:pfxNum,@Pfx)
+200B GS/OS:ClearBackup(1:@P)
+200C GS/OS:SetSysPrefs(1:prefs)
+200D GS/OS:Null(0:)
+200E GS/OS:ExpandPath(2-3:@InPath,@OutPath,UpcaseFlg)
+200F GS/OS:GetSysPrefs(1:prefs)
+2010 GS/OS:Open(2-15:ref,@P,Acc,fork,gotAcc,+GET_FILE_INFO)
+2011 GS/OS:NewLine(4:ref,ANDmask,NumChars,@NLtable)
+2012 GS/OS:Read(4-5:ref,@buff,count/4,xfer/4,cacheFlg)
+2013 GS/OS:Write(4-5:ref,@buff,count/4,xfer/4,cacheFlg)
+2014 GS/OS:Close(1:ref)
+2015 GS/OS:Flush(1-2:ref,flags)
+2016 GS/OS:SetMark(3:ref,base,displ/4)
+2017 GS/OS:GetMark(2:ref,pos/4)
+2018 GS/OS:SetEOF(3:ref,base,displ/4)
+2019 GS/OS:GetEOF(2:ref,eof/4)
+201A GS/OS:SetLevel(1-2:level,levelMode)
+201B GS/OS:GetLevel(1-2:level,levelMode)
+201C GS/OS:GetDirEntry(5-17:rf,fl,bs,ds,@n,n,T,EOF/4,b/4,c/8,m/8,A,X/4,FS,@o,resEOF/4,resBk/4)
+201D GS/OS:BeginSession(0:)
+201E GS/OS:EndSession(0:)
+201F GS/OS:SessionStatus(1:status)
+2020 GS/OS:GetDevNumber(2:@DevN,devnum)
+2024 GS/OS:Format(1-6:@DevN,@VolN,gotFS,wantFS,flags,realVolName)
+2025 GS/OS:EraseDisk(1-6:@DevN,@VolN,gotFS,wantFS,flags,realVolName)
+2026 GS/OS:ResetCache(0:)
+2027 GS/OS:GetName(1:@n)
+2028 GS/OS:GetBootvol(1:@n)
+2029 GS/OS:Quit(0-2:@P,flags)
+202A GS/OS:GetVersion(1:version)
+202B GS/OS:GetFSTInfo(2-7:n,fs,@n,ver,attr,bSz,mxV/4,mxF/4)
+202C GS/OS:DInfo(2-10:n,@n,chr,B/4,sl,unit,ver,dTyp,@hd,@nx)
+202D GS/OS:DStatus(5:n,statusReq,@statList,count/4,xfer/4)
+202E GS/OS:DControl(5:n,code,@ctlList,count/4,xfer/4)
+202F GS/OS:DRead(6:n,@bf,count/4,blk/4,blkSz,xfer/4)
+2030 GS/OS:DWrite(6:n,@bf,count/4,blk/4,blkSz,xfer/4)
+2031 GS/OS:BindInt(3:IntNum,VecRefNum,@handler)
+2032 GS/OS:UnbindInt(1:IntNum)
+2033 GS/OS:FSTSpecific(2+...)
+2034 GS/OS:AddNotifyProc(1:@proc)
+2035 GS/OS:DelNotifyProc(1:@proc)
+2036 GS/OS:DRename(2:n,@newName)
+2037 GS/OS:GetStdRefNum(2:pfxNum,refNum)
+2038 GS/OS:GetRefNum(2-6:@path,ref,acc,res,case,disp)
+2039 GS/OS:GetRefInfo(2-5:ref,acc,@path,resNum,level)
+203A GS/OS:SetStdRefNum(2:pfxNum,refNum)
+* System tools
+0000 === System Tools ===
+0001 === tool locator ===
+0101 TLBootInit()
+0201 TLStartUp()
+0301 TLShutDown()
+0401 TLVersion():Vers
+0501 TLReset()
+0601 TLStatus():ActFlg
+0901 GetTSPtr(SysFlg,TS#):@FPT
+0A01 SetTSPtr(SysFlg,TS#,@FPT)
+0B01 GetFuncPtr(SysFlg,Func):@Func
+0C01 GetWAP(SysFlg,TS#):@WAP
+0D01 SetWAP(SysFlg,TS#,@WAP)
+0E01 LoadTools(@ToolTable)
+0F01 LoadOneTool(TS#,MinVers)
+1001 UnloadOneTool(TS#)
+1101 TLMountVolume(X,Y,@L1,@L2,@B1,@B2):Btn#
+1201 TLTextMountVolume(@L1,@L2,@B1,@B2):Btn#
+1301 SaveTextState():StateH
+1401 RestoreTextState(StateH)
+1501 MessageCenter(Action,Type,MsgH)
+1601 SetDefaultTPT()
+1701 MessageByName(CreateF,@inpRec):Created,Type
+1801 StartUpTools(MemID,ssDesc,ssRef/4):ssRef/4
+1901 ShutDownTools(ssDesc,ssRef/4)
+1A01 GetMsgHandle(Flags,MsgRef/4):H
+1B01 AcceptRequests(@NameStr,UserID,@ReqProc)
+1C01 SendRequest(ReqCode,How,Target/4,@In,@Out)
+0002 === memory manager ===
+0102 MMBootInit()
+0202 MMStartUp():MemID
+0302 MMShutDown(MemID)
+0402 MMVersion():Vers
+0502 MMReset()
+0602 MMStatus():ActFlg
+0902 NewHandle(Size/4,MemID,Attr,@loc):H
+0A02 ReAllocHandle(Size/4,MemID,Attr,@loc,H)
+0B02 RestoreHandle(H)
+0C02 AddToOOMQueue(@header)
+0D02 RemoveFromOOMQueue(@header)
+1002 DisposeHandle(H)
+1102 DisposeAll(MemID)
+1202 PurgeHandle(H)
+1302 PurgeAll(MemID)
+1802 GetHandleSize(H):Size/4
+1902 SetHandleSize(Size/4,H)
+1A02 FindHandle(@byte):H
+1B02 FreeMem():FreeBytes/4
+1C02 MaxBlock():Size/4
+1D02 TotalMem():Size/4
+1E02 CheckHandle(H)
+1F02 CompactMem()
+2002 HLock(H)
+2102 HLockAll(MemID)
+2202 HUnlock(H)
+2302 HUnlockAll(MemID)
+2402 SetPurge(PrgLvl,H)
+2502 SetPurgeAll(PrgLvl,MemID)
+2802 PtrToHand(@Src,DestH,Count/4)
+2902 HandToPtr(SrcH,@Dest,Count/4)
+2A02 HandToHand(SrcH,DestH,Count/4)
+2B02 BlockMove(@Source,@Dest,Count/4)
+2F02 RealFreeMem():Size/4
+3002 SetHandleID(newMemID,theH):oldMemID
+0003 === misc tools ===
+0103 MTBootInit()
+0203 MTStartUp()
+0303 MTShutDown()
+0403 MTVersion():Vers
+0503 MTReset()
+0603 MTStatus():ActFlg
+0903 WriteBRam(@Buff)
+0A03 ReadBRam(@Buff)
+0B03 WriteBParam(Data,Parm#)
+0C03 ReadBParam(Parm#):Data
+0D03 ReadTimeHex():WkDay,Mn&Dy,Yr&Hr,Mn&Sec
+0E03 WriteTimeHex(Mn&Dy,Yr&Hr,Mn&Sec)
+0F03 ReadAsciiTime(@Buff)
+1003 SetVector(Vec#,@x)
+1103 GetVector(Vec#):@x
+1203 SetHeartBeat(@Task)
+1303 DelHeartBeat(@Task)
+1403 ClrHeartBeat()
+1503 SysFailMgr(Code,@Msg)
+1603 GetAddr(Ref#):@Parm
+1703 ReadMouse():X,Y,Stat&Mode
+1803 InitMouse(Slot)
+1903 SetMouse(Mode)
+1A03 HomeMouse()
+1B03 ClearMouse()
+1C03 ClampMouse(Xmn,Xmx,Ymn,Ymx)
+1D03 GetMouseClamp():Xmn,Xmx,Ymn,Ymx
+1E03 PosMouse(X,Y)
+1F03 ServeMouse():IntStat
+2003 GetNewID(Kind):MemID
+2103 DeleteID(MemID)
+2203 StatusID(MemID)
+2303 IntSource(Ref#)
+2403 FWEntry(A,X,Y,Address):P,A,X,Y
+2503 GetTick():Ticks/4
+2603 PackBytes(@StartPtr,@Sz,@OutBf,OutSz):Size
+2703 UnPackBytes(@Buff,BfSz,@StartPtr,@Sz):Size
+2803 Munger(@Dst,@DstL,@t,tL,@Rpl,RplL,@Pad):N
+2903 GetIRQEnable():IntStat
+2A03 SetAbsClamp(Xmn,Xmx,Ymn,Ymx)
+2B03 GetAbsClamp():Xmn,Xmx,Ymn,Ymx
+2C03 SysBeep()
+2E03 AddToQueue(@newTask,@queueHeader)
+2F03 DeleteFromQueue(@task,@queueHeader)
+3003 SetInterruptState(@stateRec,NumBytes)
+3103 GetInterruptState(@stateRec,NumBytes)
+3203 GetIntStateRecSize():Size
+3303 ReadMouse2():xPos,yPos,StatMode
+3403 GetCodeResConverter():@proc
+3503 GetROMResource(???,???/4):???H
+3603 ReleaseROMResource(???,???/4)
+3703 ConvSeconds(convVerb,Secs/4,@Date):SecondsOut/4
+3803 SysBeep2(beepKind)
+3903 VersionString(flags,Version/4,@Buffer)
+3A03 WaitUntil(WaitFromTime,DelayTime):NewTime
+3B03 StringToText(flags,@String,StrLen,@Buffer):ResFlags,PrntLen
+3C03 ShowBootInfo(@String,@Icon)
+3D03 ScanDevices():DevNum
+3E03 AlertMessage(@Table,MsgNum,@Subs):Button
+3F03 DoSysPrefs(bitsToClear,bitsToSet):SysPrefs
+0004 === QuickDraw II ===
+0104 QDBootInit()
+0204 QDStartUp(DirPg,MastSCB,MaxWid,MemID)
+0304 QDShutDown()
+0404 QDVersion():Vers
+0504 QDReset()
+0604 QDStatus():ActFlg
+0904 GetAddress(what):@Table
+0A04 GrafOn()
+0B04 GrafOff()
+0C04 GetStandardSCB():SCB
+0D04 InitColorTable(@Table)
+0E04 SetColorTable(Tab#,@SrcTab)
+0F04 GetColorTable(Tab#,@DestTbl)
+1004 SetColorEntry(Tab#,Ent#,NewCol)
+1104 GetColorEntry(Tab#,Ent#):Color
+1204 SetSCB(Line#,SCB)
+1304 GetSCB(Line#):SCB
+1404 SetAllSCBs(SCB)
+1504 ClearScreen(Color)
+1604 SetMasterSCB(SCB)
+1704 GetMasterSCB():SCB
+1804 OpenPort(@Port)
+1904 InitPort(@Port)
+1A04 ClosePort(@Port)
+1B04 SetPort(@Port)
+1C04 GetPort():@Port
+1D04 SetPortLoc(@LocInfo)
+1E04 GetPortLoc(@LocInfo)
+1F04 SetPortRect(@Rect)
+2004 GetPortRect(@Rect)
+2104 SetPortSize(w,h)
+2204 MovePortTo(h,v)
+2304 SetOrigin(h,v)
+2404 SetClip(RgnH)
+2504 GetClip(RgnH)
+2604 ClipRect(@Rect)
+2704 HidePen()
+2804 ShowPen()
+2904 GetPen(@Pt)
+2A04 SetPenState(@PenSt)
+2B04 GetPenState(@PenSt)
+2C04 SetPenSize(w,h)
+2D04 GetPenSize(@Pt)
+2E04 SetPenMode(Mode)
+2F04 GetPenMode():Mode
+3004 SetPenPat(@Patt)
+3104 GetPenPat(@Patt)
+3204 SetPenMask(@Mask)
+3304 GetPenMask(@Mask)
+3404 SetBackPat(@Patt)
+3504 GetBackPat(@Patt)
+3604 PenNormal()
+3704 SetSolidPenPat(Color)
+3804 SetSolidBackPat(Color)
+3904 SolidPattern(Color,@Patt)
+3A04 MoveTo(h,v)
+3B04 Move(dh,dv)
+3C04 LineTo(h,v)
+3D04 Line(dh,dv)
+3E04 SetPicSave(Val/4)
+3F04 GetPicSave():Val/4
+4004 SetRgnSave(Val/4)
+4104 GetRgnSave():Val/4
+4204 SetPolySave(Val/4)
+4304 GetPolySave():Val/4
+4404 SetGrafProcs(@GrafProcs)
+4504 GetGrafProcs():@GrafProcs
+4604 SetUserField(Val/4)
+4704 GetUserField():Val/4
+4804 SetSysField(Val/4)
+4904 GetSysField():Val/4
+4A04 SetRect(@Rect,left,top,right,bot)
+4B04 OffsetRect(@Rect,dh,dv)
+4C04 InsetRect(@Rect,dh,dv)
+4D04 SectRect(@R1,@R2,@DstR):nonEmptyF
+4E04 UnionRect(@Rect1,@Rect2,@UnionRect)
+4F04 PtInRect(@Pt,@Rect):Flag
+5004 Pt2Rect(@Pt1,@Pt2,@Rect)
+5104 EqualRect(@Rect1,@Rect2):Flag
+5204 NotEmptyRect(@Rect):Flag
+5304 FrameRect(@Rect)
+5404 PaintRect(@Rect)
+5504 EraseRect(@Rect)
+5604 InvertRect(@Rect)
+5704 FillRect(@Rect,@Patt)
+5804 FrameOval(@Rect)
+5904 PaintOval(@Rect)
+5A04 EraseOval(@Rect)
+5B04 InvertOval(@Rect)
+5C04 FillOval(@Rect,@Patt)
+5D04 FrameRRect(@Rect,OvalW,OvalHt)
+5E04 PaintRRect(@Rect,OvalW,OvalHt)
+5F04 EraseRRect(@Rect,OvalW,OvalHt)
+6004 InvertRRect(@Rect,OvalW,OvalHt)
+6104 FillRRect(@Rect,OvalW,OvalHt,@Patt)
+6204 FrameArc(@Rect,Ang1,ArcAng)
+6304 PaintArc(@Rect,Ang1,ArcAng)
+6404 EraseArc(@Rect,Ang1,ArcAng)
+6504 InvertArc(@Rect,Ang1,ArcAng)
+6604 FillArc(@Rect,Ang1,ArcAng,@Patt)
+6704 NewRgn():RgnH
+6804 DisposeRgn(RgnH)
+6904 CopyRgn(SrcRgnH,DestRgnH)
+6A04 SetEmptyRgn(RgnH)
+6B04 SetRectRgn(RgnH,left,top,right,bot)
+6C04 RectRgn(RgnH,@Rect)
+6D04 OpenRgn()
+6E04 CloseRgn(RgnH)
+6F04 OffsetRgn(RgnH,dh,dv)
+7004 InsetRgn(RgnH,dh,dv)
+7104 SectRgn(Rgn1H,Rgn2H,DstRgnH)
+7204 UnionRgn(Rgn1H,Rgn2H,UnionRgnH)
+7304 DiffRgn(Rgn1H,Rgn2H,DstRgnH)
+7404 XorRgn(Rgn1H,Rgn2H,DstRgnH)
+7504 PtInRgn(@Pt,RgnH):Flag
+7604 RectInRgn(@Rect,RgnH):Flag
+7704 EqualRgn(Rgn1H,Rgn2H):Flag
+7804 EmptyRgn(RgnH):Flag
+7904 FrameRgn(RgnH)
+7A04 PaintRgn(RgnH)
+7B04 EraseRgn(RgnH)
+7C04 InvertRgn(RgnH)
+7D04 FillRgn(RgnH,@Patt)
+7E04 ScrollRect(@Rect,dh,dv,UpdtRgnH)
+7F04 PaintPixels(@ppParms)
+8004 AddPt(@SrcPt,@DestPt)
+8104 SubPt(@SrcPt,@DstPt)
+8204 SetPt(@Pt,h,v)
+8304 EqualPt(@Pt1,@Pt2):Flag
+8404 LocalToGlobal(@Pt)
+8504 GlobalToLocal(@Pt)
+8604 Random():N
+8704 SetRandSeed(Seed/4)
+8804 GetPixel(Hor,Vert):Pixel
+8904 ScalePt(@Pt,@SrcRect,@DstRect)
+8A04 MapPt(@Pt,@SrcRect,@DstRect)
+8B04 MapRect(@Rect,@SrcRect,@DstRect)
+8C04 MapRgn(MapRgnH,@SrcRect,@DstRect)
+8D04 SetStdProcs(@StdProcRec)
+8E04 SetCursor(@Curs)
+8F04 GetCursorAdr():@Curs
+9004 HideCursor()
+9104 ShowCursor()
+9204 ObscureCursor()
+9304 SetMouseLoc ???
+9404 SetFont(FontH)
+9504 GetFont():FontH
+9604 GetFontInfo(@InfoRec)
+9704 GetFontGlobals(@FGRec)
+9804 SetFontFlags(Flags)
+9904 GetFontFlags():Flags
+9A04 SetTextFace(TextF)
+9B04 GetTextFace():TextF
+9C04 SetTextMode(TextM)
+9D04 GetTextMode():TextM
+9E04 SetSpaceExtra(SpEx/4f)
+9F04 GetSpaceExtra():SpEx/4f
+A004 SetForeColor(Color)
+A104 GetForeColor():Color
+A204 SetBackColor(BackCol)
+A304 GetBackColor():BackCol
+A404 DrawChar(Char)
+A504 DrawString(@Str)
+A604 DrawCString(@cStr)
+A704 DrawText(@Text,Len)
+A804 CharWidth(Char):Width
+A904 StringWidth(@Str):Width
+AA04 CStringWidth(@cStr):Width
+AB04 TextWidth(@Text,Len):Width
+AC04 CharBounds(Char,@Rect)
+AD04 StringBounds(@Str,@Rect)
+AE04 CStringBounds(@cStr,@Rect)
+AF04 TextBounds(@Text,Len,@Rect)
+B004 SetArcRot(ArcRot)
+B104 GetArcRot():ArcRot
+B204 SetSysFont(FontH)
+B304 GetSysFont():FontH
+B404 SetVisRgn(RgnH)
+B504 GetVisRgn(RgnH)
+B604 SetIntUse(Flag)
+B704 OpenPicture(@FrameRect):PicH
+B804 PicComment(Kind,DataSz,DataH)
+B904 ClosePicture()
+BA04 DrawPicture(PicH,@DstRect)
+BB04 KillPicture(PicH)
+BC04 FramePoly(PolyH)
+BD04 PaintPoly(PolyH)
+BE04 ErasePoly(PolyH)
+BF04 InvertPoly(PolyH)
+C004 FillPoly(PolyH,@Patt)
+C104 OpenPoly():PolyH
+C204 ClosePoly()
+C304 KillPoly(PolyH)
+C404 OffsetPoly(PolyH,dh,dv)
+C504 MapPoly(PolyH,@SrcRect,@DstRect)
+C604 SetClipHandle(RgnH)
+C704 GetClipHandle():RgnH
+C804 SetVisHandle(RgnH)
+C904 GetVisHandle():RgnH
+CA04 InitCursor()
+CB04 SetBufDims(MaxW,MaxFontHt,MaxFBRext)
+CC04 ForceBufDims(MaxW,MaxFontHt,MaxFBRext)
+CD04 SaveBufDims(@SizeInfo)
+CE04 RestoreBufDims(@SizeInfo)
+CF04 GetFGSize():FGSize
+D004 SetFontID(FontID/4)
+D104 GetFontID():FontID/4
+D204 SetTextSize(TextSz)
+D304 GetTextSize():TextSz
+D404 SetCharExtra(ChEx/4f)
+D504 GetCharExtra():ChEx/4f
+D604 PPToPort(@SrcLoc,@SrcRect,X,Y,Mode)
+D704 InflateTextBuffer(NewW,NewHt)
+D804 GetRomFont(@Rec)
+D904 GetFontLore(@Rec,RecSize):Size
+DA04 Get640Colors():@PattTable
+DB04 Set640Color(color)
+0005 === desk manager ===
+0105 DeskBootInit()
+0205 DeskStartUp()
+0305 DeskShutDown()
+0405 DeskVersion():Vers
+0505 DeskReset()
+0605 DeskStatus():ActFlg
+0905 SaveScrn()
+0A05 RestScrn()
+0B05 SaveAll()
+0C05 RestAll()
+0E05 InstallNDA(ndaH)
+0F05 InstallCDA(cdaH)
+1105 ChooseCDA()
+1305 SetDAStrPtr(AltDispH,@StrTbl)
+1405 GetDAStrPtr():@StrTbl
+1505 OpenNDA(ItemID):Ref#
+1605 CloseNDA(Ref#)
+1705 SystemClick(@EvRec,@Wind,fwRes)
+1805 SystemEdit(eType):Flag
+1905 SystemTask()
+1A05 SystemEvent(Mods,Where/4,When/4,Msg/4,What):F
+1B05 GetNumNDAs():N
+1C05 CloseNDAbyWinPtr(@Wind)
+1D05 CloseAllNDAs()
+1E05 FixAppleMenu(MenuID)
+1F05 AddToRunQ(@taskHeader)
+2005 RemoveFromRunQ(@taskHeader)
+2105 RemoveCDA(cdaH)
+2205 RemoveNDA(ndaH)
+2305 GetDeskAccInfo(flags,daRef/4,BufSize,@Buffer)
+2405 CallDeskAcc(flags,daRef/4,Action,Data/4):Result
+2505 GetDeskGlobal(selector):Value/4
+0006 === event manager ===
+0106 EMBootInit()
+0206 EMStartUp(DirPg,qSz,Xmn,Xmx,Ymn,Ymx,MemID)
+0306 EMShutDown()
+0406 EMVersion():Vers
+0506 EMReset()
+0606 EMStatus():ActFlg
+0906 DoWindows():DirPg
+0A06 GetNextEvent(evMask,@EvRec):Flag
+0B06 EventAvail(evMask,@EvRec):Flag
+0C06 GetMouse(@Pt)
+0D06 Button(Btn#):DownFlg
+0E06 StillDown(Btn#):Flag
+0F06 WaitMouseUp(Btn#):Flag
+1006 TickCount():Ticks/4
+1106 GetDblTime():Ticks/4
+1206 GetCaretTime():Ticks/4
+1306 SetSwitch()
+1406 PostEvent(code,Msg/4):Flag
+1506 FlushEvents(evMask,StopMask):F
+1606 GetOSEvent(evMask,@EvRec):Flag
+1706 OSEventAvail(evMask,@EvRec):Flag
+1806 SetEventMask(evMask)
+1906 FakeMouse(ChFlg,Mods,X,Y,BtnStat)
+1A06 SetAutoKeyLimit(NewLimit)
+1B06 GetKeyTranslation():kTransID
+1C06 SetKeyTranslation(kTransID)
+0007 === scheduler ===
+0107 SchBootInit()
+0207 SchStartUp()
+0307 SchShutDown()
+0407 SchVersion():Vers
+0507 SchReset()
+0607 SchStatus():ActFlg
+0907 SchAddTask(@Task):Flag
+0A07 SchFlush()
+0008 === sound manager ===
+0108 SoundBootInit()
+0208 SoundStartUp(DirPg)
+0308 SoundShutDown()
+0408 SoundVersion():Vers
+0508 SoundReset()
+0608 SoundToolStatus():ActFlg
+0908 WriteRamBlock(@Src,DOCStart,Count)
+0A08 ReadRamBlock(@Dest,DOCStart,Count)
+0B08 GetTableAddress():@JumpTbl
+0C08 GetSoundVolume(Gen#):Vol
+0D08 SetSoundVolume(Vol,Gen#)
+0E08 FFStartSound(GenN&mode,@Parms)
+0F08 FFStopSound(GenMask)
+1008 FFSoundStatus():ActFlg
+1108 FFGeneratorStatus(Gen#):Stat
+1208 SetSoundMIRQV(@IntHandler)
+1308 SetUserSoundIRQV(@NewIRQ):@OldIRQ
+1408 FFSoundDoneStatus(Gen#):Stat
+1508 FFSetUpSound(ChannelGen,@Parms)
+1608 FFStartPlaying(GenWord)
+1708 SetDocReg(@DocRegParms)
+1808 ReadDocReg(@DocRegParms)
+0009 === desktop bus ===
+0109 ADBBootInit()
+0209 ADBStartUp()
+0309 ADBShutDown()
+0409 ADBVersion():Vers
+0509 ADBReset()
+0609 ADBStatus():ActFlg
+0909 SendInfo(NumB,@Data,Cmd)
+0A09 ReadKeyMicroData(NumB,@Data,Cmd)
+0B09 ReadKeyMicroMemory(@DataOut,@DataIn,Cmd)
+0C09 [resynch--don't call]
+0D09 AsyncADBReceive(@CompVec,Cmd)
+0E09 SyncADBReceive(InputWrd,@CompVec,Cmd)
+0F09 AbsOn()
+1009 AbsOff()
+1109 RdAbs():Flag
+1209 SetAbsScale(@DataOut)
+1309 GetAbsScale(@DataIn)
+1409 SRQPoll(@CompVec,ADBreg)
+1509 SRQRemove(ADBreg)
+1609 ClearSRQTable()
+FF09 [OBSOLETE: Use 09FF]
+000A === SANE ===
+010A SANEBootInit()
+020A SANEStartUp(DirPg)
+030A SANEShutDown()
+040A SANEVersion():Vers
+050A SANEReset()
+060A SANEStatus():ActFlg
+090A FPNum (...)
+0A0A DecStrNum (...)
+0B0A ElemNum (...)
+FF0A [OBSOLETE: USE $0AFF]
+000B === integer math ===
+010B IMBootInit()
+020B IMStartUp()
+030B IMShutDown()
+040B IMVersion():Vers
+050B IMReset()
+060B IMStatus():ActFlg
+090B Multiply(A,B):Prod/4
+0A0B SDivide(Num,Den):Rem,Quot
+0B0B UDivide(Num,Den):Rem,Quot
+0C0B LongMul(A/4,B/4):Prod/8
+0D0B LongDivide(Num/4,Denom/4):Rem/4,Quot/4
+0E0B FixRatio(Numer,Denom):fxRatio/4
+0F0B FixMul(fx1/4,fx2/4):fxProd/4
+100B FracMul(fr1/4,fr2/4):frRes/4
+110B FixDiv(Quot/4,Divisor/4):fxRes/4
+120B FracDiv(Quot/4,Divisor/4):frRes/4
+130B FixRound(fxVal/4):Int
+140B FracSqrt(frVal/4):frRes/4
+150B FracCos(fxAngle/4):frRes/4
+160B FracSin(fxAngle/4):frRes/4
+170B FixATan2(In1/4,In2/4):fxArcTan/4
+180B HiWord(Long/4):Int
+190B LoWord(Long/4):Int
+1A0B Long2Fix(Long/4):fxRes/4
+1B0B Fix2Long(Fix/4):Long/4
+1C0B Fix2Frac(fxVal/4):Frac/4
+1D0B Frac2Fix(frVal/4):fxRes/4
+1E0B Fix2X(Fix/4,@Extended)
+1F0B Frac2X(frVal/4,@Extended)
+200B X2Fix(@Extended):fxRes/4
+210B X2Frac(@Extended):frRes/4
+220B Int2Hex(Int,@Str,Len)
+230B Long2Hex(Long/4,@Str,Len)
+240B Hex2Int(@Str,Len):Int
+250B Hex2Long(@Str,Len):Long/4
+260B Int2Dec(Int,@Str,Len,SgnFlg)
+270B Long2Dec(Long/4,@Str,Len,SgnFlg)
+280B Dec2Int(@Str,Len,SgnFlg):Int
+290B Dec2Long(@Str,Len,SgnFlg):Long/4
+2A0B HexIt(Int):Hex/4
+000C === text tools ===
+010C TextBootInit()
+020C TextStartUp()
+030C TextShutDown()
+040C TextVersion():Vers
+050C TextReset()
+060C TextStatus():ActFlg
+090C SetInGlobals(ANDmsk,ORmsk)
+0A0C SetOutGlobals(ANDmsk,ORmsk)
+0B0C SetErrGlobals(ANDmsk,ORmsk)
+0C0C GetInGlobals():ANDmsk,ORmsk
+0D0C GetOutGlobals():ANDmsk,ORmsk
+0E0C GetErrGlobals():ANDmsk,ORmsk
+0F0C SetInputDevice(Type,@drvr|Slot/4)
+100C SetOutputDevice(Type,@drvr|Slot/4)
+110C SetErrorDevice(Type,@drvr|Slot/4)
+120C GetInputDevice():Type,@drvr|Slot/4
+130C GetOutputDevice():Type,@drvr|Slot/4
+140C GetErrorDevice():Type,@drvr|Slot/4
+150C InitTextDev(dev)
+160C CtlTextDev(dev,code)
+170C StatusTextDev(dev,request)
+180C WriteChar(Char)
+190C ErrWriteChar(Char)
+1A0C WriteLine(@Str)
+1B0C ErrWriteLine(@Str)
+1C0C WriteString(@Str)
+1D0C ErrWriteString(@Str)
+1E0C TextWriteBlock(@Text,Offset,Len)
+1F0C ErrWriteBlock(@Text,Offset,Len)
+200C WriteCString(@cStr)
+210C ErrWriteCString(@cStr)
+220C ReadChar(EchoFlg):Char
+230C TextReadBlock(@Buff,Offset,Size,EchoFlg)
+240C ReadLine(@Buff,Max,EOLch,EchoFlg):Count
+000D === reserved ===
+000E === window manager ===
+010E WindBootInit()
+020E WindStartUp(MemID)
+030E WindShutDown()
+040E WindVersion():Vers
+050E WindReset()
+060E WindStatus():ActFlg
+090E NewWindow(@Parms):@Wind
+0A0E CheckUpdate(@EvRec):Flag
+0B0E CloseWindow(@Wind)
+0C0E Desktop(Oper,param/4):result/4
+0D0E SetWTitle(@Title,@Wind)
+0E0E GetWTitle(@Wind):@Title
+0F0E SetFrameColor(@NewColTbl,@Wind)
+100E GetFrameColor(@Table,@Wind)
+110E SelectWindow(@Wind)
+120E HideWindow(@Wind)
+130E ShowWindow(@Wind)
+140E SendBehind(@BehindWho,@Wind)
+150E FrontWindow():@Wind
+160E SetInfoDraw(@Proc,@Wind)
+170E FindWindow(@WindVar,X,Y):Where
+180E TrackGoAway(X,Y,@Wind):Flag
+190E MoveWindow(X,Y,@Wind)
+1A0E DragWindow(Grid,X,Y,Grace,@bRect,@Wind)
+1B0E GrowWindow(mnW,mnH,X,Y,@Wind):nSize/4
+1C0E SizeWindow(w,h,@Wind)
+1D0E TaskMaster(evMask,@TaskRec):Code
+1E0E BeginUpdate(@Wind)
+1F0E EndUpdate(@Wind)
+200E GetWMgrPort():@Port
+210E PinRect(X,Y,@Rect):Point/4
+220E HiliteWindow(Flag,@Wind)
+230E ShowHide(Flag,@Wind)
+240E BringToFront(@Wind)
+250E WindNewRes()
+260E TrackZoom(X,Y,@Wind):Flag
+270E ZoomWindow(@Wind)
+280E SetWRefCon(Refcon/4,@Wind)
+290E GetWRefCon(@Wind):Refcon/4
+2A0E GetNextWindow(@Wind):@Wind
+2B0E GetWKind(@Wind):Flag
+2C0E GetWFrame(@Wind):Frame
+2D0E SetWFrame(Frame,@Wind)
+2E0E GetStructRgn(@Wind):StructRgnH
+2F0E GetContentRgn(@Wind):ContRgnH
+300E GetUpdateRgn(@Wind):UpdateRgnH
+310E GetDefProc(@Wind):@Proc
+320E SetDefProc(@Proc,@Wind)
+330E GetWControls(@Wind):CtrlH
+340E SetOriginMask(Mask,@Wind)
+350E GetInfoRefCon(@Wind):Refcon/4
+360E SetInfoRefCon(Val/4,@Wind)
+370E GetZoomRect(@Wind):@zRect
+380E SetZoomRect(@zRect,@Wind)
+390E RefreshDesktop(@Rect)
+3A0E InvalRect(@Rect)
+3B0E InvalRgn(RgnH)
+3C0E ValidRect(@Rect)
+3D0E ValidRgn(RgnH)
+3E0E GetContentOrigin(@Wind):Origin/4
+3F0E SetContentOrigin(X,Y,@Wind)
+400E GetDataSize(@Wind):DataSize/4
+410E SetDataSize(w,h,@Wind)
+420E GetMaxGrow(@Wind):MaxGrow/4
+430E SetMaxGrow(maxWidth,maxHeight,@Wind)
+440E GetScroll(@Wind):Scroll/4
+450E SetScroll(h,v,@Wind)
+460E GetPage(@Wind):Page/4
+470E SetPage(h,v,@Wind)
+480E GetContentDraw(@Wind):@Proc
+490E SetContentDraw(@Proc,@Wind)
+4A0E GetInfoDraw(@Wind):@Proc
+4B0E SetSysWindow(@Wind)
+4C0E GetSysWFlag(@Wind):Flag
+4D0E StartDrawing(@Wind)
+4E0E SetWindowIcons(NewFontH):OldFontH
+4F0E GetRectInfo(@InfoRect,@Wind)
+500E StartInfoDrawing(@iRect,@Wind)
+510E EndInfoDrawing()
+520E GetFirstWindow():@Wind
+530E WindDragRect(@a,@P,X,Y,@R,@lR,@sR,F):M/4
+540E Private01():@func [GetDragRectPtr]
+550E DrawInfoBar(@Wind)
+560E WindowGlobal(Flags):Flags
+570E SetContentOrigin2(ScrollFlag,X,Y,@Wind)
+580E GetWindowMgrGlobals():@Globals
+590E AlertWindow(AlertDesc,@SubArray,AlertRef/4):Btn
+5A0E StartFrameDrawing(@Wind)
+5B0E EndFrameDrawing()
+5C0E ResizeWindow(hidden,@ContRect,@Wind)
+5D0E TaskMasterContent
+5E0E TaskMasterKey
+5F0E TaskMasterDA(evMask,@bigTaskRec):taskCode
+600E CompileText(subType,@subs,@text,size):H
+610E NewWindow2(@T,RC/4,@draw,@def,pDesc,pRef/4,rType):@W
+620E ErrorWindow(subType,@subs,ErrNum):Button
+630E GetAuxWindInfo(@Wind):@Info
+640E DoModalWindow(@Event,@Update,@EvHook,@Beep,Flags):Result/4
+650E MWGetCtlPart():Part
+660E MWSetMenuProc(@NewMenuProc):@OldMenuProc
+670E MWStdDrawProc()
+680E MWSetUpEditMenu()
+690E FindCursorCtl(@CtrlH,x,y,@Wind):PartCode
+6A0E ResizeInfoBar(flags,newHeight,@Wind)
+6B0E HandleDiskInsert(flags,devNum):resFlags,resDevNum
+6C0E UpdateWindow(flags,@Wind)
+000F === menu manager ===
+010F MenuBootInit()
+020F MenuStartUp(MemID,DirPg)
+030F MenuShutDown()
+040F MenuVersion():Vers
+050F MenuReset()
+060F MenuStatus():ActFlg
+090F MenuKey(@TaskRec,BarH)
+0A0F GetMenuBar():BarH
+0B0F MenuRefresh(@RedrawProc)
+0C0F FlashMenuBar()
+0D0F InsertMenu(MenuH,AfterWhat)
+0E0F DeleteMenu(MenuID)
+0F0F InsertMItem(@Item,AfterItem,MenuID)
+100F DeleteMItem(ItemID)
+110F GetSysBar():BarH
+120F SetSysBar(BarH)
+130F FixMenuBar():Height
+140F CountMItems(MenuID):N
+150F NewMenuBar(@Wind):BarH
+160F GetMHandle(MenuID):MenuH
+170F SetBarColors(BarCol,InvCol,OutCol)
+180F GetBarColors():Colors/4
+190F SetMTitleStart(hStart)
+1A0F GetMTitleStart():hStart
+1B0F GetMenuMgrPort():@Port
+1C0F CalcMenuSize(w,h,MenuID)
+1D0F SetMTitleWidth(w,MenuID)
+1E0F GetMTitleWidth(MenuID):TitleWidth
+1F0F SetMenuFlag(Flags,MenuID)
+200F GetMenuFlag(MenuID):Flags
+210F SetMenuTitle(@Title,MenuID)
+220F GetMenuTitle(MenuID):@Title
+230F MenuGlobal(Flags):Flags
+240F SetMItem(@Str,ItemID)
+250F GetMItem(ItemID):@ItemName
+260F SetMItemFlag(Flags,ItemID)
+270F GetMItemFlag(ItemID):Flag
+280F SetMItemBlink(Count)
+290F MenuNewRes()
+2A0F DrawMenuBar()
+2B0F MenuSelect(@TaskRec,BarH)
+2C0F HiliteMenu(Flag,MenuID)
+2D0F NewMenu(@MenuStr):MenuH
+2E0F DisposeMenu(MenuH)
+2F0F InitPalette()
+300F EnableMItem(ItemID)
+310F DisableMItem(ItemID)
+320F CheckMItem(Flag,ItemID)
+330F SetMItemMark(MarkCh,ItemID)
+340F GetMItemMark(ItemID):MarkChar
+350F SetMItemStyle(TextStyle,ItemID)
+360F GetMItemStyle(ItemID):TextStyle
+370F SetMenuID(New,Old)
+380F SetMItemID(New,Old)
+390F SetMenuBar(BarH)
+3A0F SetMItemName(@Str,ItemID)
+3B0F GetPopUpDefProc():@proc
+3C0F PopUpMenuSelect(SelID,left,top,flag,MenuH):id
+3D0F [DrawPopUp(SelID,Flag,right,bottom,left,top,MenuH)]
+3E0F NewMenu2(RefDesc,Ref/4):MenuH
+3F0F InsertMItem2(RefDesc,Ref/4,After,MenuID)
+400F SetMenuTitle2(RefDesc,TitleRef/4,MenuID)
+410F SetMItem2(RefDesc,Ref/4,Item)
+420F SetMItemName2(RefDesc,Ref/4,Item)
+430F NewMenuBar2(RefDesc,Ref/4,@Wind):BarH
+450F HideMenuBar()
+460F ShowMenuBar()
+470F SetMItemIcon(IconDesc,IconRef/4,ItemID)
+480F GetMItemIcon(ItemID):IconRef/4
+490F SetMItemStruct(Desc,StructRef/4,ItemID)
+4A0F GetMItemStruct(ItemID):ItemStruct/4
+4B0F RemoveMItemStruct(ItemID)
+4C0F GetMItemFlag2(ItemID):ItemFlag2
+4D0F SetMItemFlag2(newValue,ItemID)
+4F0F GetMItemBlink():Count
+500F InsertPathMItems(flags,@Path,devnum,MenuID,AfterID,StartID,@Results)
+0010 === control manager ===
+0110 CtlBootInit()
+0210 CtlStartUp(MemID,DirPg)
+0310 CtlShutDown()
+0410 CtlVersion():Vers
+0510 CtlReset()
+0610 CtlStatus():ActFlg
+0910 NewControl(@W,@R,@T,F,V,P1,P2,@p,r/4,@C):cH
+0A10 DisposeControl(CtrlH)
+0B10 KillControls(@Wind)
+0C10 SetCtlTitle(@Title,CtrlH)
+0D10 GetCtlTitle(CtrlH):@Title
+0E10 HideControl(CtrlH)
+0F10 ShowControl(CtrlH)
+1010 DrawControls(@Wind)
+1110 HiliteControl(Flag,CtrlH)
+1210 CtlNewRes()
+1310 FindControl(@CtrlHVar,X,Y,@Wind):Part
+1410 TestControl(X,Y,CtrlH):Part
+1510 TrackControl(X,Y,@ActProc,CtrlH):Part
+1610 MoveControl(X,Y,CtrlH)
+1710 DragControl(X,Y,@LimR,@slR,Axis,CtrlH)
+1810 SetCtlIcons(FontH):OldFontH
+1910 SetCtlValue(Val,CtrlH)
+1A10 GetCtlValue(CtrlH):Val
+1B10 SetCtlParams(P2,P1,CtrlH)
+1C10 GetCtlParams(CtrlH):P1,P2
+1D10 DragRect(@acPr,@P,X,Y,@drR,@l,@slR,F):M/4
+1E10 GrowSize():Size/4
+1F10 GetCtlDpage():DirPg
+2010 SetCtlAction(@ActProc,CtrlH)
+2110 GetCtlAction(CtrlH):Action/4
+2210 SetCtlRefCon(Refcon/4,CtrlH)
+2310 GetCtlRefCon(CtrlH):Refcon/4
+2410 EraseControl(CtrlH)
+2510 DrawOneCtl(CtrlH)
+2610 FindTargetCtl():CtrlH
+2710 MakeNextCtlTarget():CtrlH
+2810 MakeThisCtlTarget(CtrlH)
+2910 SendEventToCtl(TgtOnly,@Wind,@eTask):Accepted
+2A10 GetCtlID(CtrlH):CtlID/4
+2B10 SetCtlID(CtlID/4,CtrlH)
+2C10 CallCtlDefProc(CtrlH,Msg,Param/4):Result/4
+2D10 NotifyCtls(Mask,Msg,Param/4,@Wind)
+2E10 GetCtlMoreFlags(CtrlH):Flags
+2F10 SetCtlMoreFlags(Flags,CtrlH)
+3010 GetCtlHandleFromID(@Wind,CtlID/4):CtrlH
+3110 NewControl2(@Wind,InKind,InRef/4):CtrlH
+3210 CMLoadResource(rType,rID/4):resH
+3310 CMReleaseResource(rType,rID/4)
+3410 SetCtlParamPtr(@SubArray)
+3510 GetCtlParamPtr():@SubArray
+3710 InvalCtls(@Wind)
+3810 [reserved]
+3910 FindRadioButton(@Wind,FamilyNum):WhichRadio
+3A10 SetLETextByID(@Wind,leID/4,@PString)
+3B10 GetLETextByID(@Wind,leID/4,@PString)
+3C10 SetCtlValueByID(Value,@Wind,CtlID/4)
+3D10 GetCtlValueByID(@Wind,CtlID/4):Value
+3E10 InvalOneCtlByID(@Wind,CtlID/4)
+3F10 HiliteCtlByID(Hilite,@Wind,CtlID/4)
+0011 === loader ===
+0111 LoaderBootInit()
+0211 LoaderStartUp()
+0311 LoaderShutDown()
+0411 LoaderVersion():Vers
+0511 LoaderReset()
+0611 LoaderStatus():ActFlg
+0911 InitialLoad(MemID,@path,F):dpsSz,dps,@l,MemID
+0A11 Restart(MemID):dpsSz,dps,@loc,MemID
+0B11 LoadSegNum(MemID,file#,seg#):@loc
+0C11 UnloadSegNum(MemID,file#,seg#)
+0D11 LoadSegName(MemID,@path,@segn):@loc,MemID,file#,sg#
+0E11 UnloadSeg(@loc):seg#,file#,MemID
+0F11 GetLoadSegInfo(MemID,file#,seg#,@buff)
+1011 GetUserID(@Pathname):MemID
+1111 LGetPathname(MemID,file#):@path
+1211 UserShutDown(MemID,qFlag):MemID
+1311 RenamePathname(@path1,@path2)
+2011 InitialLoad2(MemID,@in,F,Type):dpsSz,dps,@l,MemID
+2111 GetUserID2(@path):MemID
+2211 LGetPathname2(MemID,file#):@path
+0012 === QuickDraw Aux ===
+0112 QDAuxBootInit()
+0212 QDAuxStartUp()
+0312 QDAuxShutDown()
+0412 QDAuxVersion():Vers
+0512 QDAuxReset()
+0612 QDAuxStatus():ActFlg
+0912 CopyPixels(@sLoc,@dLoc,@sRect,@dRct,M,MskH)
+0A12 WaitCursor()
+0B12 DrawIcon(@Icon,Mode,X,Y)
+0C12 SpecialRect(@Rect,FrameColor,FillColor)
+0D12 SeedFill(@sLoc,@sR,@dLoc,@dR,X,Y,Mode,@Patt,@Leak)
+0E12 CalcMask(@sLoc,@sR,@dLoc,@dR,Mode,@Patt,@Leak)
+0F12 GetSysIcon(flags,value,aux/4):@Icon
+1012 PixelMap2Rgn(@srcLoc,bitsPerPix,colorMask):RgnH
+1312 IBeamCursor()
+1412 WhooshRect(flags/4,@smallRect,@bigRect)
+1512 DrawStringWidth(Flags,Ref/4,Width)
+1612 UseColorTable(tableNum,@Table,Flags):ColorInfoH
+1712 RestoreColorTable(ColorInfoH,Flags)
+0013 === print manager ===
+0113 PMBootInit()
+0213 PMStartUp(MemID,DirPg)
+0313 PMShutDown()
+0413 PMVersion():Vers
+0513 PMReset()
+0613 PMStatus():ActFlg
+0913 PrDefault(PrRecH)
+0A13 PrValidate(PrRecH):Flag
+0B13 PrStlDialog(PrRecH):Flag
+0C13 PrJobDialog(PrRecH):Flag
+0D13 PrPixelMap(@LocInfo,@SrcRect,colorFlag)
+0E13 PrOpenDoc(PrRecH,@Port):@Port
+0F13 PrCloseDoc(@Port)
+1013 PrOpenPage(@Port,@Frame)
+1113 PrClosePage(@Port)
+1213 PrPicFile(PrRecH,@Port,@StatRec)
+1313 PrControl [obsolete]
+1413 PrError():Error
+1513 PrSetError(Error)
+1613 PrChoosePrinter():DrvFlag
+1813 PrGetPrinterSpecs():Type,Characteristics
+1913 PrDevPrChanged(@PrinterName)
+1A13 PrDevStartup(@PrinterName,@ZoneName)
+1B13 PrDevShutDown()
+1C13 PrDevOpen(@compProc,Reserved/4)
+1D13 PrDevRead(@buffer,reqCount):xferCount
+1E13 PrDevWrite(@compProc,@buff,bufLen)
+1F13 PrDevClose()
+2013 PrDevStatus(@statBuff)
+2113 PrDevAsyncRead(@compPr,bufLen,@buff):xferCount
+2213 PrDevWriteBackground(@compProc,bufLen,@buff)
+2313 PrDriverVer():Vers
+2413 PrPortVer():Vers
+2513 PrGetZoneName():@ZoneName
+2813 PrGetPrinterDvrName():@Name
+2913 PrGetPortDvrName():@Name
+2A13 PrGetUserName():@Name
+2B13 PrGetNetworkName():@Name
+3013 PrDevIsItSafe():safeFlag
+3113 GetZoneList [obsolete?]
+3213 GetMyZone [obsolete?]
+3313 GetPrinterList [obsolete?]
+3413 PMUnloadDriver(whichDriver)
+3513 PMLoadDriver(whichDriver)
+3613 PrGetDocName():@pStr
+3713 PrSetDocName(@pStr)
+3813 PrGetPgOrientation(PrRecH):Orientation
+0014 === line edit ===
+0114 LEBootInit()
+0214 LEStartUp(MemID,DirPg)
+0314 LEShutDown()
+0414 LEVersion():Vers
+0514 LEReset()
+0614 LEStatus():ActFlg
+0914 LENew(@DstRect,@ViewRect,MaxL):leH
+0A14 LEDispose(leH)
+0B14 LESetText(@Text,Len,leH)
+0C14 LEIdle(leH)
+0D14 LEClick(@EvRec,leH)
+0E14 LESetSelect(Start,End,leH)
+0F14 LEActivate(leH)
+1014 LEDeactivate(leH)
+1114 LEKey(Key,Mods,leH)
+1214 LECut(leH)
+1314 LECopy(leH)
+1414 LEPaste(leH)
+1514 LEDelete(leH)
+1614 LEInsert(@Text,Len,leH)
+1714 LEUpdate(leH)
+1814 LETextBox(@Text,Len,@Rect,Just)
+1914 LEFromScrap()
+1A14 LEToScrap()
+1B14 LEScrapHandle():ScrapH
+1C14 LEGetScrapLen():Len
+1D14 LESetScrapLen(NewL)
+1E14 LESetHilite(@HiliteProc,leH)
+1F14 LESetCaret(@CaretProc,leH)
+2014 LETextBox2(@Text,Len,@Rect,Just)
+2114 LESetJust(Just,leH)
+2214 LEGetTextHand(leH):TextH
+2314 LEGetTextLen(leH):TxtLen
+2414 GetLEDefProc():@proc
+2514 LEClassifyKey(@Event):Flag
+0015 === dialog manager ===
+0115 DialogBootInit()
+0215 DialogStartUp(MemID)
+0315 DialogShutDown()
+0415 DialogVersion():Vers
+0515 DialogReset()
+0615 DialogStatus():ActFlg
+0915 ErrorSound(@SoundProc)
+0A15 NewModalDialog(@bR,vis,refcon/4):@Dlog
+0B15 NewModelessDialog(@R,@T,@b,fr,rf/4,@zR):@D
+0C15 CloseDialog(@Dlog)
+0D15 NewDItem(@Dlog,dItem,@R,ty,Des/4,V,F,@Col)
+0E15 RemoveDItem(@Dlog,dItem)
+0F15 ModalDialog(@FilterProc):Hit
+1015 IsDialogEvent(@EvRec):Flag
+1115 DialogSelect(@EvRec,@Dlog,@Hit):Flag
+1215 DlgCut(@Dlog)
+1315 DlgCopy(@Dlog)
+1415 DlgPaste(@Dlog)
+1515 DlgDelete(@Dlog)
+1615 DrawDialog(@Dlog)
+1715 Alert(@AlertTmpl,@FiltProc):Hit
+1815 StopAlert(@AlertTmpl,@FiltProc):Hit
+1915 NoteAlert(@AlertTmpl,@FiltProc):Hit
+1A15 CautionAlert(@AlertTmpl,@FiltProc):Hit
+1B15 ParamText(@P0,@P1,@P2,@P3)
+1C15 SetDAFont(FontH)
+1E15 GetControlDItem(@Dlog,dItem):CtrlH
+1F15 GetIText(@Dlog,dItem,@Str)
+2015 SetIText(@Dlog,dItem,@Str)
+2115 SelectIText(@Dlog,dItem,start,end)
+2215 HideDItem(@Dlog,dItem)
+2315 ShowDItem(@Dlog,dItem)
+2415 FindDItem(@Dlog,Point/4):Hit
+2515 UpdateDialog(@Dlog,UpdtRgnH)
+2615 GetDItemType(@Dlog,dItem):type
+2715 SetDItemType(type,@Dlog,dItem)
+2815 GetDItemBox(@Dlog,dItem,@Rect)
+2915 SetDItemBox(@Dlog,dItem,@Rect)
+2A15 GetFirstDItem(@Dlog):dItem
+2B15 GetNextDItem(@Dlog,dItem):dItem
+2C15 ModalDialog2(@FilterProc):HitInfo/4
+2E15 GetDItemValue(@Dlog,dItem):Val
+2F15 SetDItemValue(val,@Dlog,dItem)
+3215 GetNewModalDialog(@DlogTmpl):@Dlog
+3315 GetNewDItem(@Dlog,@ItemTmpl)
+3415 GetAlertStage():Stage
+3515 ResetAlertStage()
+3615 DefaultFilter(@Dlog,@EvRec,@Hit):Flag
+3715 GetDefButton(@Dlog):dItem
+3815 SetDefButton(BtnID,@Dlog)
+3915 DisableDItem(@Dlog,dItem)
+3A15 EnableDItem(@Dlog,dItem)
+0016 === scrap manager ===
+0116 ScrapBootInit()
+0216 ScrapStartUp()
+0316 ScrapShutDown()
+0416 ScrapVersion():Vers
+0516 ScrapReset()
+0616 ScrapStatus():ActFlg
+0916 UnloadScrap()
+0A16 LoadScrap()
+0B16 ZeroScrap()
+0C16 PutScrap(Count/4,Type,@Src)
+0D16 GetScrap(DestH,Type)
+0E16 GetScrapHandle(Type):ScrapH
+0F16 GetScrapSize(Type):Size/4
+1016 GetScrapPath():@Pathname
+1116 SetScrapPath(@Pathname)
+1216 GetScrapCount():Count
+1316 GetScrapState():State
+1416 GetIndScrap(Index,@buffer)
+1516 ShowClipboard(flags,@rect):@Wind
+0017 === standard file ===
+0117 SFBootInit()
+0217 SFStartUp(MemID,DirPg)
+0317 SFShutDown()
+0417 SFVersion():Vers
+0517 SFReset()
+0617 SFStatus():ActFlg
+0917 SFGetFile(X,Y,@Prmpt,@FPrc,@tL,@Reply)
+0A17 SFPutFile(X,Y,@Prompt,@DfltName,mxL,@Reply)
+0B17 SFPGetFile(X,Y,@P,@FPrc,@tL,@dTmp,@dHk,@Rp)
+0C17 SFPPutFile(X,Y,@P,@Df,mxL,@dTmpl,@dHk,@Rply)
+0D17 SFAllCaps(Flag)
+0E17 SFGetFile2(X,Y,prDesc,prRef/4,@fProc,@tList,@rep)
+0F17 SFPutFile2(X,Y,prDesc,prRef/4,nmDesc,nmRef/4,@rep)
+1017 SFPGetFile2(X,Y,@draw,prD,prRf/4,@fP,@tL,@d,@hk,@rep)
+1117 SFPPutFile2(X,Y,@draw,prD,prRf/4,nmD,nmRf/4,@d,@hk,@rep)
+1217 SFShowInvisible(InvisState):OldState
+1317 SFReScan(@filterProc,@typeList)
+1417 SFMultiGet2(X,Y,prDesc,prRef/4,@fP,@tL,@rep)
+1517 SFPMultiGet2(X,Y,@draw,prD,prRf/4,@fP,@tL,@d,@hk,@rep)
+0019 === note synthesizer ===
+0119 NSBootInit()
+0219 NSStartUp(Rate,@UpdProc)
+0319 NSShutDown()
+0419 NSVersion():Vers
+0519 NSReset()
+0619 NSStatus():ActFlg
+0919 AllocGen(Priority):Gen#
+0A19 DeallocGen(Gen#)
+0B19 NoteOn(Gen#,Semitone,Vol,@Instr)
+0C19 NoteOff(Gen#,Semitone)
+0D19 AllNotesOff()
+0E19 NSSetUpdateRate(NewRate):OldRate
+0F19 NSSetUserUpdateRtn(@New):@Old
+001A === note sequencer ===
+011A SeqBootInit()
+021A SeqStartUp(DirPg,Mode,Rate,Incr)
+031A SeqShutDown()
+041A SeqVersion():Vers
+051A SeqReset()
+061A SeqStatus():ActFlg
+091A SetIncr(Increment)
+0A1A ClearIncr():OldIncr
+0B1A GetTimer():Tick
+0C1A GetLoc():Phrase,Patt,Level
+0D1A SeqAllNotesOff()
+0E1A SetTrkInfo(Priority,InstIndex,TrkNum)
+0F1A StartSeq(@ErrRtn,@CompRtn,SeqH)
+101A StepSeq()
+111A StopSeq(NextFlag)
+121A SetInstTable(TableH)
+131A StartInts()
+141A StopInts()
+151A StartSeqRel(@errHndlr,@CompRtn,SeqH)
+001B === font manager ===
+011B FMBootInit()
+021B FMStartUp(MemID,DirPg)
+031B FMShutDown()
+041B FMVersion():Vers
+051B FMReset()
+061B FMStatus():ActFlg
+091B CountFamilies(FamSpecs):Count
+0A1B FindFamily(Specs,Pos,@Name):FamNum
+0B1B GetFamInfo(FamNum,@Name):FamStats
+0C1B GetFamNum(@Name):FamNum
+0D1B AddFamily(FamNum,@Name)
+0E1B InstallFont(ID/4,Scale)
+0F1B SetPurgeStat(FontID/4,PrgStat)
+101B CountFonts(ID/4,Specs):N
+111B FindFontStats(ID/4,Specs,Pos,@FStatRec)
+121B LoadFont(ID/4,Specs,Pos,@FStatRec)
+131B LoadSysFont()
+141B AddFontVar(FontH,NewSpecs)
+151B FixFontMenu(MenuID,StartID,FamSpecs)
+161B ChooseFont(CurrID/4,Famspecs):NewID/4
+171B ItemID2FamNum(ItemID):FamNum
+181B FMSetSysFont(FontID/4)
+191B FMGetSysFID():SysID/4
+1A1B FMGetCurFID():CurID/4
+1B1B FamNum2ItemID(FamNum):ItemID
+1C1B InstallWithStats(ID/4,Scale,@ResultRec)
+001C === List Manager ===
+011C ListBootInit()
+021C ListStartUp()
+031C ListShutDown()
+041C ListVersion():Vers
+051C ListReset()
+061C ListStatus():ActFlg
+091C CreateList(@Wind,@ListRec):CtrlH
+0A1C SortList(@CompareProc,@ListRec)
+0B1C NextMember(@Member,@ListRec):@NxtMemVal
+0C1C DrawMember(@Member,@ListRec)
+0D1C SelectMember(@Member,@ListRec)
+0E1C GetListDefProc():@Proc
+0F1C ResetMember(@ListRec):NxtMemVal/4
+101C NewList(@Member,@ListRec)
+111C DrawMember2(itemNum,CtrlH)
+121C NextMember2(itemNum,CtrlH):itemNum
+131C ResetMember2(CtrlH):itemNum
+141C SelectMember2(itemNum,CtrlH)
+151C SortList2(@CompareProc,CtrlH)
+161C NewList2(@draw,start,ref/4,refKind,size,CtrlH)
+171C ListKey(flags,@EventRec,CtrlH)
+181C CompareStrings(flags,@String1,@String2):Order
+001D === Audio Compression/Expansion ===
+011D ACEBootInit()
+021D ACEStartUp(DirPg)
+031D ACEShutDown()
+041D ACEVersion():Vers
+051D ACEReset()
+061D ACEStatus():ActFlg
+071D ACEInfo(Code):Value/4
+091D ACECompress(SrcH,SrcOff/4,DestH,DestOff/4,Blks,Method)
+0A1D ACEExpand(SrcH,SrcOff/4,DestH,DestOff/4,Blks,Method)
+0B1D ACECompBegin()
+0C1D ACEExpBegin()
+0D1D GetACEExpState(@Buffer)
+0E1D SetACEExpState(@Buffer)
+001E === Resource Manager ===
+011E ResourceBootInit()
+021E ResourceStartUp(MemID)
+031E ResourceShutDown()
+041E ResourceVersion():Vers
+051E ResourceReset()
+061E ResourceStatus():ActFlag
+091E CreateResourceFile(aux/4,fType,Access,@n)
+0A1E OpenResourceFile(reqAcc,@mapAddr,@n):fileID
+0B1E CloseResourceFile(fileID)
+0C1E AddResource(H,Attr,rType,rID/4)
+0D1E UpdateResourcefile(fileID)
+0E1E LoadResource(rType,rID/4):H
+0F1E RemoveResource(rType,rID/4)
+101E MarkResourceChange(changeFlag,rType,rID/4)
+111E SetCurResourceFile(fileID)
+121E GetCurResourceFile():fileID
+131E SetCurResourceApp(MemID)
+141E GetCurResourceApp():MemID
+151E HomeResourceFile(rType,rID/4):fileID
+161E WriteResource(rType,rID/4)
+171E ReleaseResource(PurgeLevel,rType,rID/4)
+181E DetachResource(rType,rID/4)
+191E UniqueResourceID(IDrange,rType):rID/4
+1A1E SetResourceID(newID/4,rType,oldID/4)
+1B1E GetResourceAttr(rType,rID/4):Attr
+1C1E SetResourceAttr(rAttr,rType,rID/4)
+1D1E GetResourceSize(rType,rID/4):Size/4
+1E1E MatchResourceHandle(@buffer,H)
+1F1E GetOpenFileRefNum(fileID):RefNum
+201E CountTypes():Num
+211E GetIndType(tIndex):rType
+221E CountResources(rType):Num/4
+231E GetIndResource(rType,rIndex/4):rID/4
+241E SetResourceLoad(Flag):oldFlag
+251E SetResourceFileDepth(Depth):oldDepth
+261E GetMapHandle(fileID):MapH
+271E LoadAbsResource(@loc,MaxSize/4,rType,rID/4):Size/4
+281E ResourceConverter(@proc,rType,logFlags)
+291E LoadResource2(flag,@AttrBuff,rType,rID/4):H
+2A1E RMFindNamedResource(rType,@name,@fileID):rID/4
+2B1E RMGetResourceName(rType,rID/4,@nameBuffer)
+2C1E RMLoadNamedResource(rType,@name):H
+2D1E RMSetResourceName(rType,rID/4,@name)
+2E1E OpenResourceFileByID(reqAcc,userID):oldResApp
+2F1E CompactResourceFile(flags,fileID)
+0020 === MIDI ===
+0120 MidiBootInit()
+0220 MidiStartUp(MemID,DirPg)
+0320 MidiShutDown()
+0420 MidiVersion():Vers
+0520 MidiReset()
+0620 MidiStatus():ActFlg
+0920 MidiControl(Function,Argument/4)
+0A20 MidiDevice(Function,@DriverInfo)
+0B20 MidiClock(Function,Argument/4)
+0C20 MidiInfo(Function):Info/4
+0D20 MidiReadPacket(@buff,size):Count
+0E20 MidiWritePacket(@buff):Count
+0021 === Video Overlay ===
+0121 VDBootInit()
+0221 VDStartUp()
+0321 VDShutDown()
+0421 VDVersion():Vers
+0521 VDReset()
+0621 VDStatus():ActFlg
+0921 VDInStatus(Selector):Status
+0A21 VDInSetStd(InStandard)
+0B21 VDInGetStd():InStandard
+0C21 VDInConvAdj(Selector,AdjFunction)
+0D21 VDKeyControl(Selector,KeyerCtrlVal)
+0E21 VDKeyStatus(Selector):KeyerStatus
+0F21 VDKeySetKCol(Red,Green,Blue)
+1021 VDKeyGetKRCol():RedValue
+1121 VDKeyGetKGCol():GreenValue
+1221 VDKeyGetKBCol():BlueValue
+1321 VDKeySetKDiss(KDissolve)
+1421 VDKeyGetKDiss():KDissolve
+1521 VDKeySetNKDiss(NKDissolve)
+1621 VDKeyGetNKDiss():NKDissolve
+1721 VDOutSetStd(OutStandard)
+1821 VDOutGetStd():OutStandard
+1921 VDOutControl(Selector,Value)
+1A21 VDOutStatus(Selector):OutStatus
+1B21 VDGetFeatures(Feature):Info
+1C21 VDInControl(Selector,Value)
+1D21 VDGGControl(Selector,Value)
+1E21 VDGGStatus(Selector):Value
+0022 === Text Edit ===
+0122 TEBootInit()
+0222 TEStartUp(MemID,DirPg)
+0322 TEShutDown()
+0422 TEVersion():Vers
+0522 TEReset()
+0622 TEStatus():ActFlg
+0922 TENew(@parms):teH
+0A22 TEKill(teH)
+0B22 TESetText(tDesc,tRef/4,Len/4,stDesc,stRef/4,teH)
+0C22 TEGetText(bDesc,bRef/4,bLen/4,stDesc,stRef/4,teH):L/4
+0D22 TEGetTextInfo(@infoRec,parmCount,teH)
+0E22 TEIdle(teH)
+0F22 TEActivate(teH)
+1022 TEDeactivate(teH)
+1122 TEClick(@eventRec,teH)
+1222 TEUpdate(teH)
+1322 TEPaintText(@Port,startLn/4,@R,Flags,teH):NextLn/4
+1422 TEKey(@eventRec,teH)
+1522 [not supported]
+1622 TECut(teH)
+1722 TECopy(teH)
+1822 TEPaste(teH)
+1922 TEClear(teH)
+1A22 TEInsert(tDesc,tRef/4,tLen/4,stDesc,stRef/4,teH)
+1B22 TEReplace(tDesc,tRef/4,tLen/4,stDesc,stRef/4,teH)
+1C22 TEGetSelection(@selStart,@selEnd,teH)
+1D22 TESetSelection(selStart/4,selEnd/4,teH)
+1E22 TEGetSelectionStyle(@stRec,stH,teH):comFlag
+1F22 TEStyleChange(flags,@stRec,teH)
+2022 TEOffsetToPoint(offset/4,@vertPos,@horPos,teH)
+2122 TEPointToOffset(vertPos/4,horPos/4,teH):textOffset/4
+2222 TEGetDefProc():@defProc
+2322 TEGetRuler(rulerDesc,rulerRef/4,teH)
+2422 TESetRuler(rulerDesc,rulerRef/4,teH)
+2522 TEScroll(scrDesc,vertAmt/4,horAmt/4,teH):Offset/4
+2622 TEGetInternalProc():@proc
+2722 TEGetLastError(clearFlag,teH):lastError
+2822 TECompactRecord(teH)
+0023 === MIDI Synth ===
+0123 MSBootInit()
+0223 MSStartUp()
+0323 MSShutDown()
+0423 MSVersion():Vers
+0523 MSReset()
+0623 MSStatus():ActFlg
+0923 SetBasicChannel(Channel)
+0A23 SetMIDIMode(Mode)
+0B23 PlayNote(Channel,NoteNum,KeyVel)
+0C23 StopNote(Channel,NoteNum)
+0D23 KillAllNotes()
+0E23 SetRecTrack(TrackNum)
+0F23 SetPlayTrack(TrackNum,State)
+1023 TrackToChannel(TrackNum,ChannelNum)
+1123 Locate(TimeStamp/4,@SeqBuff):@SeqItem
+1223 SetVelComp(VelocityOffset)
+1323 SetMIDIPort(EnabInput,EnabOutput)
+1423 SetInstrument(@InstRec,InstNum)
+1523 SeqPlayer(@SeqPlayerRec)
+1623 SetTempo(Tempo)
+1723 SetCallBack(@CallBackRec)
+1823 SysExOut(@Msg,Delay,@MonRoutine)
+1923 SetBeat(BeatDuration)
+1A23 MIDIMessage(Dest,nBytes,Message,Byte1,Byte2)
+1B23 LocateEnd(@seqBuffer):@End
+1C23 Merge(@Buffer1,@Buffer2)
+1D23 DeleteTrack(TrackNum,@Seq)
+1E23 SetMetro(Volume,Freq,@Wave)
+1F23 GetMSData():Reserved/4,@DirPage
+2023 ConvertToTime(TkPerBt,BtPerMsr,BeatNum,MsrNum):Ticks/4
+2123 ConvertToMeasure(TkPerBt,BtPerMsr,Ticks/4):Ticks,Beat,Msr
+2223 MSSuspend()
+2323 MSResume()
+2423 SetTuningTable(@Table)
+2523 GetTuningTable(@Buffer)
+2623 SetTrackOut(TrackNum,PathVal)
+2723 InitMIDIDriver(Slot,Internal,UserID,@Driver)
+2823 RemoveMIDIDriver()
+0026 === Media Controller ===
+0126 MCBootInit()
+0226 MCStartUp(MemID)
+0326 MCShutDown()
+0426 MCVersion():Vers
+0526 MCReset()
+0626 MCStatus():ActFlg
+0926 MCGetErrorMsg(mcErrorNo,@PStringBuff)
+0A26 MCLoadDriver(mcChannelNo)
+0B26 MCUnLoadDriver(mcChannelNo)
+0C26 MCTimeToBin(mcTimeValue/4):result/4
+0D26 MCBinToTime(mcBinVal/4):result/4
+0E26 MCGetTrackTitle(mcDiskID/4,mcTrackNo,@PStringBuff)
+0F26 MCSetTrackTitle(mcDiskID/4,TrackNum,@title)
+1026 MCGetProgram(mcDiskID/4,@resultBuff)
+1126 MCSetProgram(mcDiskID/4,@mcProg)
+1226 MCGetDiscTitle(mcDiskID/4,@PStringBuff)
+1326 MCSetDiscTitle(mcDiskID/4,@title)
+1426 MCDStartUp(mcChannelNo,@portName,userID)
+1526 MCDShutDown(mcChannelNo)
+1626 MCGetFeatures(mcChannelNo,mcFeatSel):result/4
+1726 MCPlay(mcChannelNo)
+1826 MCPause(mcChannelNo)
+1926 MCSendRawData(mcChannelNo,@mcNative)
+1A26 MCGetStatus(mcChannelNo,mcStatusSel):result
+1B26 MCControl(mcChannelNo,ctlCommand)
+1C26 MCScan(mcChannelNo,mcDirection)
+1D26 MCGetSpeeds(mcChannelNo,@PStringBuff)
+1E26 MCSpeed(mcChannelNo,mcFPS)
+1F26 MCStopAt(mcChannelNo,mcUnitType,mcStopLoc/4)
+2026 MCJog(mcChannelNo,mcUnitType,mcNJog/4,mcJogRepeat)
+2126 MCSearchTo(mcChannelNo,mcUnitType,searchLoc/4)
+2226 MCSearchDone(mcChannelNo):result
+2326 MCSearchWait(mcChannelNo)
+2426 MCGetPosition(mcChannelNo,mcUnitType):result/4
+2526 MCSetAudio(mcChannelNo,mcAudioCtl)
+2626 MCGetTimes(mcChannelNo,mctimesSel):result/4
+2726 MCGetDiscTOC(mcChannelNo,mcTrackNo):result/4
+2826 MCGetDiscID(mcChannelNo):result/4
+2926 MCGetNoTracks(mcChannelNo):result
+2A26 MCRecord(mcChannelNo)
+2B26 MCStop(mcChannelNo)
+2C26 MCWaitRawData(mcChannelNo,@result,tickWait,termMask)
+2D26 MCGetName(mcChannelNo,@PStringBuff)
+2E26 MCSetVolume(mcChannelNo,mcLeftVol,mcRightVol)
+0036 === Marinetti ===
+0136 TCPIPBootInit()
+0236 TCPIPStartUp()
+0336 TCPIPShutDown()
+0436 TCPIPVersion():Vers
+0536 TCPIPReset()
+0636 TCPIPStatus():ActFlg
+0836 TCPIPLongVersion():rVersion/4
+0936 TCPIPGetConnectStatus():connectedFlag
+0A36 TCPIPGetErrorTable():@errTablePtr
+0B36 TCPIPGetReconnectStatus():reconnectFlag
+0C36 TCPIPReconnect(@displayPtr)
+0D36 TCPIPConvertIPToHex(@cvtRecPtr,@ddippstring)
+0E36 TCPIPConvertIPToASCII(ipaddress/4,@ddpstring,flags):strlen
+0F36 TCPIPGetMyIPAddress():ipaddress/4
+1036 TCPIPGetConnectMethod():method
+1136 TCPIPSetConnectMethod(method)
+1236 TCPIPConnect(@displayPtr)
+1336 TCPIPDisconnect(forceflag,@displayPtr)
+1436 TCPIPGetMTU():mtu
+1536 TCPIPValidateIPCString(@cstringPtr):validFlag
+1636 TCPIPGetConnectData(userid,method):H
+1736 TCPIPSetConnectData(method,H)
+1836 TCPIPGetDisconnectData(userid,method):H
+1936 TCPIPSetDisconnectData(method,H)
+1A36 TCPIPLoadPreferences()
+1B36 TCPIPSavePreferences()
+1C36 TCPIPGetDNS(@DNSRecPtr)
+1D36 TCPIPSetDNS(@DNSRecPtr)
+1E36 TCPIPGetTuningTable(@tunePtr)
+1F36 TCPIPSetTuningTable(@tunePtr)
+2036 TCPIPCancelDNR(@dnrBufferPtr)
+2136 TCPIPDNRNameToIP(@nameptr,@dnrBufferPtr)
+2236 TCPIPPoll()
+2336 TCPIPLogin(userid,destip/4,destport,defaultTOS,defaultTTL):ipid
+2436 TCPIPLogout(ipid)
+2536 TCPIPSendICMP(ipid,@messagePtr,messageLen)
+2636 TCPIPSendUDP(ipid,@udpPtr,udpLen)
+2736 TCPIPGetDatagramCount(ipid,protocol):dgmCount
+2836 TCPIPGetNextDatagram(ipid,protocol,flags):H
+2936 TCPIPGetLoginCount():loginCount
+2A36 TCPIPSendICMPEcho(ipid,seqNum)
+2B36 TCPIPReceiveICMPEcho(ipid):seqNum
+2C36 TCPIPOpenTCP(ipid):tcpError
+2D36 TCPIPWriteTCP(ipid,@dataPtr,dataLength/4,pushFlag,urgentFlag):tcpError
+2E36 TCPIPReadTCP(ipid,buffType,buffData/4,buffLen/4,@rrBuffPtr):tcpError
+2F36 TCPIPCloseTCP(ipid):tcpError
+3036 TCPIPAbortTCP(ipid):tcpError
+3136 TCPIPStatusTCP(ipid,@srBuffPtr):tcpError
+3236 TCPIPGetSourcePort(ipid):sourcePort
+3336 TCPIPGetTOS(ipid):TOS
+3436 TCPIPSetTOS(ipid,TOS)
+3536 TCPIPGetTTL(ipid):TTL
+3636 TCPIPSetTTL(ipid,TTL)
+3736 TCPIPSetSourcePort(ipid,sourcePort)
+3836 TCPIPSetMyIPAddress(ipaddress/4)
+3936 TCPIPGetDP():dp
+3A36 TCPIPGetDebugHex():debugFlag
+3B36 TCPIPDebugHex(debugFlag)
+3C36 TCPIPGetDebugTCP():debugFlag
+3D36 TCPIPDebugTCP(debugFlag)
+3E36 TCPIPGetUserRecord(ipid):userRecEntry/4
+3F36 TCPIPConvertIPCToHex(@cvtRecPtr,@ddipcstring)
+4036 TCPIPSendIPDatagram(@datagramPtr)
+4136 TCPIPConvertIPToClass(ipaddress/4):class
+4236 TCPIPGetConnectMsgFlag():conMsgFlag
+4336 TCPIPSetConnectMsgFlag(conMsgFlag)
+4436 TCPIPGetUsername(@unBuffPtr)
+4536 TCPIPSetUsername(@usernamePtr)
+4636 TCPIPGetPassword(@pwBuffPtr)
+4736 TCPIPSetPassword(@passwordPtr)
+4836 TCPIPValidateIPString(@pstringPtr):validFlag
+4936 TCPIPGetUserStatistic(ipid,statisticNum):statistic/4
+4A36 TCPIPGetLinkVariables():@variablesPtr
+4B36 TCPIPEditLinkConfig(connectHandle/4,disconnectHandle/4)
+4C36 TCPIPGetModuleNames():@moduleListPtr
+4D36 TCPIPRebuildModuleList()
+4E36 TCPIPListenTCP(ipid):tcpError
+4F36 TCPIPAcceptTCP(ipid,reserved):newipid
+5036 TCPIPSetNewDestination(ipid,destip/4,destport)
+5136 TCPIPGetHostName(@hnBuffPtr)
+5236 TCPIPSetHostName(@hostNamePtr)
+5336 TCPIPStatusUDP(ipid,@udpVarsPtr)
+5436 TCPIPGetLinkLayer(@linkInfoBlkPtr)
+5536 TCPIPPtrToPtr(@from,@to,len/4)
+5636 TCPIPPtrToPtrNeg(@fromend,@toend,len/4)
+5736 TCPIPGetAuthMessage(userid):authMsgHandle/4
+5836 TCPIPConvertIPToCASCII(ipaddress/4,@ddcstring,flags):strlen
+5936 TCPIPMangleDomainName(flags,@dnPstringPtr):port
+5A36 TCPIPGetAliveFlag():aliveFlag
+5B36 TCPIPSetAliveFlag(aliveFlag)
+5C36 TCPIPGetAliveMinutes():aliveMinutes
+5D36 TCPIPSetAliveMinutes(aliveMinutes)
+5E36 TCPIPReadLineTCP(ipid,@delimitStrPtr,buffType,buffData/4,buffLen/4,@rrBuffPtr):tcpError
+5F36 TCPIPGetBootConnectFlag():bootConnectFlag
+6036 TCPIPSetBootConnectFlag(bootConnectFlag)
+6136 TCPIPSetUDPDispatch(ipid,dispatchFlag)
+6236 TCPIPGetDestination(ipid,@destRecPtr)
+6336 TCPIPGetUserEventTrigger(triggerNumber,ipid):triggerProcPtr/4
+6436 TCPIPSetUserEventTrigger(triggerNumber,ipid,@triggerProcPtr)
+6536 TCPIPGetSysEventTrigger(triggerNumber):triggerProcPtr/4
+6636 TCPIPSetSysEventTrigger(triggerNumber,@triggerProcPtr)
+6736 TCPIPGetDNRTimeouts(@dnrTimeoutsBuffPtr)
+6836 TCPIPSetDNRTimeouts(@dnrTimeoutsBuffPtr)
+0032 === Male Voice ===
+0132 MaleBootInit()
+0232 MaleStartUp()
+0332 MaleShutDown()
+0432 MaleVersion():Vers
+0532 MaleReset()
+0632 MaleStatus():ActFlg
+0932 MaleSpeak(Vol,Speed,Pitch,@PhonStr)
+0033 === Female Voice ===
+0133 FemaleBootInit()
+0233 FemaleStartUp()
+0333 FemaleShutDown()
+0433 FemaleVersion():Vers
+0533 FemaleReset()
+0633 FemaleStatus():ActFlg
+0933 FemaleSpeak(Vol,Speed,Pitch,@PhonStr)
+0034 === TML Speech Toolkit parser ===
+0134 SpeechBootInit()
+0234 SpeechStartUp(MemID)
+0334 SpeechShutDown()
+0434 SpeechVersion():Vers
+0534 SpeechReset()
+0634 SpeechStatus():ActFlg
+0934 Parse(@EnglStr,@PhonStr,Start)
+0A34 DictInsert(@EnglStr,@PhonStr)
+0B34 DictDelete(@EnglStr)
+0C34 DictDump(@EnglStr,@PhonStr):@Str;
+0D34 SetSayGlobals(Gend,Tone,Pitch,Spd,Vol)
+0E34 DictInit(Flag)
+0F34 Say(@EnglishStr)
+1034 Activate...
+0042 === Finder (error codes only) ===
+00FF === GSBug ===
+04FF DebugVersion():Vers
+06FF DebugStatus():ActFlg
+09FF DebugStr(@PStr)
+0AFF SetMileStone(@PStr)
+0BFF DebugSetHook(@hook)
+0CFF DebugGetInfo(selector):Info/4
+0DFF DebugControl(data/4,extraData/4,operation,type)
+0EFF DebugQuery(data/4,operation,type):Info/4
+* User tools
+0000 === User Tools ===
+0001 === fakeModalDialog (DTS) ===
+0101 fmdBootInit()
+0201 fmdStartUp()
+0301 fmdShutDown()
+0401 fmdVersion():Vers
+0501 fmdReset()
+0601 fmdStatus():ActFlg
+0901 fakeModalDialog(@Event,@Update,@EvHook,@Beep,Flags):Result/4
+0A01 fmdSetMenuProc(@MenuProc)
+0B01 fmdGetMenuProc():@MenuProc
+0C01 fmdStdDrawProc()
+0D01 fmdEditMenu()
+0E01 fmdFindCursorCtl(@CtrlH,x,y,@Wind):PartCode
+0F01 fmdLESetText(@Wind,leID/4,@PString)
+1001 fmdLEGetText(@Wind,leID/4,@PString)
+1101 fmdWhichRadio(@Wind,RadioID/4):WhichRadio
+1201 fmdIBeamCursor()
+1301 fmdInitIBeam()
+1401 fmdSetIBeam(@Cursor)
+1501 fmdGetIBeamAdr():@Cursor
+1601 fmdGetCtlPart():Part
+1701 fmdGetError():Error
+0002 === PixelMap Tools (DTS) ===
+0102 pmapBootInit()
+0202 pmapStartUp()
+0302 pmapShutDown()
+0402 pmapVersion():Vers
+0502 pmapReset()
+0602 pmapStatus():ActFlg
+0902 pixelMap2Rgn(@srcLoc,bitsPerPix,colorMask):RgnH
+0A02 newPort(@pmapPortInfo):@port
+0B02 killPort(@pmapPortInfo)
+* E1xxxx vectors
+0000 System Tool dispatcher
+0004 System Tool dispatcher, glue entry
+0008 User Tool dispatcher
+000C User Tool dispatcher, glue entry
+0010 Interrupt mgr
+0014 COP mgr
+0018 Abort mgr
+001C System Death mgr
+0020 AppleTalk interrupt
+0024 Serial interrupt
+0028 Scanline interrupt
+002C Sound interrupt
+0030 VertBlank interrupt
+0034 Mouse interrupt
+0038 1/4 sec interrupt
+003C Keyboard interrupt
+0040 ADB Response byte int
+0044 ADB SRQ int
+0048 Desk Acc mgr
+004C FlushBuffer handler
+0050 KbdMicro interrupt
+0054 1 sec interrupt
+0058 External VGC int
+005C other interrupt
+0060 Cursor update
+0064 IncBusy
+0068 DecBusy
+006C Bell vector
+0070 Break vector
+0074 Trace vector
+0078 Step vector
+007C [install ROMdisk]
+0080 ToWriteBram
+0084 ToReadBram
+0088 ToWriteTime
+008C ToReadTime
+0090 ToCtrlPanel
+0094 ToBramSetup
+0098 ToPrintMsg8
+009C ToPrintMsg16
+00A0 Native Ctrl-Y
+00A4 ToAltDispCDA
+00A8 ProDOS 16 [inline parms]
+00AC OS vector
+00B0 GS/OS(@parms,call) [stack parms]
+00B4 OS_P8_Switch
+00B8 OS_Public_Flags
+00BC OS_KIND (byte: 0=P8,1=P16)
+00BD OS_BOOT (byte)
+00BE OS_BUSY (bit 15=busy)
+00C0 MsgPtr
+0180 ToBusyStrip
+0184 ToStrip
+01B2 MidiInputPoll
+0200 Memory Mover
+0204 Set System Speed
+0208 Slot Arbiter
+0220 HyperCard IIgs callback
+0224 WordForRTL
+1004 ATLK: BASIC
+1008 ATLK: Pascal
+100C ATLK: RamGoComp
+1010 ATLK: SoftReset
+1014 ATLK: RamDispatch
+1018 ATLK: RamForbid
+101C ATLK: RamPermit
+1020 ATLK: ProEntry
+1022 ATLK: ProDOS
+1026 ATLK: SerStatus
+102A ATLK: SerWrite
+102E ATLK: SerRead
+103A init file hook
+103E ATLK: PFI Vector
+D600 ATLK: CmdTable
+DA00 ATLK: TickCount
+* E0xxxx vectors
+1E04 QD:StdText
+1E08 QD:StdLine
+1E0C QD:StdRect
+1E10 QD:StdRRect
+1E14 QD:StdOval
+1E18 QD:StdArc
+1E1C QD:StdPoly
+1E20 QD:StdRgn
+1E24 QD:StdPixels
+1E28 QD:StdComment
+1E2C QD:StdTxMeas
+1E30 QD:StdTxBnds
+1E34 QD:StdGetPic
+1E38 QD:StdPutPic
+1E98 QD:ShieldCursor
+1E9C QD:UnShieldCursor
+* softswitches and F8 ROM routines
+B000 Dvx: xgetparm_ch
+B003 Dvx: xgetparm_n
+B006 Dvx: xmess
+B009 Dvx: xprint_ftype
+B00C Dvx: xprint_access
+B00F Dvx: xprdec_2
+B012 Dvx: xprdec_3
+B015 Dvx: xprdec_pad
+B018 Dvx: xprint_path
+B01B Dvx: xbuild_local
+B01E Dvx: xprint_sd
+B021 Dvx: xprint_drvr
+B024 Dvx: xredirect
+B027 Dvx: xpercent
+B02A Dvx: xyesno
+B02D Dvx: xgetln
+B030 Dvx: xbell
+B033 Dvx: xdowncase
+B036 Dvx: xplural
+B039 Dvx: xcheck_wait
+B03C Dvx: xpr_date_ay
+B03F Dvx: xpr_time_ay
+B042 Dvx: xProDOS_err
+B045 Dvx: xProDOS_er
+B048 Dvx: xerr
+B04B Dvx: xprdec_pady
+B04E Dvx: xdir_setup
+B051 Dvx: xdir_finish
+B054 Dvx: xread1dir
+B057 Dvx: xpmgr
+B05A Dvx: xmmgr
+B05D Dvx: xpoll_io
+B060 Dvx: xprint_ver
+B063 Dvx: xpush_level
+B066 Dvx: xfman_open
+B069 Dvx: xfman_read
+B06C Dvx: xrdkey (v1.1+)
+B06F Dvx: xdirty (v1.1+)
+B072 Dvx: xgetnump (v1.1+)
+B075 Dvx: xyesno2 (v1.2+)
+B078 Dvx: xdir_setup2 (v1.23+)
+B07B Dvx: xshell_info (v1.25+)
+C000 r:KBD w:CLR80COL
+C001 w:SET80COL
+C002 w:RDMAINRAM
+C003 w:RDCARDRAM
+C004 w:WRMAINRAM
+C005 w:WRCARDRAM
+C006 w:SETSLOTCXROM
+C007 w:SETINTCXROM
+C008 w:SETSTDZP
+C009 w:SETALTZP
+C00A w:SETINTC3ROM
+C00B w:SETSLOTC3ROM
+C00C w:CLR80VID
+C00D w:SET80VID
+C00E w:CLRALTCHAR
+C00F w:SETALTCHAR
+C010 r:KBDSTRB
+C011 r:RDLCBNK2
+C012 r:RDLCRAM
+C013 r:RDRAMRD
+C014 r:RDRAMWRT
+C015 r:RDCXROM
+C016 r:RDALTZP
+C017 r:RDC3ROM
+C018 r:RD80COL
+C019 r:RDVBLBAR
+C01A r:RDTEXT
+C01B r:RDMIX
+C01C r:RDPAGE2
+C01D r:RDHIRES
+C01E r:ALTCHARSET
+C01F r:RD80VID
+C020 reserved [cassette]
+C021 rw:MONOCOLOR
+C022 rw:TBCOLOR
+C023 rw:VGCINT
+C024 r:MOUSEDATA
+C025 r:KEYMODREG
+C026 rw:DATAREG [key micro]
+C027 rw:KMSTATUS
+C028 rw:ROMBANK [IIc Plus]
+C029 rw:NEWVIDEO
+C02B rw:LANGSEL
+C02C r:CHARROM
+C02D rw:SLTROMSEL
+C02E r:VERTCNT
+C02F r:HORIZCNT
+C030 rw:SPKR
+C031 rw:DISKREG
+C032 w:SCANINT
+C033 rw:CLOCKDATA
+C034 rw:CLOCKCTL [+border color]
+C035 rw:SHADOW
+C036 rw:CYAREG
+C037 rw:DMAREG
+C038 rw:SCCBREG
+C039 rw:SCCAREG
+C03A rw:SCCBDATA
+C03B rw:SCCADATA
+C03C rw:SOUNDCTL
+C03D rw:SOUNDDATA
+C03E rw:SOUNDADRL
+C03F rw:SOUNDADRH
+C040 reserved [C040 Strobe]
+C041 *rw:INTEN
+C044 *r:MMDELTAX
+C045 *r:MMDELTAY
+C046 w:DIAGTYPE r:INTFLAG
+C047 w:CLRVBLINT
+C048 w:CLRXYINT
+C050 rw:TXTCLR
+C051 rw:TXTSET
+C052 rw:MIXCLR
+C053 rw:MIXSET
+C054 rw:TXTPAGE1
+C055 rw:TXTPAGE2
+C056 rw:LORES
+C057 rw:HIRES
+C058 rw:SETAN0
+C059 rw:CLRAN0
+C05A rw:SETAN1
+C05B rw:CLRAN1
+C05C rw:SETAN2
+C05D rw:CLRAN2
+C05E rw:SETAN3
+C05F rw:CLRAN3
+C060 r:BUTN3
+C061 r:BUTN0
+C062 r:BUTN1
+C063 r:BUTN2
+C064 r:PADDL0
+C065 r:PADDL1
+C066 r:PADDL2
+C067 r:PADDL3
+C068 rw:STATEREG
+C06D *TESTREG
+C06E *CLTRM
+C06F *ENTM
+C070 rw:PTRIG
+C081 rw:ROMIN
+C083 rw:LCBANK2
+C08B rw:LCBANK1
+C0E0 IWM:PH0 off
+C0E1 IWM:PH0 on
+C0E2 IWM:PH1 off
+C0E3 IWM:PH1 on
+C0E4 IWM:PH2 off
+C0E5 IWM:PH2 on
+C0E6 IWM:PH3 off
+C0E7 IWM:PH3 on
+C0E8 IWM:motor off
+C0E9 IWM:motor on
+C0EA IWM:drive 1
+C0EB IWM:drive 2
+C0EC IWM:Q6 OFF (Read)
+C0ED IWM:Q6 ON (WP-sense)
+C0EE IWM:Q7 OFF (WP-sense/Read)
+C0EF IWM:Q7 ON (Write)
+C311 ROM:AUXMOVE
+C314 ROM:XFER
+CFFF rw:CLRROM
+F800 F8ROM:PLOT
+F80E F8ROM:PLOT1
+F819 F8ROM:HLINE
+F828 F8ROM:VLINE
+F832 F8ROM:CLRSCR
+F836 F8ROM:CLRTOP
+F847 F8ROM:GBASCALC
+F85F F8ROM:NXTCOL
+F864 F8ROM:SETCOL
+F871 F8ROM:SCRN
+F88C F8ROM:INSDS1.2
+F88E F8ROM:INSDS2
+F890 F8ROM:GET816LEN
+F8D0 F8ROM:INSTDSP
+F940 F8ROM:PRNTYX
+F941 F8ROM:PRNTAX
+F944 F8ROM:PRNTX
+F948 F8ROM:PRBLNK
+F94A F8ROM:PRBL2
+F953 F8ROM:PCADJ
+F962 F8ROM:TEXT2COPY
+FA40 F8ROM:OLDIRQ
+FA4C F8ROM:BREAK
+FA59 F8ROM:OLDBRK
+FA62 F8ROM:RESET
+FAA6 F8ROM:PWRUP
+FABA F8ROM:SLOOP
+FAD7 F8ROM:REGDSP
+FB19 F8ROM:RTBL
+FB1E F8ROM:PREAD
+FB21 F8ROM:PREAD4
+FB2F F8ROM:INIT
+FB39 F8ROM:SETTXT
+FB40 F8ROM:SETGR
+FB4B F8ROM:SETWND
+FB51 F8ROM:SETWND2
+FB5B F8ROM:TABV
+FB60 F8ROM:APPLEII
+FB6F F8ROM:SETPWRC
+FB78 F8ROM:VIDWAIT
+FB88 F8ROM:KBDWAIT
+FBB3 F8ROM:VERSION
+FBBF F8ROM:ZIDBYTE2
+FBC0 F8ROM:ZIDBYTE
+FBC1 F8ROM:BASCALC
+FBDD F8ROM:BELL1
+FBE2 F8ROM:BELL1.2
+FBE4 F8ROM:BELL2
+FBF0 F8ROM:STORADV
+FBF4 F8ROM:ADVANCE
+FBFD F8ROM:VIDOUT
+FC10 F8ROM:BS
+FC1A F8ROM:UP
+FC22 F8ROM:VTAB
+FC24 F8ROM:VTABZ
+FC42 F8ROM:CLREOP
+FC58 F8ROM:HOME
+FC62 F8ROM:CR
+FC66 F8ROM:LF
+FC70 F8ROM:SCROLL
+FC9C F8ROM:CLREOL
+FC9E F8ROM:CLREOLZ
+FCA8 F8ROM:WAIT
+FCB4 F8ROM:NXTA4
+FCBA F8ROM:NXTA1
+FCC9 F8ROM:HEADR
+FD0C F8ROM:RDKEY
+FD10 F8ROM:FD10
+FD18 F8ROM:RDKEY1
+FD1B F8ROM:KEYIN
+FD35 F8ROM:RDCHAR
+FD67 F8ROM:GETLNZ
+FD6A F8ROM:GETLN
+FD6C F8ROM:GETLN0
+FD6F F8ROM:GETLN1
+FD8B F8ROM:CROUT1
+FD8E F8ROM:CROUT
+FD92 F8ROM:PRA1
+FDDA F8ROM:PRBYTE
+FDE3 F8ROM:PRHEX
+FDED F8ROM:COUT
+FDF0 F8ROM:COUT1
+FDF6 F8ROM:COUTZ
+FE1F F8ROM:IDROUTINE
+FE2C F8ROM:MOVE
+FE5E F8ROM:LIST (not on GS)
+FE80 F8ROM:SETINV
+FE84 F8ROM:SETNORM
+FE89 F8ROM:SETKBD
+FE8B F8ROM:INPORT
+FE93 F8ROM:SETVID
+FE95 F8ROM:OUTPORT
+FEB6 F8ROM:GO
+FECD F8ROM:WRITE
+FEFD F8ROM:READ
+FF2D F8ROM:PRERR
+FF3A F8ROM:BELL
+FF3F F8ROM:RESTORE
+FF4A F8ROM:SAVE
+FF58 F8ROM:IORTS
+FF59 F8ROM:OLDRST
+FF65 F8ROM:MON
+FF69 F8ROM:MONZ
+FF6C F8ROM:MONZ2
+FF70 F8ROM:MONZ4
+FF8A F8ROM:DIG
+FFA7 F8ROM:GETNUM
+FFAD F8ROM:NXTCHR
+FFBE F8ROM:TOSUB
+FFC7 F8ROM:ZMODE
+* 01xxxx vectors
+FC00 SysSrv: DEV_DISPATCHER
+FC04 SysSrv: CACHE_FIND_BLK
+FC08 SysSrv: CACHE_ADD_BLK
+FC14 SysSrv: CACHE_DEL_BLK
+FC1C SysSrv: ALLOC_SEG
+FC20 SysSrv: RELEASE_SEG
+FC34 SysSrv: SWAP_OUT
+FC38 SysSrv: DEREF
+FC50 SysSrv: SET_SYS_SPEED
+FC68 SysSrv: LOCK_MEM
+FC6C SysSrv: UNLOCK_MEM
+FC70 SysSrv: MOVE_INFO
+FC88 SysSrv: SIGNAL
+FC90 SysSrv: SET_DISK_SW
+FCA4 SysSrv: SUP_DRVR_DISP
+FCA8 SysSrv: INSTALL_DRIVER
+FCBC SysSrv: DYN_SLOT_ARBITER
+FCD8 SysSrv: UNBIND_INT_VEC
+* Nifty List service calls
+0000 NLServ: nlRecover
+0001 NLServ: nlEnter
+0002 NLServ: nlRemoveNL
+0003 NLServ: nlGetInfo
+0004 NLServ: nlInstallHook
+0005 NLServ: nlRemoveHook
+0006 NLServ: nlGetDirectory():@dir
+0007 NLServ: nlNewSession(@callback):sessRef
+0008 NLServ: nlKillSession(sessRef)
+0009 NLServ: nlSetSession(sessRef):oldRef
+000A NLServ: nlWelcome
+0010 NLServ: nlGetFirstHandle
+0011 NLServ: nlGetHandleInfo
+0012 NLServ: nlLookup
+0013 NLServ: nlIndLookup
+0014 NLServ: nlGetProcName(@proc):@pString
+0020 NLServ: nlScanHandles
+0021 NLServ: nlDisasm1
+0022 NLServ: nlExecCmdLine
+0023 NLServ: nlGetRange
+0024 NLServ: nlGetAGlobal(ref):value
+0025 NLServ: nlSetAGlobal(@(ref,value))
+0026 NLServ: nlAbortToCmd
+0030 NLServ: nlWriteChar
+0031 NLServ: nlShowChar
+0032 NLServ: nlWriteStr
+0033 NLServ: nlShowStr
+0034 NLServ: nlWriteCStr
+0035 NLServ: nlShowCStr
+0036 NLServ: nlWriteText
+0037 NLServ: nlShowText
+0038 NLServ: nlWriteByte
+0039 NLServ: nlWriteWord
+003A NLServ: nlWritePtr
+003B NLServ: nlWriteLong
+003C NLServ: nlGetLn
+003D NLServ: nlGetChar
+003E NLServ: nlCheckKey
+003F NLServ: nlCrout
+0040 NLServ: nlSpout
+0041 NLServ: nlPause
+0042 NLServ: nlHandleInfo
+0043 NLServ: nlWriteNoVoice(@cStr)
+0044 NLServ: nlShowWString(@wStr)
+0050 NLServ: nlChrGet
+0051 NLServ: nlChrGot
+0052 NLServ: nlEatBlanks()
+0054 NLServ: nlEvalExpr(@exprBuff):exprLen
+0060 NLServ: nlGetByte(@addr):byte
+0061 NLServ: nlGetWord(@addr):word
+0062 NLServ: nlGetLong(@addr):long
+* resource type names
+8001 rIcon
+8002 rPicture
+8003 rControlList
+8004 rControlTemplate
+8005 rC1InputString
+8006 rPString
+8007 rStringList
+8008 rMenuBar
+8009 rMenu
+800A rMenuItem
+800B rTextForLETextBox2
+800C rCtlDefProc
+800D rCtlColorTbl
+800E rWindParam1
+800F rWindParam2
+8010 rWindColor
+8011 rTextBlock
+8012 rStyleBlock
+8013 rToolStartup
+8014 rResName
+8015 rAlertString
+8016 rText
+8017 rCodeResource
+8018 rCDEVCode
+8019 rCDEVFlags
+801A rTwoRects
+801B rFileType
+801C rListRef
+801D rCString
+801E rXCMD
+801F rXFCN
+8020 rErrorString
+8021 rKTransTable
+8022 rWString
+8023 rC1OutputString
+8024 rSoundSample
+8025 rTERuler
+8026 rFSequence
+8027 rCursor
+8028 rItemStruct
+8029 rVersion
+802A rComment
+802B rBundle
+802C rFinderPath
+802D rPaletteWindow
+802E rTaggedStrings
+802F rPatternList
+C001 rRectList
+C002 rPrintRecord
+C003 rFont
+* Error codes
+0001 OS:bad call number / dispatcher:toolset not found
+0002 function not found
+0004 OS:bad parameter count
+0007 GS/OS is busy
+0010 GS/OS:device not found
+0011 GS/OS:bad device number
+0020 GS/OS:invalid driver request
+0021 GS/OS:invalid driver control or status code
+0022 GS/OS:bad call parameter
+0023 GS/OS:character device not open
+0024 GS/OS:character device already open
+0025 OS:interrupt table full
+0026 GS/OS:resources not available
+0027 OS:I/O error
+0028 OS:no device connected
+0029 GS/OS:driver is busy
+002B OS:disk write protected
+002C GS/OS:invalid byte count
+002D GS/OS:invalid block address
+002E OS:disk switched
+002F OS:no disk
+0040 OS:bad pathname
+0042 OS:max number of files already open
+0043 OS:bad file reference number
+0044 OS:directory not found
+0045 OS:volume not found
+0046 OS:file not found
+0047 OS:duplicate filename
+0048 OS:volume full
+0049 OS:volume directory full
+004A OS:incompatible file format
+004B OS:unsupported storage type
+004C OS:end of file encountered
+004D OS:position out of range
+004E OS:access not allowed
+004F GS/OS:buffer too small
+0050 OS:file is open
+0051 OS:directory damaged
+0052 OS:unknown volume type
+0053 OS:parameter out of range
+0054 GS/OS:out of memory
+0055 P8:volume control block table full
+0056 P8:bad buffer address
+0057 OS:duplicate volume name
+0058 GS/OS:not a block device
+0059 GS/OS:file level out of range
+005A OS:bad bitmap address (block # too large)
+005B GS/OS:invalid pathnames for ChangePath
+005C GS/OS:not an executable file
+005D GS/OS:Operating System not supported
+005F GS/OS:too many applications on stack
+0060 GS/OS:data unavailable
+0061 GS/OS:end of directory
+0062 GS/OS:invalid FST call class
+0063 GS/OS:file doesn't have a resource fork
+0064 GS/OS:invalidFSTID
+0065 GS/OS:invalid FST operation
+0066 GS/OS:fstCaution
+0067 GS/OS:devNameErr
+0068 GS/OS:devListFull
+0069 GS/OS:supListFull
+006A GS/OS:fstError (generic)
+0070 GS/OS:resExistsErr
+0071 GS/OS:resAddErr
+0088 network error
+0110 toolVersionErr
+0111 messNotFoundErr
+0112 messageOvfl
+0113 srqNameTooLong
+0120 reqNotAccepted
+0121 duplicateName
+0122 invalidSendRequest
+0201 memErr (couldn't allocate memory)
+0202 emptyErr
+0203 notEmptyErr
+0204 lockErr
+0205 purgeErr
+0206 handleErr
+0207 idErr
+0208 attrErr
+0301 badInputErr
+0302 noDevParamErr
+0303 taskInstlErr
+0304 noSigTaskErr
+0305 queueDmgdErr
+0306 taskNtFdErr
+0307 firmTaskErr
+0308 hbQueueBadErr
+0309 unCnctdDevErr
+030B idTagNtAvlErr
+034F mtBuffTooSmall
+0381 invalidTag
+0382 alreadyInQueue
+0390 badTimeVerb
+0391 badTimeData
+0401 alreadyInitialized
+0402 cannotReset
+0403 notInitialized
+0410 screenReserved
+0411 badRect
+0420 notEqualChunkiness
+0430 rgnAlreadyOpen
+0431 rgnNotOpen
+0432 rgnScanOverflow
+0433 rgnFull
+0440 polyAlreadyOpen
+0441 polyNotOpen
+0442 polyTooBig
+0450 badTableNum
+0451 badColorNum
+0452 badScanLine
+0510 daNotFound
+0511 notSysWindow
+0520 deskBadSelector
+0601 emDupStrtUpErr
+0602 emResetErr
+0603 emNotActErr
+0604 emBadEvtCodeErr
+0605 emBadBttnNoErr
+0606 emQSiz2LrgErr
+0607 emNoMemQueueErr
+0681 emBadEvtQErr
+0682 emBadQHndlErr
+0810 noDOCFndErr
+0811 docAddrRngErr
+0812 noSAppInitErr
+0813 invalGenNumErr
+0814 synthModeErr
+0815 genBusyErr
+0817 mstrIRQNotAssgnErr
+0818 sndAlreadyStrtErr
+08FF uncleamedSntIntErr
+0910 cmndIncomplete
+0911 cantSync
+0982 adbBusy
+0983 devNotAtAddr
+0984 srqListFull
+0B01 imBadInptParam
+0B02 imIllegalChar
+0B03 imOverflow
+0B04 imStrOverflow
+0C01 badDevType
+0C02 badDevNum
+0C03 badMode
+0C04 unDefHW
+0C05 lostDev
+0C06 lostFile
+0C07 badTitle
+0C08 noRoom
+0C09 noDevice
+0C0B dupFile
+0C0C notClosed
+0C0D notOpen
+0C0E badFormat
+0C0F ringBuffOFlo
+0C10 writeProtected
+0C40 devErr
+0E01 paramLenErr
+0E02 allocateErr
+0E03 taskMaskErr
+0E04 compileTooLarge
+0E05 cantUpdateErr
+0F01 menuStarted
+0F02 menuItemNotFound
+0F03 menuNoStruct
+0F04 dupMenuID
+1001 wmNotStartedUp
+1002 cmNotInitialized
+1003 noCtlInList
+1004 noCtlError
+1005 notExtendedCtlError
+1006 noCtlTargetError
+1007 notExtendedCtlError
+1008 canNotBeTargetError
+1009 noSuchIDError
+100A tooFewParmsError
+100B noCtlToBeTargetError
+100C noFrontWindowError
+1101 idNotFound / segment not found?
+1102 OMF version error
+1103 idPathnameErr
+1104 idNotLoadFile
+1105 idBusyErr
+1107 idFilVersErr
+1108 idUserIDErr
+1109 idSequenceErr
+110A idBadRecordErr
+110B idForeignSegErr
+1210 picEmpty
+1211 picAlreadyOpen / badRectSize?
+1212 pictureError / destModeError?
+121F bad picture opcode
+1221 badRect
+1222 badMode
+1230 badGetSysIconInput
+1301 missingDriver
+1302 portNotOn
+1303 noPrintRecord
+1304 badLaserPrep
+1305 badLPFile
+1306 papConnNotOpen
+1307 papReadWriteErr
+1308 ptrConnFailed
+1309 badLoadParam
+130A callNotSupported
+1321 startUpAlreadyMade
+1401 leDupStartUpErr
+1402 leResetErr
+1403 leNotActiveErr
+1404 leScrapErr
+150A badItemType
+150B newItemFailed
+150C itemNotFound
+150D notModalDialog
+1610 badScrapType
+1701 badPromptDesc
+1702 badOrigNameDesc
+1704 badReplyNameDesc
+1705 badReplyPathDesc
+1706 badCall
+17FF sfNotStarted
+1901 nsAlreadyInit
+1902 nsSndNotInit
+1921 nsNotAvail
+1922 nsBadGenNum
+1923 nsNotInit
+1924 nsGenAlreadyOn
+1925 soundWrongVer
+1A00 noRoomMidiErr
+1A01 noCommandErr
+1A02 noRoomErr
+1A03 startedErr
+1A04 noNoteErr
+1A05 noStartErr
+1A06 instBndsErr
+1A07 nsWrongVer
+1B01 fmDupStartUpErr
+1B02 fmResetErr
+1B03 fmNotActiveErr
+1B04 fmFamNotFndErr
+1B05 fmFontNtFndErr
+1B06 fmFontMemErr
+1B07 fmSysFontErr
+1B08 fmBadFamNumErr
+1B09 fmBadSizeErr
+1B0A fmBadNameErr
+1B0B fmMenuErr
+1B0C fmScaleSizeErr
+1B0D fmBadParmErr
+1C02 listRejectEvent
+1D01 aceIsActive
+1D02 aceBadDP
+1D03 aceNotActive
+1D04 aceNoSuchParam
+1D05 aceBadMethod
+1D06 aceBadSrc
+1D07 aceBadDest
+1D08 aceDataOverlap
+1E01 resForkUsed
+1E02 resBadFormat
+1E03 resNoConverter
+1E04 resNoCurFile
+1E05 resDupID
+1E06 resNotFound
+1E07 resFileNotFound
+1E08 resBadAppID
+1E09 resNoUniqueID
+1E0A resIndexRange
+1E0B resSysIsOpen
+1E0C resHasChanged
+1E0D resDiffConverter
+1E0E resDiskFull
+1E0F resInvalidShutDown
+1E10 resNameNotFound
+1E11 resBadNameVers
+1E12 resDupStartUp
+1E13 resInvalidTypeOrID
+2000 miStartUpErr
+2001 miPacketErr
+2002 miArrayErr
+2003 miFullbufErr
+2004 miToolsErr
+2005 miOutOffErr
+2007 miNoBufErr
+2008 miDriverErr
+2009 miBadFreqErr
+200A miClockErr
+200B miConflictErr
+200C miNoDevErr
+2080 miDevNotAvail
+2081 miDevSlotBusy
+2082 miDevBusy
+2083 miDevOverrun
+2084 miDevNoConnect
+2085 miDevReadErr
+2086 miDevVersion
+2087 miDevIntHndlr
+2110 vdNoVideoDevice
+2111 vdAlreadyStarted
+2112 vdInvalidSelector
+2113 vdInvalidParam
+21FF vdUnImplemented
+2201 teAlreadyStarted
+2202 teNotStarted
+2203 teInvalidHandle
+2204 teInvalidDescriptor
+2205 teInvalidFlag
+2206 teInvalidPCount
+2208 teBufferOverflow
+2209 teInvalidLine
+220B teInvalidParameter
+220C teInvalidTextBox2
+220D teNeedsTools
+2301 msAlreadyStarted
+2302 msNotStarted
+2303 msNoDPMem
+2304 msNoMemBlock
+2305 msNoMiscTool
+2306 msNoSoundTool
+2307 msGenInUse
+2308 msBadPortNum
+2309 msPortBusy
+230A msParamRangeErr
+230B msMsgQueueFull
+230C msRecBufFull
+230D msOutputDisabled
+230E msMessageError
+230F msOutputBufFull
+2310 msDriverNotStarted
+2311 msDriverAlreadySet
+2380 msDevNotAvail
+2381 msDevSlotBusy
+2382 msDevBusy
+2383 msDevOverrun
+2384 msDevNoConnect
+2385 msDevReadErr
+2386 msDevVersion
+2387 msDevIntHndlr
+2601 mcUnimp
+2602 mcBadSpeed
+2603 mcBadUnitType
+2604 mcTimeOutErr
+2605 mcNotLoaded
+2606 mcBadAudio
+2607 mcDevRtnError
+2608 mcUnrecStatus
+2609 mcBadSelector
+260A mcFunnyData
+260B mcInvalidPort
+260C mcOnlyOnce
+260D mcNoResMgr
+260E mcItemNotThere
+260F mcWasShutDown
+2610 mcWasStarted
+2611 mcBadChannel
+2612 mcInvalidParam
+2613 mcCallNotSupported
+3601 terrBADIPID
+3602 terrNOCONNECTION
+3603 terrNORECONDATA
+3604 terrLINKERROR
+3605 terrSCRIPTFAILED
+3606 terrCONNECTED
+3607 terrSOCKETOPEN
+3608 terrINITNOTFOUND
+3609 terrVERSIONMISMATCH
+360A terrBADTUNETABLELEN
+360B terrIPIDTABLEFULL
+360C terrNOICMPQUEUED
+360D terrLOGINSPENDING
+360E terrTCPIPNOTACTIVE
+360F terrNODNSERVERS
+3610 terrDNRBUSY
+3611 terrNOLINKLAYER
+3612 terrBADLINKLAYER
+3613 terrENJOYCOKE
+3614 terrNORECONSUPPORT
+3615 terrUSERABORTED
+3616 terrBADUSERPASS
+3617 terrBADPARAMETER
+3618 terrBADENVIRONMENT
+3619 terrNOINCOMING
+361A terrLINKBUSY
+361B terrNOLINKINTERFACE
+361C terrNOLINKRESPONSE
+361D terrNODNRPENDING
+361E terrBADALIVEMINUTES
+361F terrBUFFERTOOSMALL
+3620 terrNOTSERVE
+3621 terrBADTRIGGERNUM
+4201 fErrBadInput
+4202 fErrFailed
+4203 fErrCancel
+4204 fErrDimmed
+4205 fErrBusy
+4206 fErrNotPrudent
+4207 fErrBadBundle
+42FF fErrNotImp
+FF01 debugUnImpErr
+FF02 debugBadSelErr
+FF03 debugDupBreakErr
+FF04 debugBreakNotSetErr
+FF05 debugTableFullErr
+FF06 debugTableEmptyErr
+FF07 debugBreaksInErr
+* HyperCardIIgs callbacks
+0001 HC:SendCardMessage(@Str)
+0002 HC:EvalExpr(@Str):H
+0003 HC:StringLength(@Str):Length/4
+0004 HC:StringMatch(@Pattern,@Target):@Ptr
+0005 HC:SendHCMessage(@Msg)
+0006 HC:ZeroBytes(@Ptr,Count/4)
+0007 HC:PasToZero(@Str):StringH
+0008 HC:ZeroToPas(@ZeroStr,@Str)
+0009 HC:StrToLong(@Str31):Long/4
+000A HC:StrToNum(@Str31):Long/4
+000B HC:StrToBool(@Str31):Boolean
+000C HC:StrToExt(@Str31):@Extended
+000D HC:LongToStr(posNum/4):@Str31
+000E HC:NumToStr(Num/4):@Str31
+000F HC:NumToHex(Num/4,nDigits):@Str31
+0010 HC:BoolToStr(Boolean):@Str31
+0011 HC:ExtToStr(@Extended):@Str31
+0012 HC:GetGlobal(@GlobalName):ValueH
+0013 HC:SetGlobal(@GlobalName,GlobValueH)
+0014 HC:GetFieldByName(cardFieldFlag,@FieldName):H
+0015 HC:GetFieldByNum(cardFieldFlag,fieldNum):H
+0016 HC:GetFieldByID(cardFieldFlag,fieldID):H
+0017 HC:SetFieldByName(cardFieldFlag,@fieldName,ValueH)
+0018 HC:SetFieldByNum(cardFieldFlag,fieldNum,ValueH)
+0019 HC:SetFieldByID(cardFieldFlag,fieldID,ValueH)
+001A HC:StringEqual(@Str1,@Str2):Boolean
+001B HC:ReturnToPas(@ZeroStr,@Str)
+001C HC:ScanToReturn(@PtrToPtr)
+001D HC:ScanToZero(@PtrToPtr)
+001E HC:GSToPString(GStringH):@Str
+001F HC:PToGSString(@Str):GStringH
+0020 HC:CopyGSString(GStringH):GString2H
+0021 HC:GSConcat(GString1H,GString2H):NewGStringH
+0022 HC:GSStringEqual(GString1H,GString2H):Boolean
+0023 HC:GSToZero(GStringH):ZeroH
+0024 HC:ZeroToGS(ZeroH):GStringH
+0025 HC:LoadNamedResource(whichType,@Name):H
+0026 HC:FindNamedResource(Type,@Name,@File,@ID/4):Bool
+0027 HC:SetResourceName(Type,ID/4,@Name)
+0028 HC:GetResourceName(Type,ID/4):@Str
+0029 HC:BeginXSound()
+002A HC:EndXSound()
+002B HC:GetMaskAndData(@MaskLocInfo,@DataLocInfo)
+002C HC:ChangedMaskAndData(whatChanged)
+002D HC:PointToStr(Point/4,@String)
+002E HC:RectToStr(@Rect,@String)
+002F HC:StrToPoint(@String,@Point)
+0030 HC:StrToRect(@String,@Rect)
+0031 HC:NewXWindow(@BoundsR,@Title,visFlg,windStyle):WindowPtr
+0032 HC:SetXWIdleTime(@Window,Interval/4)
+0033 HC:CloseXWindow(@Window)
+0034 HC:HideHCPalettes()
+0035 HC:ShowHCPalettes()
+0036 HC:SetXWindowValue(@Window,Value/4)
+0037 HC:GetXWindowValue(@Window):Value/4
+0038 HC:XWAllowReEntrancy(@Window,SysEvts,HCEvts)
+* Request Codes
+0001 systemSaysBeep
+0002 systemSaysUnknownDisk
+0003 srqGoAway
+0004 srqGetrSoundSample
+0005 srqSynchronize
+0006 srqPlayrSoundSample
+0008 systemSaysNewDeskMsg
+000C systemSaysDoClipboard
+000D systemSaysForceUndim
+000E systemSaysEjectingDev
+0010 srqOpenOrPrint
+0011 srqQuit
+0100 finderSaysHello
+0101 finderSaysGoodbye
+0102 finderSaysSelectionChanged
+0103 finderSaysMItemSelected
+0104 finderSaysBeforeOpen
+0105 finderSaysOpenFailed
+0106 finderSaysBeforeCopy
+0107 finderSaysIdle
+0108 finderSaysExtrasChosen
+0109 finderSaysBeforeRename
+010A finderSaysKeyHit
+0502 systemSaysDeskStartUp
+0503 systemSaysDeskShutDown
+051E systemSaysFixedAppleMenu
+0F01 systemSaysMenuKey
+1201 systemSaysGetSysIcon
+8000 tellFinderGetDebugInfo (or srqMountServer to EasyMount)
+8001 askFinderAreYouThere
+8002 tellFinderOpenWindow
+8003 tellFinderCloseWindow
+8004 tellFinderGetSelectedIcons
+8005 tellFinderSetSelectedIcons
+8006 tellFinderLaunchThis
+8007 tellFinderShutDown
+8008 tellFinderMItemSelected
+800A tellFinderMatchFileToIcon
+800B tellFinderAddBundle
+800C tellFinderAboutChange
+800D tellFinderCheckDatabase
+800E tellFinderColorSelection
+800F tellFinderAddToExtras
+8011 askFinderIdleHowLong
+8012 tellFinderGetWindowIcons
+8013 tellFinderGetWindowInfo
+8014 tellFinderRemoveFromExtras
+8015 tellFinderSpecialPreferences
+8200 srqConvertRelPitch
+9000 cpOpenCDev
+9001 cpOpenControlPanels
+*
diff --git a/src/assets/config.txt b/src/assets/config.txt
new file mode 100644
index 0000000..d62c885
--- /dev/null
+++ b/src/assets/config.txt
@@ -0,0 +1,46 @@
+# GSplus configuration file version 0.15
+
+s5d1 =
+s5d2 =
+
+s6d1 =
+s6d2 =
+
+s7d1 =
+
+g_cfg_rom_path = ../../roms/gsrom3
+
+
+bram1[00] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[10] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[20] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[30] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[40] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[50] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[60] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[70] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[80] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[90] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[a0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[b0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[c0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[d0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[e0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+bram1[f0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+bram3[00] = 00 00 00 01 00 00 0d 06 02 01 01 00 01 00 00 00
+bram3[10] = 00 00 07 06 02 01 01 00 00 00 0f 06 06 00 05 06
+bram3[20] = 01 00 00 00 00 00 00 01 00 00 00 00 05 02 02 00
+bram3[30] = 00 00 2d 2d 00 00 00 00 00 00 02 02 02 06 08 00
+bram3[40] = 01 02 03 04 05 06 07 0a 00 01 02 03 04 05 06 07
+bram3[50] = 08 09 0a 0b 0c 0d 0e 0f 00 00 ff ff ff ff ff ff
+bram3[60] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[70] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[80] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[90] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[a0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[b0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[c0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[d0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[e0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+bram3[f0] = ff ff ff ff ff ff ff ff ff ff ff ff 36 2d 9c 87
diff --git a/assets/control b/src/assets/control.in
similarity index 67%
rename from assets/control
rename to src/assets/control.in
index 6f878f7..bc8a0fb 100644
--- a/assets/control
+++ b/src/assets/control.in
@@ -1,10 +1,9 @@
Package: gsplus
-Version: 0.14-0
+Version: @gsplus_VERSION_MAJOR@.@gsplus_VERSION_MINOR@-0
Section: base
Priority: optional
Architecture: amd64
Depends: libsdl2-2.0-0, libfreetype6, libsdl2-image-2.0-0
Maintainer: Dagen Brock
Description: GSplus
- An Apple IIgs emulator for multiple platforms,
- based on KEGS
+ An Apple IIgs emulator based on KEGS
diff --git a/assets/gsp-icons.icns b/src/assets/gsp-icons.icns
similarity index 100%
rename from assets/gsp-icons.icns
rename to src/assets/gsp-icons.icns
diff --git a/src/atbridge/CMakeLists.txt b/src/atbridge/CMakeLists.txt
new file mode 100644
index 0000000..7bdcac3
--- /dev/null
+++ b/src/atbridge/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_library(atbridge aarp.c atbridge.c elap.c llap.c pcap_delay.c port.c)
+
+target_compile_definitions(atbridge PUBLIC HAVE_ATBRIDGE)
+
+if(WIN32)
+ target_link_libraries(atbridge ws2_32) # winsock2
+endif()
diff --git a/src/atbridge/aarp.c b/src/atbridge/aarp.c
index edbb925..dcb066d 100644
--- a/src/atbridge/aarp.c
+++ b/src/atbridge/aarp.c
@@ -17,7 +17,7 @@
#include "aarp.h"
#ifdef WIN32
-#include
+#include
#elif __linux__
#include
#endif
diff --git a/src/atbridge/atbridge.c b/src/atbridge/atbridge.c
index f908f2c..e2204b9 100644
--- a/src/atbridge/atbridge.c
+++ b/src/atbridge/atbridge.c
@@ -18,7 +18,7 @@
#include "aarp.h"
#ifdef WIN32
-#include
+#include
#elif __linux__
#include
#endif
diff --git a/src/atbridge/elap.c b/src/atbridge/elap.c
index 3774df4..c55c4cc 100644
--- a/src/atbridge/elap.c
+++ b/src/atbridge/elap.c
@@ -16,12 +16,12 @@
#include "elap_defs.h"
#include "pcap_delay.h"
-#ifdef __CYGWIN__
-#include
-#include
-#endif
+// #ifdef __CYGWIN__
+// #include
+// #include
+// #endif
#ifdef WIN32
-#include
+#include
#include
#endif
#ifdef __linux__
diff --git a/src/atbridge/pcap_delay.h b/src/atbridge/pcap_delay.h
index 03e6920..329d234 100644
--- a/src/atbridge/pcap_delay.h
+++ b/src/atbridge/pcap_delay.h
@@ -14,13 +14,7 @@ This wrapper provides a subset of the available PCAP APIs necessary for ATBridge
Feel free to extend the wrapper.
*/
-#ifdef WIN32
-#include "../arch/win32/pcap.h"
-#elif __linux__
#include
-#elif __APPLE__
-#include
-#endif
bool pcapdelay_load();
bool pcapdelay_is_loaded();
diff --git a/src/config.txt b/src/config.txt
deleted file mode 100644
index 29464ec..0000000
--- a/src/config.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-# GSplus configuration file version 0.10a
-
-s5d1 =
-s5d2 =
-
-s6d1 =
-s6d2 =
-
-s7d1 =
-
-
-
-bram1[00] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[10] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[20] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[30] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[40] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[50] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[60] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[70] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[80] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[90] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[a0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[b0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[c0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[d0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[e0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram1[f0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-bram3[00] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[10] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[20] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[30] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[40] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[50] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[60] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[70] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[80] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[90] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[a0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[b0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[c0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[d0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[e0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-bram3[f0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/src/engine_c.c b/src/engine_c.c
index 9372be2..f4110c5 100644
--- a/src/engine_c.c
+++ b/src/engine_c.c
@@ -353,11 +353,8 @@ extern word32 slow_mem_changed[];
}
void check_breakpoints(word32 addr) {
- int count;
int i;
-
- count = g_num_breakpoints;
- for(i = 0; i < count; i++) {
+ for(i = 0; i < g_num_breakpoints; i++) {
if((g_breakpts[i] & 0xffffff) == addr) {
g_dbg_step = -2;
halt2_printf("Hit breakpoint at %06x\n", addr);
diff --git a/src/engine_s.s b/src/engine_s.s
deleted file mode 100644
index 2799a4b..0000000
--- a/src/engine_s.s
+++ /dev/null
@@ -1,2467 +0,0 @@
-/*
- GSPLUS - Advanced Apple IIGS Emulator Environment
- Based on the KEGS emulator written by Kent Dickey
- See COPYRIGHT.txt for Copyright information
- See LICENSE.txt for license (GPL v2)
-*/
-
- .code
-
- .level 1.1
-
-#include "defs.h"
-
-#define ASM
-
-
-/*
-#define COUNT_GET_CALLS
-*/
-
-#if 0
-# define CHECK_SIZE_CONSISTENCY
-#endif
-
-
-#define STACK_ENGINE_SIZE 512
-
-#define STACK_SAVE_CMP_INDEX_REG -64
-#define STACK_GET_MEM_B0_DIRECT_SAVELINK -68
-#define STACK_SAVE_ARG0 -72
-#define STACK_SAVE_INSTR -76
-#define STACK_SRC_BANK -80
-#define STACK_INST_TAB_PTR_DONT_USE_THIS -84
-#if 0
-#define STACK_BP_ARG0_SAVE -88
-#define STACK_BP_ARG1_SAVE -92
-#define STACK_BP_ARG2_SAVE -96
-#define STACK_BP_ARG3_SAVE -100
-#define STACK_BP_RP_SAVE -104
-#define STACK_BP_SCRATCH4_SAVE -108
-#endif
-
-#define STACK_GET_MEMORY_SAVE_LINK -112
-#define STACK_SET_MEMORY_SAVE_LINK -116
-
-#define STACK_MEMORY16_SAVE1 -120
-#define STACK_MEMORY16_SAVE2 -124
-#define STACK_MEMORY16_SAVE3 -128
-
-#define STACK_SAVE_CYCLES_WORD2 -132 /* Cycles = dword */
-#define STACK_SAVE_CYCLES -136
-
-#define STACK_SET_MEMORY24_SAVE1 -140
-#define STACK_SET_MEMORY24_SAVE2 -144
-#define STACK_SET_MEMORY24_SAVE3 -148
-
-#define STACK_GET_MEMORY24_SAVE1 -152
-#define STACK_GET_MEMORY24_SAVE2 -156
-#define STACK_GET_MEMORY24_SAVE3 -160
-
-/* #define STACK_SAVE_INIT_CYCLES -164 */
-#define STACK_SAVE_DECIMAL16_A -168
-#define STACK_SAVE_DECIMAL16_B -172
-#define STACK_SAVE_INSTR_TMP1 -176
-
-#define STACK_SAVE_DISPATCH_LINK -180
-#define STACK_SAVE_OP_LINK -184
-#define STACK_GET_MEMORY16_ADDR_LATCH -188
-#define STACK_GET_MEMORY24_ADDR_LATCH -192
-
-#define STACK_GET_MEM_B0_DIRECT_ARG0 -200
-#define STACK_GET_MEM_B0_DIRECT_RET0 -204
-#define STACK_SAVE_PUSH16_LINK -208
-#define STACK_SAVE_PUSH16_ARG1 -212
-
-#define STACK_SAVE_PULL16_LINK -216
-#define STACK_SAVE_PULL16_RET0 -220
-#define STACK_SAVE_PULL24_LINK -224
-#define STACK_SAVE_PULL24_RET0 -228
-
-#define STACK_SAVE_COP_ARG0 -232
-#define STACK_SAVE_TMP_INST0 -236
-#define STACK_SAVE_TMP_INST -240
-#define STACK_SAVE_TMP_INST1 -244
-#define STACK_SAVE_DISP_PIECES_LINK -248
-#define STACK_SAVE_DISPATCH_SCRATCH1 -252
-
-#if 0
-#define STACK_BP_SCRATCH2_SAVE -256
-#define STACK_BP_SCRATCH3_SAVE -260
-#endif
-
-
-
-#define CYCLES_PLUS_1 fadd,dbl fr_plus_1,fcycles,fcycles
-#define CYCLES_PLUS_2 fadd,dbl fr_plus_2,fcycles,fcycles
-#define CYCLES_PLUS_3 fadd,dbl fr_plus_3,fcycles,fcycles
-#define CYCLES_PLUS_5 fadd,dbl fr_plus_3,fcycles,fcycles ! \
- fadd,dbl fr_plus_2,fcycles,fcycles
-
-#define CYCLES_MINUS_1 fsub,dbl fcycles,fr_plus_1,fcycles
-#define CYCLES_MINUS_2 fsub,dbl fcycles,fr_plus_2,fcycles
-
-#define CYCLES_FINISH fadd,dbl fcycles_stop,fr_plus_1,fcycles
-
-#define FCYCLES_ROUND_1 fadd,dbl fcycles,fr_plus_x_m1,ftmp1
-#define FCYCLES_ROUND_2 fcnvfxt,dbl,dbl ftmp1,ftmp1
-#define FCYCLES_ROUND_3 fcnvxf,dbl,dbl ftmp1,fcycles
-
-/* HACK: INC_KPC* and DEC_KPC2 should avoid overflow into kbank! */
-#define INC_KPC_1 addi 1,kpc,kpc
-#define INC_KPC_2 addi 2,kpc,kpc
-#define INC_KPC_3 addi 3,kpc,kpc
-#define INC_KPC_4 addi 4,kpc,kpc
-#define DEC_KPC2 addi -2,kpc,kpc
-
-#define get_mem_b0_8 get_memory_asm
-#define get_mem_b0_16 get_memory16_asm
-#define get_mem_b0_24 get_memory24_asm
-
-#define get_mem_long_8 get_memory_asm
-#define get_mem_long_16 get_memory16_asm
-#define get_mem_long_24 get_memory24_asm
-
-#define set_mem_long_8 set_memory_asm
-#define set_mem_long_16 set_memory16_asm
-
-#define set_mem_b0_8 set_memory_asm
-#define set_mem_b0_16 set_memory16_asm
-#define set_mem_b0_24 set_memory24_asm
-
- .code
- .import halt_sim,data
- .import g_fcycles_stop,data
- .import g_irq_pending,data
- .import g_wait_pending,data
- .import g_rom_version,data
- .import g_num_brk,data
- .import g_num_cop,data
- .import g_testing,data
-
- .import log_pc,code
- .import toolbox_debug_c,code
-
- .import get_memory_io,code
-
- .import set_memory_io,code
- .import set_memory16_pieces,code
- .import set_memory24_pieces,code
-
-#include "op_routs.h"
-
- .import do_break,code
- .import do_cop,code
- .import page_info_rd_wr,data
- .import get_memory_calls,data
- .import slow_mem_changed,data
- .import g_cur_dcycs,data
- .import g_last_vbl_dcycs,data
- .import g_slow_memory_ptr,data
- .import g_memory_ptr,data
- .import g_dummy_memory1_ptr,data
- .import g_rom_fc_ff_ptr,data
- .import g_rom_cards_ptr,data
-
- .export fixed_memory_ptrs_init,code
-fixed_memory_ptrs_init
- LDC(slow_memory,arg0)
- LDC(g_slow_memory_ptr,arg1)
- stw arg0,(arg1)
-
- LDC(dummy_memory1,arg0)
- LDC(g_dummy_memory1_ptr,arg1)
- stw arg0,(arg1)
-
- LDC(rom_fc_ff,arg0)
- LDC(g_rom_fc_ff_ptr,arg1)
- stw arg0,(arg1)
-
- LDC(rom_cards,arg0)
- LDC(g_rom_cards_ptr,arg1)
- stw arg0,(arg1)
-
- bv 0(link)
- nop
-
- .export get_itimer,code
-get_itimer
- bv 0(link)
- mfctl %cr16,ret0
-
- .export enter_asm,data
-enter_asm
- stwm page_info_ptr,STACK_ENGINE_SIZE(sp)
- stw link,-STACK_ENGINE_SIZE+4(sp)
- ldo -STACK_ENGINE_SIZE+16(sp),scratch2
- stw addr_latch,-STACK_ENGINE_SIZE+8(sp)
- fstds,ma fcycles,8(scratch2)
- fstds,ma fr_plus_1,8(scratch2)
- fcpy,dbl 0,fcycles
- fstds,ma fr_plus_2,8(scratch2)
- fstds,ma fr_plus_3,8(scratch2)
- fcpy,dbl 0,fr_plus_1
- fstds,ma fr_plus_x_m1,8(scratch2)
- fstds,ma fcycles_stop,8(scratch2)
- fcpy,dbl 0,fr_plus_2
- fstds,ma fcycles_last_dcycs,8(scratch2)
- ldil l%g_cur_dcycs,scratch2
-
- ldil l%g_last_vbl_dcycs,scratch3
- fcpy,dbl 0,fr_plus_3
- ldo r%g_cur_dcycs(scratch2),scratch2
- fcpy,dbl 0,fr_plus_x_m1
- ldo r%g_last_vbl_dcycs(scratch3),scratch3
- fldds 0(scratch2),ftmp1
- ldil l%page_info_rd_wr,page_info_ptr
- fldds 0(scratch3),fcycles_last_dcycs
- fcpy,dbl 0,fcycles_stop
- ldo r%page_info_rd_wr(page_info_ptr),page_info_ptr
- bv 0(scratch1)
- fsub,dbl ftmp1,fcycles_last_dcycs,fcycles
-
-
- .export leave_asm,data
-leave_asm
- ldw -STACK_ENGINE_SIZE+4(sp),link
- ldo -STACK_ENGINE_SIZE+16(sp),scratch2
- ldw -STACK_ENGINE_SIZE+8(sp),addr_latch
- fldds,ma 8(scratch2),fcycles
- fldds,ma 8(scratch2),fr_plus_1
- fldds,ma 8(scratch2),fr_plus_2
- fldds,ma 8(scratch2),fr_plus_3
- fldds,ma 8(scratch2),fr_plus_x_m1
- fldds,ma 8(scratch2),fcycles_stop
- fldds,ma 8(scratch2),fcycles_last_dcycs
-
- bv (link)
- ldwm -STACK_ENGINE_SIZE(sp),page_info_ptr
-
-
- .align 8
- .export get_memory_c
-get_memory_c
-; arg0 = addr
-; arg1 = cycles
- bl enter_asm,scratch1
- nop
- bl get_memory_asm,link
- nop
- b leave_asm
- nop
-
- .export get_memory16_c
-get_memory16_c
-; arg0 = addr
-; arg1 = cycles
- bl enter_asm,scratch1
- nop
- bl get_memory16_asm,link
- nop
- b leave_asm
- nop
-
- .export get_memory24_c
-get_memory24_c
-; arg0 = addr
-; arg1 = cycles
- bl enter_asm,scratch1
- nop
- bl get_memory24_asm,link
- nop
- b leave_asm
- nop
-
-#define GET_MEM8(upper16,lower8,ret0) \
- extru arg0,23,16,arg3 ! \
- CYCLES_PLUS_1 ! \
- ldwx,s arg3(page_info_ptr),scratch3 ! \
- copy arg0,addr_latch ! \
- copy scratch3,scratch2 ! \
- dep arg0,31,8,scratch3 ! \
- extru,= scratch2,BANK_IO_BIT,1,0 ! \
- bl,n get_memory_iocheck_stub_asm,link ! \
- ldb (scratch3),ret0
-
- .align 32
-
- .export get_memory_asm
-get_memory_asm
-; arg0 = addr
- extru arg0,23,16,arg3
- copy arg0,addr_latch
-
- ldwx,s arg3(page_info_ptr),scratch2
- CYCLES_PLUS_1
- bb,<,n scratch2,BANK_IO_BIT,get_memory_iocheck_stub_asm
- dep arg0,31,8,scratch2
- bv 0(link)
- ldb (scratch2),ret0
-
-
- .align 8
-
- .export get_memory16_asm
-get_memory16_asm
-; arg0 = addr
- ldi 0xff,scratch3
- extru arg0,23,16,arg3
-
- and scratch3,arg0,scratch4
- ldwx,s arg3(page_info_ptr),scratch2
- copy arg0,addr_latch
- comb,= scratch4,scratch3,get_memory16_pieces_stub_asm
- and scratch2,scratch3,scratch3
- comb,<> 0,scratch3,get_memory16_pieces_stub_asm
- dep arg0,31,8,scratch2
- ldb (scratch2),ret0
- CYCLES_PLUS_2
- ldb 1(scratch2),scratch1
- bv 0(link)
- dep scratch1,23,8,ret0
-
- .align 8
-
- .export get_memory24_asm
-get_memory24_asm
-; arg0 = addr
- ldi 0xfe,scratch3
- extru arg0,23,16,arg3
-
- and scratch3,arg0,scratch4
- ldwx,s arg3(page_info_ptr),scratch2
- copy arg0,addr_latch
- comb,= scratch4,scratch3,get_memory24_pieces_stub_asm
- extru scratch2,31,8,scratch3
- comb,<> 0,scratch3,get_memory24_pieces_stub_asm
- dep arg0,31,8,scratch2
- ldb (scratch2),ret0
- ldb 1(scratch2),scratch1
- CYCLES_PLUS_3
- ldb 2(scratch2),scratch2
- dep scratch1,23,8,ret0
- bv 0(link)
- dep scratch2,15,8,ret0
-
-
- .align 0x20
- .export get_memory_iocheck_stub_asm,code
-get_memory_iocheck_stub_asm
- extru,= scratch2,BANK_BREAK_BIT,1,0
- bl check_breakpoints_asm,scratch4
- stw link,STACK_GET_MEMORY_SAVE_LINK(sp)
- bb,< scratch2,BANK_IO2_BIT,get_memory_io_stub_asm
- dep arg0,31,8,scratch2
- bv 0(link)
- ldb (scratch2),ret0
-
- .export get_memory_io_stub_asm
-get_memory_io_stub_asm
- FCYCLES_ROUND_1
- ldo STACK_SAVE_CYCLES(sp),arg1
- FCYCLES_ROUND_2
- FCYCLES_ROUND_3
- bl get_memory_io,link
- fstds fcycles,(arg1)
-
- ldw STACK_GET_MEMORY_SAVE_LINK(sp),link
- ldo STACK_SAVE_CYCLES(sp),arg1
- bv (link)
- fldds (arg1),fcycles
-
-
-
- .export get_memory16_pieces_stub_asm,code
-get_memory16_pieces_stub_asm
- stw addr_latch,STACK_GET_MEMORY16_ADDR_LATCH(sp)
- addi 1,arg0,scratch1
- stw link,STACK_MEMORY16_SAVE2(sp)
- bl get_memory_asm,link
- stw scratch1,STACK_MEMORY16_SAVE1(sp)
-
- stw ret0,STACK_MEMORY16_SAVE3(sp)
- bl get_memory_asm,link
- ldw STACK_MEMORY16_SAVE1(sp),arg0
-
- ldw STACK_MEMORY16_SAVE2(sp),link
- copy ret0,scratch1
- ldw STACK_MEMORY16_SAVE3(sp),ret0
- ldw STACK_GET_MEMORY16_ADDR_LATCH(sp),addr_latch
- bv (link)
- dep scratch1,23,8,ret0
-
-
- .export get_memory24_pieces_stub_asm,code
-get_memory24_pieces_stub_asm
- stw addr_latch,STACK_GET_MEMORY16_ADDR_LATCH(sp)
- addi 1,arg0,scratch1
- stw link,STACK_GET_MEMORY24_SAVE2(sp)
- bl get_memory_asm,link
- stw scratch1,STACK_GET_MEMORY24_SAVE1(sp)
-
- stw ret0,STACK_GET_MEMORY24_SAVE3(sp)
- bl get_memory_asm,link
- ldw STACK_GET_MEMORY24_SAVE1(sp),arg0
-
- ldw STACK_GET_MEMORY24_SAVE1(sp),arg0
- stb ret0,STACK_GET_MEMORY24_SAVE3+2(sp)
- bl get_memory_asm,link
- addi 1,arg0,arg0
-
- ldw STACK_GET_MEMORY24_SAVE2(sp),link
- copy ret0,scratch1
- ldw STACK_GET_MEMORY24_SAVE3(sp),ret0
- ldw STACK_GET_MEMORY16_ADDR_LATCH(sp),addr_latch
- bv (link)
- dep scratch1,15,8,ret0
-
-
-
-
-; C callable routine to wrap around set_memory_asm
- .export set_memory_c
-set_memory_c
-;arg0 = addr
-;arg1 = val
-;arg2 = cycles
- bl enter_asm,scratch1
- nop
- bl set_memory_asm,link
- nop
- b leave_asm
- nop
-
-
- .export set_memory16_c
-set_memory16_c
-;arg0 = addr
-;arg1 = val
-;arg2 = cycles
- bl enter_asm,scratch1
- nop
- bl set_memory16_asm,link
- nop
- b leave_asm
- nop
-
- .export set_memory24_c
-set_memory24_c
-;arg0 = addr
-;arg1 = val
-;arg2 = cycles
- bl enter_asm,scratch1
- nop
- bl set_memory24_asm,link
- nop
- b leave_asm
- nop
-
-
- .align 32
-
- .export set_memory_asm
-set_memory_asm
-; arg0 = addr
-; arg1 = val
- extru arg0,23,16,arg3
- addil l%PAGE_INFO_WR_OFFSET,arg3
- CYCLES_PLUS_1
- ldwx,s r1(page_info_ptr),scratch2
- ldi 0xff,scratch3
- and scratch2,scratch3,scratch3
- dep arg0,31,8,scratch2
- comib,<>,n 0,scratch3,set_memory_special_case
-set_memory_cont_asm
- bv 0(link)
- stb arg1,(scratch2)
-
-
- .export set_memory_special_case
-set_memory_special_case
- extru,= scratch3,BANK_BREAK_BIT,1,0
- bl check_breakpoints_asm,scratch4
- extru arg1,31,8,arg1
-
-set_memory_special_case2
- bb,< scratch3,BANK_IO2_BIT,set_memory_io_stub_asm
- ldil l%slow_memory,scratch4
- bb,< scratch3,BANK_SHADOW_BIT,set_memory_shadow1_asm
- extru arg0,31,16,arg3
- bb,< scratch3,BANK_SHADOW2_BIT,set_memory_shadow2_asm
- nop
- bb,< scratch3,BANK_BREAK_BIT,set_memory_cont_asm
- nop
- break
-
-
-set_memory_shadow1_asm
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_1
-#endif
- add arg3,scratch4,scratch4
- extru arg3,31-SHIFT_PER_CHANGE,5,scratch1
- ldb r%slow_memory(scratch4),arg2
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_2
-#endif
- mtctl scratch1,cr11
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_3
-#endif
- comclr,<> arg2,arg1,0
- bv 0(link)
- stb arg1,(scratch2)
- zvdepi 1,1,arg2
- extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2
- ldil l%slow_mem_changed,scratch1
- sh2add scratch2,scratch1,scratch1
- ldw r%slow_mem_changed(scratch1),scratch3
- stb arg1,r%slow_memory(scratch4)
- or arg2,scratch3,scratch3
- bv 0(link)
- stw scratch3,r%slow_mem_changed(scratch1)
-
-set_memory_shadow2_asm
- depi 1,15,1,arg3
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_1
-#endif
- add arg3,scratch4,scratch4
- extru arg3,31-SHIFT_PER_CHANGE,5,scratch1
- ldb r%slow_memory(scratch4),arg2
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_2
-#endif
- mtctl scratch1,cr11
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_3
-#endif
- comclr,<> arg2,arg1,0
- bv 0(link)
- stb arg1,(scratch2)
- zvdepi 1,1,arg2
- extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2
- ldil l%slow_mem_changed,scratch1
- sh2add scratch2,scratch1,scratch1
- ldw r%slow_mem_changed(scratch1),scratch3
- stb arg1,r%slow_memory(scratch4)
- or arg2,scratch3,scratch3
- bv 0(link)
- stw scratch3,r%slow_mem_changed(scratch1)
-
-
-set_memory_io_stub_asm
- FCYCLES_ROUND_1
- ldo STACK_SAVE_CYCLES(sp),arg2
- FCYCLES_ROUND_2
- stw link,STACK_SET_MEMORY_SAVE_LINK(sp)
- FCYCLES_ROUND_3
- bl set_memory_io,link
- fstds fcycles,(arg2)
-
- ldw STACK_SET_MEMORY_SAVE_LINK(sp),link
- ldo STACK_SAVE_CYCLES(sp),arg2
- bv (link)
- fldds (arg2),fcycles
-
- .align 8
- .export set_memory16_asm
-set_memory16_asm
-; arg0 = addr
-; arg1 = val
- extru arg0,23,16,arg3
-
- addil l%PAGE_INFO_WR_OFFSET,arg3
- extrs arg0,31,8,scratch4
- ldwx,s r1(page_info_ptr),scratch2
- ldi 0xff,scratch3
- and scratch3,scratch2,scratch3
- dep arg0,31,8,scratch2
- comib,=,n -1,scratch4,set_memory16_pieces_stub_asm
- comib,<>,n 0,scratch3,set_memory16_special_case
-set_memory16_cont_asm
- stb arg1,0(scratch2)
- CYCLES_PLUS_2
- extru arg1,23,8,arg3
- bv 0(link)
- stb arg3,1(scratch2)
-
-
- .align 8
-set_memory16_shadow1_asm
- CYCLES_PLUS_2
- copy arg1,arg2
- extru arg1,23,8,arg1
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_1
-#endif
- add arg3,scratch4,scratch4
- dep arg2,23,8,arg1
- extru arg3,31-SHIFT_PER_CHANGE,5,scratch1
- ldh r%slow_memory(scratch4),arg2
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_2
-#endif
- mtctl scratch1,cr11
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_3
-#endif
- comclr,<> arg2,arg1,0 ;return if arg2 == arg1
- bv 0(link)
- sth arg1,(scratch2)
- zvdepi 1,1,arg2
- extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2
- ldil l%slow_mem_changed,scratch1
- sh2add scratch2,scratch1,scratch1
- ldw r%slow_mem_changed(scratch1),scratch3
- sth arg1,r%slow_memory(scratch4)
- or arg2,scratch3,scratch3
- bv 0(link)
- stw scratch3,r%slow_mem_changed(scratch1)
-
- .align 8
-set_memory16_shadow2_asm
- CYCLES_PLUS_2
- copy arg1,arg2
- extru arg1,23,8,arg1
- depi 1,15,1,arg3
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_1
-#endif
- dep arg2,23,8,arg1
- add arg3,scratch4,scratch4
- extru arg3,31-SHIFT_PER_CHANGE,5,scratch1
- ldh r%slow_memory(scratch4),arg2
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_2
-#endif
- mtctl scratch1,cr11
-#ifdef ACCURATE_SLOW_MEM
- FCYCLES_ROUND_3
-#endif
- comclr,<> arg2,arg1,0
- bv 0(link)
- sth arg1,(scratch2)
- zvdepi 1,1,arg2
- extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2
- ldil l%slow_mem_changed,scratch1
- sh2add scratch2,scratch1,scratch1
- ldw r%slow_mem_changed(scratch1),scratch3
- sth arg1,r%slow_memory(scratch4)
- or arg2,scratch3,scratch3
- bv 0(link)
- stw scratch3,r%slow_mem_changed(scratch1)
-
-
- .align 8
-set_memory16_special_case
- extru,= scratch3,BANK_BREAK_BIT,1,0
- bl check_breakpoints_asm,scratch4
- extru arg1,31,16,arg1
-
-set_memory16_special_case2
- bb,< scratch3,BANK_IO2_BIT,set_memory16_pieces_stub_asm
- ldil l%slow_memory,scratch4
-
-; if not halfword aligned, go through pieces_stub_asm
- bb,<,n arg0,31,set_memory16_pieces_stub_asm
- bb,< scratch3,BANK_SHADOW2_BIT,set_memory16_shadow2_asm
- extru arg0,31,16,arg3
- bb,< scratch3,BANK_SHADOW_BIT,set_memory16_shadow1_asm
- nop
- bb,< scratch3,BANK_BREAK_BIT,set_memory16_cont_asm
- nop
- break
-
- .align 8
-set_memory16_pieces_stub_asm
- addi 1,arg0,scratch1
- stw link,STACK_MEMORY16_SAVE3(sp)
- extru arg1,23,8,scratch2
- stw scratch1,STACK_MEMORY16_SAVE1(sp)
- bl set_memory_asm,link
- stw scratch2,STACK_MEMORY16_SAVE2(sp)
-
- ldw STACK_MEMORY16_SAVE1(sp),arg0
- ldw STACK_MEMORY16_SAVE2(sp),arg1
- b set_memory_asm
- ldw STACK_MEMORY16_SAVE3(sp),link
-
-
- .align 8
- .export set_memory24_asm
-set_memory24_asm
-; arg0 = addr
-; arg1 = val
- extru arg0,23,16,arg3
-
- addil l%PAGE_INFO_WR_OFFSET,arg3
- extrs arg0,30,7,scratch4
- ldwx,s r1(page_info_ptr),scratch2
- ldi 0xff,scratch3
- and scratch3,scratch2,scratch3
- dep arg0,31,8,scratch2
- comib,=,n -1,scratch4,set_memory24_pieces_stub_asm
- comib,<>,n 0,scratch3,set_memory24_pieces_stub_asm
- stb arg1,0(scratch2)
- extru arg1,23,8,arg3
- CYCLES_PLUS_3
- stb arg3,1(scratch2)
- extru arg1,15,8,arg3
- bv 0(link)
- stb arg3,2(scratch2)
-
-set_memory24_pieces_stub_asm
- addi 1,arg0,scratch1
- stw link,STACK_SET_MEMORY24_SAVE3(sp)
- extru arg1,23,16,scratch2
- stw scratch1,STACK_SET_MEMORY24_SAVE1(sp)
- bl set_memory_asm,link
- stw scratch2,STACK_SET_MEMORY24_SAVE2(sp)
-
- ldw STACK_SET_MEMORY24_SAVE1(sp),arg0
- bl set_memory_asm,link
- ldw STACK_SET_MEMORY24_SAVE2(sp),arg1
-
- ldw STACK_SET_MEMORY24_SAVE1(sp),arg0
- ldw STACK_SET_MEMORY24_SAVE3(sp),link
- addi 1,arg0,arg0
- b set_memory_asm
- ldb STACK_SET_MEMORY24_SAVE2+2(sp),arg1
-
-
-
-
-
- .import g_num_breakpoints,data
- .import g_breakpts,data
-
- .align 8
- .export check_breakpoints_asm,code
-check_breakpoints_asm
-; can't use arg0-arg3. don't use scratch2,scratch3
-; scratch4: return link
-;
- ldil l%g_num_breakpoints,scratch1
- ldil l%g_breakpts,ret0
- ldw r%g_num_breakpoints(scratch1),r1
- ldo r%g_breakpts(ret0),ret0
- addi,>= -1,r1,r1
- bv,n 0(scratch4)
- ldwx,s r1(ret0),scratch1
-check_breakpoints_loop_asm
- comb,=,n scratch1,arg0,check_breakpoints_hit
- addib,>=,n -1,r1,check_breakpoints_loop_asm
- ldwx,s r1(ret0),scratch1
-
- bv 0(scratch4)
- nop
-
- .export check_breakpoints_hit,code
-check_breakpoints_hit
- LDC(halt_sim,scratch1)
- ldw (scratch1),r1
- ldil l%g_fcycles_stop,ret0
- depi 1,31,1,r1
- stw 0,r%g_fcycles_stop(ret0)
- stw 0,r%g_fcycles_stop+4(ret0)
- bv 0(scratch4)
- stw r1,(scratch1)
- nop
- nop
- nop
-
-
-
- .align 8
- .export set_mem_yreg
-set_mem_yreg
-; arg0 = addr to write
- extru,= psr,27,1,0 ;null branch if 16 bit
- b set_memory_asm
- copy yreg,arg1
-;if get here, 16 bit yreg
- b,n set_memory16_asm
- nop
-
-
- .align 8
- .export set_mem_xreg
-set_mem_xreg
-; arg0 = addr to write
- extru,= psr,27,1,0 ;null branch if 16 bit
- b set_memory_asm
- copy xreg,arg1
-;if get here, 16 bit xreg
- b,n set_memory16_asm
- nop
-
-
-
- .export get_memory_outofrange,code
-get_memory_outofrange
- break
-
-
-get_mem_b0_16_stub
- b get_mem_b0_16
- nop
-
- .align 8
-get_mem_b0_direct_page_16
-; get 2 bytes for direct-page fetch.
-; arg0 = addr;
-; if emul and dl = 0, then stick dh in
-; into high bytes.
-; if emul, grab + 1 byte from dh page also.
-; if not emul, just call get_mem_b0
- ldi 0xff,scratch2
- extru,<> psr,23,1,0 ;null next if emul bit set
- b get_mem_b0_16
- extru direct,23,8,scratch1
- and arg0,scratch2,scratch3
- extru,<> direct,31,8,0 ;null if direct not page aligned
- dep scratch1,23,24,arg0 ;..done only if direct is page aligned
- comb,<> scratch3,scratch2,get_mem_b0_16_stub
- stw link,STACK_GET_MEM_B0_DIRECT_SAVELINK(sp)
-; we're at 0x??ff, so next byte needs to come from 0x??00.
- bl get_mem_b0_8,link
- stw arg0,STACK_GET_MEM_B0_DIRECT_ARG0(sp)
-; now, get next byte
- ldw STACK_GET_MEM_B0_DIRECT_ARG0(sp),arg0
- extru direct,23,8,scratch1
- stw ret0,STACK_GET_MEM_B0_DIRECT_RET0(sp)
- addi 1,arg0,arg0
- extru,<> direct,31,8,0 ;null if direct not page aligned
- dep scratch1,23,24,arg0 ;..done only if direct is page aligned
- bl get_mem_b0_8,link
- nop
-
-; and return
- copy ret0,scratch2
- ldw STACK_GET_MEM_B0_DIRECT_SAVELINK(sp),scratch1
- ldb STACK_GET_MEM_B0_DIRECT_RET0+3(sp),ret0
- bv (scratch1)
- dep scratch2,23,8,ret0
-
-
-
-push_8
- copy arg0,arg1
- copy stack,arg0
- addi -1,stack,stack
- extru,= psr,23,1,0 ;emul mode?
- depi 1,23,24,stack
- b set_mem_b0_8
- extru stack,31,16,stack
-
-pull_8
- addi 1,stack,stack
- extru,= psr,23,1,0
- depi 1,23,24,stack
- extru stack,31,16,stack
- b get_mem_b0_8
- copy stack,arg0
-
-push_16
- copy arg0,arg1
- bb,>= psr,23,push_16_native
- extru stack,30,7,scratch1
-
-; push_16_emul
- addi -2,stack,stack
- comib,= 0,scratch1,push_16_emul_page
- addi 1,stack,arg0 ;we know we are not at end of page
- b set_mem_b0_16
- depi 1,23,24,stack
-
-
-push_16_emul_page
- stw link,STACK_SAVE_PUSH16_LINK(sp)
- addi 1,arg0,arg0
- stw arg1,STACK_SAVE_PUSH16_ARG1(sp)
- depi 1,23,24,arg0
- bl set_mem_b0_8,link
- extru arg1,23,8,arg1
-; and do next push
- addi 1,stack,arg0
- depi 1,23,24,stack
- ldw STACK_SAVE_PUSH16_LINK(sp),link
- ldb STACK_SAVE_PUSH16_ARG1+3(sp),arg1
- b set_mem_b0_8
- depi 1,23,24,arg0
-
-push_16_native
-; here, we're a native push_16
- addi -2,stack,stack
- comib,= 0,scratch1,push_16_nat_page
- addi 1,stack,arg0 ;we know we are not at end of page
- b set_mem_b0_16
- extru stack,31,16,stack
-
-
-push_16_nat_page
- stw link,STACK_SAVE_PUSH16_LINK(sp)
- addi 1,arg0,arg0
- stw arg1,STACK_SAVE_PUSH16_ARG1(sp)
- extru arg0,31,16,arg0
- bl set_mem_b0_8,link
- extru arg1,23,8,arg1
-; and do next push
- addi 1,stack,arg0
- extru stack,31,16,stack
- ldw STACK_SAVE_PUSH16_LINK(sp),link
- ldb STACK_SAVE_PUSH16_ARG1+3(sp),arg1
- b set_mem_b0_8
- extru arg0,31,16,arg0
-
-push_16_unsafe
- copy arg0,arg1
- addi -1,stack,arg0
- addi -2,stack,stack
- extru,= psr,23,1,0
- depi 1,23,24,stack
- extru arg0,31,16,arg0
- b set_mem_b0_16
- extru stack,31,16,stack
-
-push_24_unsafe
- copy arg0,arg1
- addi -2,stack,arg0
- addi -3,stack,stack
- extru,= psr,23,1,0
- depi 1,23,24,stack
- extru arg0,31,16,arg0
- b set_mem_b0_24
- extru stack,31,16,stack
-
-pull_16_unsafe
- addi 1,stack,stack
- extru,= psr,23,1,0
- depi 1,23,24,stack
- extru stack,31,16,arg0
- addi 1,stack,stack
- extru,= psr,23,1,0
- depi 1,23,24,stack
- b get_mem_b0_16
- extru stack,31,16,stack
-
- .align 8
-pull_16
- extrs stack,29,6,scratch1
- bb,< psr,23,pull_16_emul
- addi 1,stack,arg0
- comib,= -1,scratch1,pull_16_nat_page
- addi 2,stack,stack
-; if we get here, native & not near page cross
- extru arg0,31,16,arg0
- b get_mem_b0_16
- extru stack,31,16,stack
-
-pull_16_emul
- comib,= -1,scratch1,pull_16_emul_page
- addi 2,stack,stack
-; if get here, emul & not near page cross
- b get_mem_b0_16
- depi 1,23,24,stack
-
-pull_16_nat_page
- stw link,STACK_SAVE_PULL16_LINK(sp)
- bl get_mem_b0_8,link
- extru arg0,31,16,arg0
-; got first byte
- stw ret0,STACK_SAVE_PULL16_RET0(sp)
- extru stack,31,16,stack
- bl get_mem_b0_8,link
- copy stack,arg0
-; got second byte
- ldw STACK_SAVE_PULL16_LINK(sp),link
- copy ret0,scratch1
- ldb STACK_SAVE_PULL16_RET0+3(sp),ret0
- bv 0(link)
- dep scratch1,23,8,ret0
-
-pull_16_emul_page
- stw link,STACK_SAVE_PULL16_LINK(sp)
- bl get_mem_b0_8,link
- depi 1,23,24,arg0
-; got first byte
- stw ret0,STACK_SAVE_PULL16_RET0(sp)
- depi 1,23,24,stack
- bl get_mem_b0_8,link
- copy stack,arg0
-; got second byte
- ldw STACK_SAVE_PULL16_LINK(sp),link
- copy ret0,scratch1
- ldb STACK_SAVE_PULL16_RET0+3(sp),ret0
- bv 0(link)
- dep scratch1,23,8,ret0
-
- .export pull_24,code
-pull_24
- extrs stack,29,6,scratch1
- bb,< psr,23,pull_24_emul
- addi 1,stack,arg0
- comib,= -1,scratch1,pull_24_nat_page
- addi 3,stack,stack
-; if we get here, native & not near page cross, go for it
- extru arg0,31,16,arg0
- b get_mem_b0_24
- extru stack,31,16,stack
-
-pull_24_emul
- depi 1,23,24,arg0
- comib,= -1,scratch1,pull_24_emul_page
- addi 3,stack,stack
-; if we get here, emul & not near page cross
- b get_mem_b0_24
- depi 1,23,24,stack
-
-pull_24_nat_page
- stw link,STACK_SAVE_PULL24_LINK(sp)
- bl get_mem_b0_8,link
- extru arg0,31,16,arg0
-; got first byte
- stw ret0,STACK_SAVE_PULL24_RET0(sp)
- addi -1,stack,arg0
- extru stack,31,16,stack
- bl get_mem_b0_8,link
- extru arg0,31,16,arg0
-; got second byte
- stb ret0,STACK_SAVE_PULL24_RET0+2(sp)
- bl get_mem_b0_8,link
- copy stack,arg0
-; got all bytes
- ldw STACK_SAVE_PULL24_LINK(sp),link
- copy ret0,scratch1
- ldw STACK_SAVE_PULL24_RET0(sp),ret0
- bv (link)
- dep scratch1,15,8,ret0
-
-pull_24_emul_page
- stw link,STACK_SAVE_PULL24_LINK(sp)
- bl get_mem_b0_8,link
- nop
-; got first byte
- addi -1,stack,arg0
- stw ret0,STACK_SAVE_PULL24_RET0(sp)
- depi 1,23,24,stack
- bl get_mem_b0_8,link
- depi 1,23,24,arg0
-; got second byte
- stb ret0,STACK_SAVE_PULL24_RET0+2(sp)
- bl get_mem_b0_8,link
- copy stack,arg0
-; got all bytes
- ldw STACK_SAVE_PULL24_LINK(sp),link
- copy ret0,scratch1
- ldw STACK_SAVE_PULL24_RET0(sp),ret0
- bv (link)
- dep scratch1,15,8,ret0
-
-update_system_state_and_change_kbank
-; kbank already changed..do nothing
-
-update_system_state
-; psr is new psw state
-; arg0 is old in bits 31 and 30
- ldi 0x30,scratch1
- extru,= psr,23,1,0
- depi 3,27,2,psr
- and psr,scratch1,scratch1
- extru,= psr,23,1,0
- depi 1,23,24,stack
- dep arg0,29,2,scratch1
- blr scratch1,0
- addit,>= -0x3d,scratch1,0
-; 0000: no change
- b update_sys9
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 0001: x from 1->0
- b update_sys9
- ldi 2,scratch1
- nop ! nop
- nop ! nop ! nop ! nop
-; 0010: m from 1->0
- b resize_acc_to16
- ldi 0,ret0
- nop ! nop
- nop ! nop ! nop ! nop
-; 0011: m,x from 1->0
- b resize_acc_to16
- ldi 0,ret0
- nop ! nop
- nop ! nop ! nop ! nop
-; 0100: x from 0->1
- depi 0,23,24,yreg
- b update_sys9
- depi 0,23,24,xreg
- nop
- nop ! nop ! nop ! nop
-; 0101: no change
- b update_sys9
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 0110: x from 0->1, m from 1->0
- depi 0,23,24,yreg
- ldi 0,ret0
- b resize_acc_to16
- depi 0,23,24,xreg
- nop ! nop ! nop ! nop
-; 0111: m from 1->0
- b resize_acc_to16
- ldi 0,ret0
- nop ! nop
- nop ! nop ! nop ! nop
-; 1000: m from 0->1
- b resize_acc_to8
- ldi 0,ret0
- nop ! nop
- nop ! nop ! nop ! nop
-; 1001: m from 0->1, x from 1->0
- b resize_acc_to8
- ldi 0,ret0
- nop ! nop
- nop ! nop ! nop ! nop
-; 1010: no change
- b update_sys9
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 1011: x from 1->0
- b update_sys9
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 1100: m,x from 0->1
- depi 0,23,24,yreg
- ldi 0,ret0
- b resize_acc_to8
- depi 0,23,24,xreg
- nop ! nop ! nop ! nop
-; 1101: m from 0->1
- b resize_acc_to8
- ldi 0,ret0
- nop ! nop
- nop ! nop ! nop ! nop
-; 1110: x from 0->1
- depi 0,23,24,yreg
- ldi 0,ret0
- b update_sys9
- depi 0,23,24,xreg
- nop ! nop ! nop ! nop
-; 1111: no change
- b update_sys9
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 10000
- break
-
-
- .export get_yreg_from_mem,code
-get_yreg_from_mem
-; arg0 = addr to read from, write into yreg
- bb,>=,n psr,27,get_yreg_from_mem16
- bl get_mem_b0_8,link
- extru arg0,31,24,arg0
-
- extru ret0,31,8,zero
- extru ret0,24,1,neg
- b dispatch
- copy zero,yreg
-
- .export get_yreg_from_mem16,code
-get_yreg_from_mem16
- bl get_mem_b0_16,link
- extru arg0,31,24,arg0
-
- extru ret0,31,16,zero
- extru ret0,16,1,neg
- b dispatch
- copy zero,yreg
-
-
- .export get_xreg_from_mem,code
-get_xreg_from_mem
-; arg0 = addr to read from, write into xreg
- bb,>=,n psr,27,get_xreg_from_mem16
- bl get_mem_b0_8,link
- extru arg0,31,24,arg0
-
- extru ret0,31,8,zero
- extru ret0,24,1,neg
- b dispatch
- copy zero,xreg
-
- .export get_xreg_from_mem16,code
-get_xreg_from_mem16
- bl get_mem_b0_16,link
- extru arg0,31,24,arg0
-
- extru ret0,31,16,zero
- extru ret0,16,1,neg
- b dispatch
- copy zero,xreg
-
-
-
-
- .export enter_engine,code
-enter_engine
-; load up regs with struct vals
- .proc
- .callinfo frame=STACK_ENGINE_SIZE,caller,save_rp,entry_gr=18,entry_fr=19
- .enter
-
- ldw ENGINE_FPLUS_PTR(arg0),scratch1 ;fplus ptr
- fldds ENGINE_FCYCLES(arg0),fcycles
-
- ldil l%g_fcycles_stop,fcycles_stop_ptr
- ldw ENGINE_REG_ACC(arg0),acc
- ldo r%g_fcycles_stop(fcycles_stop_ptr),fcycles_stop_ptr
- fldds FPLUS_PLUS_1(scratch1),fr_plus_1
- ldo FPLUS_PLUS_3(scratch1),ret0
- fldds FPLUS_PLUS_2(scratch1),fr_plus_2
- ldil l%g_last_vbl_dcycs,ret1
- fldds FPLUS_PLUS_3-FPLUS_PLUS_3(ret0),fr_plus_3
- ldo r%g_last_vbl_dcycs(ret1),ret1
- fldds FPLUS_PLUS_X_M1-FPLUS_PLUS_3(ret0),fr_plus_x_m1
- fldds 0(ret1),fcycles_last_dcycs
- ldil l%table8,ret0
- ldw ENGINE_REG_XREG(arg0),xreg
- ldil l%table16,inst_tab_ptr
- ldw ENGINE_REG_YREG(arg0),yreg
- ldo r%table8(ret0),ret0
- ldw ENGINE_REG_STACK(arg0),stack
- ldo r%table16(inst_tab_ptr),inst_tab_ptr
- ldw ENGINE_REG_PSR(arg0),psr
- ldi 0,zero
- ldw ENGINE_REG_DBANK(arg0),dbank
- ldil l%page_info_rd_wr,page_info_ptr
- ldw ENGINE_REG_DIRECT(arg0),direct
- extru,= psr,26,1,0 ;nullify if acc size = 0 == 16bit
- copy ret0,inst_tab_ptr
- ldw ENGINE_REG_KPC(arg0),kpc
-
- ldo r%page_info_rd_wr(page_info_ptr),page_info_ptr
- extru,<> psr,30,1,0
- ldi 1,zero
- extru psr,24,1,neg
- stw arg0,STACK_SAVE_ARG0(sp)
- ldi 0xfd,const_fd
- b dispatch
- ldi 0,scratch1
-
- .export resize_acc_to8,code
-resize_acc_to8
- ldil l%table8,inst_tab_ptr
- extru psr,27,1,scratch1 ;size of x
- b update_sys9
- ldo r%table8(inst_tab_ptr),inst_tab_ptr
-
- .export resize_acc_to16,code
-resize_acc_to16
- ldil l%table16,inst_tab_ptr
- extru psr,27,1,scratch1
- b update_sys9
- ldo r%table16(inst_tab_ptr),inst_tab_ptr
-
-
-
-dispatch_done_cycles_mismatch
- ldi -1,ret0
- b dispatch_done
- nop
-
-
-
- .export dispatch_done
-dispatch_done
- bl refresh_engine_struct,link
- ldw STACK_SAVE_ARG0(sp),arg0
- .leave
- .procend
-
-refresh_engine_struct
-; warning--this routine must not change arg1, arg2, arg3, or ret0
-; can only change scratch1
-
- comiclr,<> 0,zero,scratch1
- ldi 1,scratch1
- dep neg,24,1,psr
- dep scratch1,30,1,psr
- stw acc,ENGINE_REG_ACC(arg0)
- stw xreg,ENGINE_REG_XREG(arg0)
- stw yreg,ENGINE_REG_YREG(arg0)
- stw stack,ENGINE_REG_STACK(arg0)
- stw dbank,ENGINE_REG_DBANK(arg0)
- stw direct,ENGINE_REG_DIRECT(arg0)
- stw psr,ENGINE_REG_PSR(arg0)
- stw kpc,ENGINE_REG_KPC(arg0)
- bv 0(link)
- fstds fcycles,ENGINE_FCYCLES(arg0)
-
- .export check_irqs_pending,code
-update_sys9
-check_irqs_pending
-; if any g_irq_pending, return RET_IRQ
- ldil l%g_irq_pending,scratch1
- ldw r%g_irq_pending(scratch1),scratch2
- bb,<,n psr,29,dispatch
- comib,= 0,scratch2,dispatch
- zdepi RET_IRQ,3,4,ret0
- b,n dispatch_done
- nop
-
- .export clr_halt_act
- .export set_halt_act
-clr_halt_act
- LDC(halt_sim,scratch1)
- bv 0(link)
- stw 0,(scratch1)
-
-set_halt_act
- LDC(halt_sim,scratch1)
- ldw (scratch1),scratch2
- ldil l%g_fcycles_stop,scratch3
- stw 0,r%g_fcycles_stop(scratch3)
- or scratch2,arg0,arg0
- stw 0,r%g_fcycles_stop+4(scratch3)
- bv 0(link)
- stw arg0,(scratch1)
-
-
- .align 32
- .export dispatch_fast,code
-dispatch_fast
-; instr is the instr to fetch
-#ifdef LOG_PC
- b dispatch
- nop
-#endif
- fldds 0(fcycles_stop_ptr),fcycles_stop
- extru kpc,23,16,arg2
-
- extru kpc,31,8,scratch4
- ldwx,s arg2(page_info_ptr),scratch2
-
- ldwx,s instr(inst_tab_ptr),link
- fcmp,>,dbl fcycles,fcycles_stop ;C=1 if must stop
-
- addl scratch4,scratch2,scratch1
- comclr,>= scratch4,const_fd,0 ;stop for pieces if near end of page
-
- ldi -1,scratch2
- bb,<,n scratch2,BANK_IO_BIT,dispatch_instr_io
-
- ftest ;null next if can cont
-
- bv 0(link)
- CYCLES_PLUS_2
-
- b dispatch_instr_io
- CYCLES_MINUS_2
-
-
- .align 32
- .export dispatch,code
-dispatch
-
-#ifdef CHECK_SIZE_CONSISTENCY
- nop
- bl check_size_consist,link
- nop
-#endif
-
-#ifdef DEBUG_TOOLBOX
- ldil l%g_rom_version,scratch1
- ldw r%g_rom_version(scratch1),scratch1
- ldi 0x00db,scratch1 ;ROM 01
- comiclr,> 3,scratch1,0
- ldi 0x00e5,scratch1 ;ROM 03
- depi -2,15,8,scratch1 ;set bank to 0xfe
- comb,<>,n scratch1,kpc,no_debug_toolbox
- copy xreg,arg0
- copy stack,arg1
- bl toolbox_debug_c,link
- copy cycles,arg2
-
- extru kpc,23,16,scratch2
-no_debug_toolbox
-#endif
- fldds 0(fcycles_stop_ptr),fcycles_stop
- extru kpc,23,16,arg2
-
- ldi 0xfd,scratch3
- ldwx,s arg2(page_info_ptr),scratch2
-
- fcmp,<=,dbl fcycles,fcycles_stop ;C=1 if can cont
- extru kpc,31,8,scratch4
-
- ldbx scratch4(scratch2),instr
- comclr,>= scratch4,scratch3,0 ;stop for pieces if near end of page
-
- ftest ;null next if can cont
-
- ldi -1,scratch2
- ldwx,s instr(inst_tab_ptr),link
-
- addl scratch4,scratch2,scratch1
- bb,<,n scratch2,BANK_IO_BIT,dispatch_instr_io
-
- ; depi 0,31,3,link
-
-#ifndef LOG_PC
- bv 0(link)
- CYCLES_PLUS_2
-#else
- CYCLES_PLUS_2
-
- .import log_pc_ptr,data
- .import log_pc_start_ptr,data
- .import log_pc_end_ptr,data
- .export log_pc_asm
-log_pc_asm
-; save regs into log_pc_ptr, wrap around to log_pc_start_ptr if
-; log_pc_ptr gets > log_pc_end_ptr
- ldb 1(scratch1),scratch3
- dep neg,24,1,psr ;set neg
- ldb 2(scratch1),scratch2
- ldil l%log_pc_ptr,scratch4
- ldb 3(scratch1),ret0
- fsub,dbl fcycles_last_dcycs,fr_plus_2,ftmp1
- dep scratch2,23,8,scratch3
- ldo r%log_pc_ptr(scratch4),scratch4
- dep instr,7,8,scratch3
- ldw 0(scratch4),scratch2
- dep ret0,15,8,scratch3
- copy kpc,ret1
- depi 0,30,1,psr ;zero
- comiclr,<> 0,zero,0
- depi 1,30,1,psr ;set zero
- stw scratch3,LOG_PC_INSTR(scratch2)
- dep dbank,7,8,ret1
- copy acc,scratch3
- dep psr,15,16,scratch3
- fadd,dbl fcycles,ftmp1,ftmp1
- stw ret1,LOG_PC_DBANK_KPC(scratch2)
- copy yreg,ret1
- stw scratch3,LOG_PC_PSR_ACC(scratch2)
- dep xreg,15,16,ret1
- copy direct,scratch3
- fstds ftmp1,LOG_PC_DCYCS(scratch2)
- ldw rs%log_pc_end_ptr-log_pc_ptr(scratch4),ret0
- dep stack,15,16,scratch3
- stw ret1,LOG_PC_XREG_YREG(scratch2)
- addi LOG_PC_SIZE,scratch2,r31
- stw scratch3,LOG_PC_STACK_DIRECT(scratch2)
-
-; comb,>= r31,ret0,log_pc_oflow
-; nop
-
- comclr,< r31,ret0,0
-; reload log_pc with log_pc_start_ptr
- ldw rs%log_pc_start_ptr-log_pc_ptr(scratch4),r31
-
- bv 0(link)
- stw r31,0(scratch4)
-
-log_pc_oflow
- ldil l%g_fcycles_stop,scratch3
- ldil l%halt_sim,ret0
- stw 0,r%g_fcycles_stop(scratch3)
- ldi 2,arg0
- stw 0,r%g_fcycles_stop+4(scratch3)
- stw arg0,r%halt_sim(ret0)
-
- ldw rs%log_pc_start_ptr-log_pc_ptr(scratch4),r31
- bv 0(link)
- stw r31,0(scratch4)
-#endif
-
-
- .export dispatch_instr_io,code
-dispatch_instr_io
-; check if we're here because of timeout or halt required
- fcmp,<=,dbl fcycles,fcycles_stop ;C=1 if we can cont
- ldwx,s arg2(page_info_ptr),scratch2
-
- ftest ;do next instr if must stop
- b,n dispatch_done_clr_ret0
-
- bb,>=,n scratch2,BANK_IO_BIT,dispatch_instr_pieces
-
- ldil l%0xc700,scratch1
- ldo r%0xc700(scratch1),scratch1
- addi 0x0a,scratch1,scratch2
- comb,= scratch1,kpc,dispatch_done
- zdepi RET_C700,3,4,ret0
-
- addi 0xd,scratch1,scratch3
- comb,= scratch2,kpc,dispatch_done
- zdepi RET_C70A,3,4,ret0
-
- comb,= scratch3,kpc,dispatch_done
- zdepi RET_C70D,3,4,ret0
-
- .export dispatch_instr_pieces,code
-dispatch_instr_pieces
-; fetch pc, get size from inst_info_ptr
- bl get_mem_long_8,link
- copy kpc,arg0
-; ret is instr
- ldwx,s ret0(inst_tab_ptr),link
- ldil l%sizes_tab,scratch4
- copy ret0,instr
- ldo r%sizes_tab(scratch4),scratch4
- addi 1,kpc,arg0
- ldbx instr(scratch4),scratch2
-#ifdef LOG_PC
-; save "real" link so call_log_pc can restore it
-
- stw link,STACK_SAVE_DISPATCH_LINK(sp)
- LDC(call_log_pc,link)
- stw instr,STACK_SAVE_INSTR(sp)
-#endif
- stw link,STACK_SAVE_DISP_PIECES_LINK(sp)
-
- ldi 0x1bea,ret0
- sh3add scratch2,0,scratch2
- ldo STACK_SAVE_TMP_INST(sp),scratch1
- blr scratch2,0
- addit,>= -48,scratch2,0
-
-/* must correct cycle count so all instrs are called with cycls += 2 */
-/* since get_mem will auto-inc cycles by the number of bytes, we */
-/* need to "patch" things here, by adding 1 for 1byte, and subbing */
-/* from 3 and 4 byte instrs */
-; 0
- bv 0(link)
- CYCLES_PLUS_1
- nop
- nop
- nop ! nop ! nop ! nop
- nop ! nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 1
- bl get_mem_long_8,link
- nop
- ldw STACK_SAVE_DISP_PIECES_LINK(sp),link
- dep ret0,15,8,ret0
- ldo STACK_SAVE_TMP_INST(sp),scratch1
- bv 0(link)
- stw ret0,0(scratch1)
- nop ! nop
- nop ! nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 2
- bl get_mem_long_16,link
- CYCLES_MINUS_1
- ldo STACK_SAVE_TMP_INST(sp),scratch1
- ldw STACK_SAVE_DISP_PIECES_LINK(sp),link
- dep ret0,15,8,ret0
- bv 0(link)
- stw ret0,0(scratch1)
- nop
- nop ! nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 3
- bl get_mem_long_24,link
- CYCLES_MINUS_2
- shd ret0,ret0,16,scratch2
- ldw STACK_SAVE_DISP_PIECES_LINK(sp),link
- extru ret0,23,8,ret0
- ldo STACK_SAVE_TMP_INST(sp),scratch1
- dep ret0,23,8,scratch2
- bv 0(link)
- stw scratch2,0(scratch1)
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 4 variable acc size
- extru,<> psr,26,1,0
- bl,n get_mem_long_16,link
- bl,n get_mem_long_8,link
- CYCLES_MINUS_1
- ldw STACK_SAVE_DISP_PIECES_LINK(sp),link
- ldo STACK_SAVE_TMP_INST(sp),scratch1
- dep ret0,15,8,ret0
- bv 0(link)
- stw ret0,0(scratch1)
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 5 variable x size
- extru,<> psr,27,1,0
- bl,n get_mem_long_16,link
- bl,n get_mem_long_8,link
- CYCLES_MINUS_1
- ldw STACK_SAVE_DISP_PIECES_LINK(sp),link
- ldo STACK_SAVE_TMP_INST(sp),scratch1
- dep ret0,15,8,ret0
- bv 0(link)
- stw ret0,0(scratch1)
- nop ! nop ! nop
- nop ! nop ! nop ! nop
-; 6 = evil
- break
-
-
-#ifdef LOG_PC
- .export call_log_pc,code
-call_log_pc
-; ret0 = operands
-; must get instr = instruction
-; and link = correct dispatch loc
- ldw STACK_SAVE_INSTR(sp),instr
- b log_pc_asm
- ldw STACK_SAVE_DISPATCH_LINK(sp),link
-#endif
-
-dispatch_done_clr_ret0
- nop ;just in case of bad nullification
- b dispatch_done
- ldi 0,ret0
-
-
-#ifdef CHECK_SIZE_CONSISTENCY
- .import size_fail,code
-
- .export check_size_consist
-check_size_consist
- ldil l%table16,scratch1
- ldil l%table8,scratch2
- ldo r%table16(scratch1),scratch1
- bb,< psr,26,check_tab_8_bit
- ldo r%table8(scratch2),scratch2
-; else 16
- comb,= scratch1,inst_tab_ptr,acc_size_ok
- nop
-
- .export acc_tab_fail1
-acc_tab_fail1
- copy inst_tab_ptr,arg1
- copy scratch1,arg2
- bl size_fail,link
- ldi 0x100,arg0
- b,n dispatch_done_clr_ret0
-; 8
- .export check_tab_8_bit
-check_tab_8_bit
- comb,= scratch2,inst_tab_ptr,acc_size_ok
- nop
-
- .export acc_tab_fail0
-acc_tab_fail0
- copy inst_tab_ptr,arg1
- copy scratch2,arg2
- bl size_fail,link
- ldi 0x101,arg0
- b dispatch_done
- ldi 0,ret0
-
- .export acc_size_ok
-acc_size_ok
- bv 0(link)
- nop
-#endif
-
- .align 8
-adc_binary_8_entry2
- extru psr,31,1,scratch3
- add ret0,scratch3,ret0
-
- dep ret0,31,8,acc
- extru ret0,31,8,zero
-
-/* and calc overflow */
- xor arg0,ret0,arg2 /* cmp binary add res w/ src1 */
- xor arg0,scratch2,scratch3 /* cmp signs of two inputs */
- extru ret0,24,1,neg
- andcm arg2,scratch3,scratch3 /* and that with ~res. */
- extru ret0,23,1,scratch4
- extru scratch3,24,1,scratch3
- dep scratch4,31,1,psr /* set carry */
- b dispatch
- dep scratch3,25,1,psr /* set overflow */
-
- .align 8
- .export adc_binary_8
-adc_binary_8
- extru ret0,31,8,scratch2
- bb,>= psr,28,adc_binary_8_entry2
- add arg0,scratch2,ret0
-
-
- ldil l%dispatch,link
- b adc_decimal_8
- ldo r%dispatch(link),link
-
- .export adc_decimal_8
-/* adds arg0 to scratch2 */
-/* acc8 (in arg0) and ret0 have already been added into ret0. Ignore that */
-adc_decimal_8
- ldi 0xf,scratch1
- extru psr,31,1,ret0
-
- and arg0,scratch1,scratch3
- and scratch2,scratch1,scratch4
-
- add scratch3,scratch4,ret1
- ldi 0xf0,arg3
-
- add ret0,ret1,ret0
-
- and arg0,arg3,scratch3
- addi -0xa,ret0,ret1
-
- and scratch2,arg3,scratch4
- depi 1,27,4,ret1
- comiclr,> 0xa,ret0,0
- copy ret1,ret0
-
- add scratch3,scratch4,ret1
- add ret0,ret1,ret0
-
- extru ret0,24,1,ret1
- extru ret0,23,1,arg1
- xor ret1,arg1,ret1
- dep ret1,25,1,psr /* ov=((sum>>2) ^ (sum>>1) & 0x40 */
-
- comiclr,> 0xa0,ret0,0
- addi 0x60,ret0,ret0
-
- xor arg0,scratch2,scratch4
- extru ret0,31,8,zero
-
- extru,= scratch4,24,1,0
- depi 0,25,1,psr /* no overflow! */
-
-
- depi 0,31,1,psr
- comiclr,> 0x100,ret0,0
- addi 1,psr,psr
-
- extru ret0,24,1,neg
- bv 0(link)
- dep zero,31,8,acc
-
-
-
- .align 8
- .export sbc_binary_8,code
-sbc_binary_8
- extru ret0,31,8,scratch2
- bb,>= psr,28,adc_binary_8_entry2
- add arg0,scratch2,ret0
-
- ldil l%dispatch,link
- b sbc_decimal_8
- ldo r%dispatch(link),link
-
-
-/* else decimal */
- .export sbc_decimal_8,code
-sbc_decimal_8
-/* do arg0 - scratch2 = acc */
- ldi 0xf,scratch1
- extru psr,31,1,ret0
-
- and scratch2,scratch1,scratch3
- and arg0,scratch1,scratch4
-
- add scratch3,ret0,ret0
-
- add ret0,scratch4,ret0
- ldi 0xf0,arg3
-
- addi -0x6,ret0,ret1
- and scratch2,arg3,scratch3
-
- and ret1,scratch1,ret1 /* sum2 = (sum - 0x6) & 0xf */
- and arg0,arg3,scratch4
- comiclr,<= 0x10,ret0,0
- copy ret1,ret0 /* sum = sum2 */
-
- add scratch3,scratch4,ret1
- ldi 0xff,arg2
- add ret0,ret1,ret0
-
- extru ret0,24,1,ret1
- addi 0xa0,ret0,scratch3
- extru ret0,23,1,arg3
- and scratch3,arg2,scratch3 /* (sum = sum + 0xa0) & 0xff */
- xor ret1,arg3,ret1
-
- dep ret1,25,1,psr /* overflow = ((sum >> 2) ^ */
- /* (sum >> 1)) & 0x40 */
-
- depi 0,31,1,psr
- comiclr,<= 0x100,ret0,arg3
- or,TR scratch3,0,ret0
- addi 1,psr,psr
-
- and ret0,arg2,zero
- extru ret0,24,1,neg
-
- xor arg0,scratch2,ret1
-
- extru,= ret1,24,1,0
- depi 0,25,1,psr /* clear overflow */
-
- bv 0(link)
- dep ret0,31,8,acc
-
-
-
- .align 8
- .export adc_binary_16
-adc_binary_16
- extru ret0,31,16,scratch2
- bb,< psr,28,adc_decimal_16
- add arg0,scratch2,ret0
-
-adc_binary_16_entry2
- extru psr,31,1,scratch1
- add ret0,scratch1,ret0
-
- dep ret0,31,16,acc
- extru ret0,31,16,zero
-
-/* and calc overflow */
- xor arg0,ret0,arg2 /* cmp binary add res w/ src1 */
- xor arg0,scratch2,scratch3
- extru ret0,16,1,neg
- andcm arg2,scratch3,scratch3 /* and that with ~res. */
- extru ret0,15,1,scratch4
- extru scratch3,16,1,scratch3
- dep scratch4,31,1,psr /* set carry */
- b dispatch
- dep scratch3,25,1,psr /* set overflow */
-
-
- .export adc_decimal_16
-adc_decimal_16
-/* must save arg0, scratch2 */
- stw arg0,STACK_SAVE_DECIMAL16_A(sp)
- extru arg0,31,8,arg0
- stw scratch2,STACK_SAVE_DECIMAL16_B(sp)
- bl adc_decimal_8,link
- extru scratch2,31,8,scratch2
-
- ldb STACK_SAVE_DECIMAL16_A+2(sp),arg0
- ldb STACK_SAVE_DECIMAL16_B+2(sp),scratch2
- bl adc_decimal_8,link
- stw acc,STACK_SAVE_DECIMAL16_A(sp)
-
- ldw STACK_SAVE_DECIMAL16_A(sp),scratch1
- zdep acc,23,8,acc
- dep scratch1,31,8,acc
- b dispatch
- copy acc,zero
-
-
- .align 8
- .export sbc_binary_16,code
-sbc_binary_16
- extru ret0,31,16,scratch2
- bb,>= psr,28,adc_binary_16_entry2
- add arg0,scratch2,ret0
-
-/* else decimal */
- .export sbc_decimal_16,code
-sbc_decimal_16
- stw arg0,STACK_SAVE_DECIMAL16_A(sp)
- extru arg0,31,8,arg0
- stw scratch2,STACK_SAVE_DECIMAL16_B(sp)
- bl sbc_decimal_8,link
- extru scratch2,31,8,scratch2
-
- ldb STACK_SAVE_DECIMAL16_A+2(sp),arg0
- ldb STACK_SAVE_DECIMAL16_B+2(sp),scratch2
- bl sbc_decimal_8,link
- stw acc,STACK_SAVE_DECIMAL16_A(sp)
-
- ldw STACK_SAVE_DECIMAL16_A(sp),scratch1
- zdep acc,23,8,acc
- dep scratch1,31,8,acc
- b dispatch
- copy acc,zero
-
-
-
-
-#define ACC8
- .code
-#include "defs_instr.h"
-#include "8inst_s.h"
- .code
-#undef SYM
-#undef ACC8
-
- .code
-#include "defs_instr.h"
-#include "16inst_s.h"
- .code
-#undef SYM
-
- .export inst00_8
- .export inst01_8
- .export inst02_8
- .export inst03_8
- .export inst04_8
- .export inst05_8
- .export inst06_8
- .export inst07_8
- .export inst08_8
- .export inst09_8
- .export inst0a_8
- .export inst0b_8
- .export inst0c_8
- .export inst0d_8
- .export inst0e_8
- .export inst0f_8
-
- .export inst10_8
- .export inst11_8
- .export inst12_8
- .export inst13_8
- .export inst14_8
- .export inst15_8
- .export inst16_8
- .export inst17_8
- .export inst18_8
- .export inst19_8
- .export inst1a_8
- .export inst1b_8
- .export inst1c_8
- .export inst1d_8
- .export inst1e_8
- .export inst1f_8
-
- .export inst20_8
- .export inst21_8
- .export inst22_8
- .export inst23_8
- .export inst24_8
- .export inst25_8
- .export inst26_8
- .export inst27_8
- .export inst28_8
- .export inst29_8
- .export inst2a_8
- .export inst2b_8
- .export inst2c_8
- .export inst2d_8
- .export inst2e_8
- .export inst2f_8
-
- .export inst30_8
- .export inst31_8
- .export inst32_8
- .export inst33_8
- .export inst34_8
- .export inst35_8
- .export inst36_8
- .export inst37_8
- .export inst38_8
- .export inst39_8
- .export inst3a_8
- .export inst3b_8
- .export inst3c_8
- .export inst3d_8
- .export inst3e_8
- .export inst3f_8
-
- .export inst40_8
- .export inst41_8
- .export inst42_8
- .export inst43_8
- .export inst44_8
- .export inst45_8
- .export inst46_8
- .export inst47_8
- .export inst48_8
- .export inst49_8
- .export inst4a_8
- .export inst4b_8
- .export inst4c_8
- .export inst4d_8
- .export inst4e_8
- .export inst4f_8
-
- .export inst50_8
- .export inst51_8
- .export inst52_8
- .export inst53_8
- .export inst54_8
- .export inst55_8
- .export inst56_8
- .export inst57_8
- .export inst58_8
- .export inst59_8
- .export inst5a_8
- .export inst5b_8
- .export inst5c_8
- .export inst5d_8
- .export inst5e_8
- .export inst5f_8
-
- .export inst60_8
- .export inst61_8
- .export inst62_8
- .export inst63_8
- .export inst64_8
- .export inst65_8
- .export inst66_8
- .export inst67_8
- .export inst68_8
- .export inst69_8
- .export inst6a_8
- .export inst6b_8
- .export inst6c_8
- .export inst6d_8
- .export inst6e_8
- .export inst6f_8
-
- .export inst70_8
- .export inst71_8
- .export inst72_8
- .export inst73_8
- .export inst74_8
- .export inst75_8
- .export inst76_8
- .export inst77_8
- .export inst78_8
- .export inst79_8
- .export inst7a_8
- .export inst7b_8
- .export inst7c_8
- .export inst7d_8
- .export inst7e_8
- .export inst7f_8
-
- .export inst80_8
- .export inst81_8
- .export inst82_8
- .export inst83_8
- .export inst84_8
- .export inst85_8
- .export inst86_8
- .export inst87_8
- .export inst88_8
- .export inst89_8
- .export inst8a_8
- .export inst8b_8
- .export inst8c_8
- .export inst8d_8
- .export inst8e_8
- .export inst8f_8
- .export inst90_8
- .export inst91_8
- .export inst92_8
- .export inst93_8
- .export inst94_8
- .export inst95_8
- .export inst96_8
- .export inst97_8
- .export inst98_8
- .export inst99_8
- .export inst9a_8
- .export inst9b_8
- .export inst9c_8
- .export inst9d_8
- .export inst9e_8
- .export inst9f_8
- .export insta0_8
- .export insta1_8
- .export insta2_8
- .export insta3_8
- .export insta4_8
- .export insta5_8
- .export insta6_8
- .export insta7_8
- .export insta8_8
- .export insta9_8
- .export instaa_8
- .export instab_8
- .export instac_8
- .export instad_8
- .export instae_8
- .export instaf_8
- .export instb0_8
- .export instb1_8
- .export instb2_8
- .export instb3_8
- .export instb4_8
- .export instb5_8
- .export instb6_8
- .export instb7_8
- .export instb8_8
- .export instb9_8
- .export instba_8
- .export instbb_8
- .export instbc_8
- .export instbd_8
- .export instbe_8
- .export instbf_8
- .export instc0_8
- .export instc1_8
- .export instc2_8
- .export instc3_8
- .export instc4_8
- .export instc5_8
- .export instc6_8
- .export instc7_8
- .export instc8_8
- .export instc9_8
- .export instca_8
- .export instcb_8
- .export instcc_8
- .export instcd_8
- .export instce_8
- .export instcf_8
- .export instd0_8
- .export instd1_8
- .export instd2_8
- .export instd3_8
- .export instd4_8
- .export instd5_8
- .export instd6_8
- .export instd7_8
- .export instd8_8
- .export instd9_8
- .export instda_8
- .export instdb_8
- .export instdc_8
- .export instdd_8
- .export instde_8
- .export instdf_8
- .export inste0_8
- .export inste1_8
- .export inste2_8
- .export inste3_8
- .export inste4_8
- .export inste5_8
- .export inste6_8
- .export inste7_8
- .export inste8_8
- .export inste9_8
- .export instea_8
- .export insteb_8
- .export instec_8
- .export insted_8
- .export instee_8
- .export instef_8
- .export instf0_8
- .export instf1_8
- .export instf2_8
- .export instf3_8
- .export instf4_8
- .export instf5_8
- .export instf6_8
- .export instf7_8
- .export instf8_8
- .export instf9_8
- .export instfa_8
- .export instfb_8
- .export instfc_8
- .export instfd_8
- .export instfe_8
- .export instff_8
-
-
- .export inst00_16
- .export inst01_16
- .export inst02_16
- .export inst03_16
- .export inst04_16
- .export inst05_16
- .export inst06_16
- .export inst07_16
- .export inst08_16
- .export inst09_16
- .export inst0a_16
- .export inst0b_16
- .export inst0c_16
- .export inst0d_16
- .export inst0e_16
- .export inst0f_16
-
- .export inst10_16
- .export inst11_16
- .export inst12_16
- .export inst13_16
- .export inst14_16
- .export inst15_16
- .export inst16_16
- .export inst17_16
- .export inst18_16
- .export inst19_16
- .export inst1a_16
- .export inst1b_16
- .export inst1c_16
- .export inst1d_16
- .export inst1e_16
- .export inst1f_16
-
- .export inst20_16
- .export inst21_16
- .export inst22_16
- .export inst23_16
- .export inst24_16
- .export inst25_16
- .export inst26_16
- .export inst27_16
- .export inst28_16
- .export inst29_16
- .export inst2a_16
- .export inst2b_16
- .export inst2c_16
- .export inst2d_16
- .export inst2e_16
- .export inst2f_16
-
- .export inst30_16
- .export inst31_16
- .export inst32_16
- .export inst33_16
- .export inst34_16
- .export inst35_16
- .export inst36_16
- .export inst37_16
- .export inst38_16
- .export inst39_16
- .export inst3a_16
- .export inst3b_16
- .export inst3c_16
- .export inst3d_16
- .export inst3e_16
- .export inst3f_16
-
- .export inst40_16
- .export inst41_16
- .export inst42_16
- .export inst43_16
- .export inst44_16
- .export inst45_16
- .export inst46_16
- .export inst47_16
- .export inst48_16
- .export inst49_16
- .export inst4a_16
- .export inst4b_16
- .export inst4c_16
- .export inst4d_16
- .export inst4e_16
- .export inst4f_16
-
- .export inst50_16
- .export inst51_16
- .export inst52_16
- .export inst53_16
- .export inst54_16
- .export inst55_16
- .export inst56_16
- .export inst57_16
- .export inst58_16
- .export inst59_16
- .export inst5a_16
- .export inst5b_16
- .export inst5c_16
- .export inst5d_16
- .export inst5e_16
- .export inst5f_16
-
- .export inst60_16
- .export inst61_16
- .export inst62_16
- .export inst63_16
- .export inst64_16
- .export inst65_16
- .export inst66_16
- .export inst67_16
- .export inst68_16
- .export inst69_16
- .export inst6a_16
- .export inst6b_16
- .export inst6c_16
- .export inst6d_16
- .export inst6e_16
- .export inst6f_16
-
- .export inst70_16
- .export inst71_16
- .export inst72_16
- .export inst73_16
- .export inst74_16
- .export inst75_16
- .export inst76_16
- .export inst77_16
- .export inst78_16
- .export inst79_16
- .export inst7a_16
- .export inst7b_16
- .export inst7c_16
- .export inst7d_16
- .export inst7e_16
- .export inst7f_16
-
- .export inst80_16
- .export inst81_16
- .export inst82_16
- .export inst83_16
- .export inst84_16
- .export inst85_16
- .export inst86_16
- .export inst87_16
- .export inst88_16
- .export inst89_16
- .export inst8a_16
- .export inst8b_16
- .export inst8c_16
- .export inst8d_16
- .export inst8e_16
- .export inst8f_16
- .export inst90_16
- .export inst91_16
- .export inst92_16
- .export inst93_16
- .export inst94_16
- .export inst95_16
- .export inst96_16
- .export inst97_16
- .export inst98_16
- .export inst99_16
- .export inst9a_16
- .export inst9b_16
- .export inst9c_16
- .export inst9d_16
- .export inst9e_16
- .export inst9f_16
- .export insta0_16
- .export insta1_16
- .export insta2_16
- .export insta3_16
- .export insta4_16
- .export insta5_16
- .export insta6_16
- .export insta7_16
- .export insta8_16
- .export insta9_16
- .export instaa_16
- .export instab_16
- .export instac_16
- .export instad_16
- .export instae_16
- .export instaf_16
- .export instb0_16
- .export instb1_16
- .export instb2_16
- .export instb3_16
- .export instb4_16
- .export instb5_16
- .export instb6_16
- .export instb7_16
- .export instb8_16
- .export instb9_16
- .export instba_16
- .export instbb_16
- .export instbc_16
- .export instbd_16
- .export instbe_16
- .export instbf_16
- .export instc0_16
- .export instc1_16
- .export instc2_16
- .export instc3_16
- .export instc4_16
- .export instc5_16
- .export instc6_16
- .export instc7_16
- .export instc8_16
- .export instc9_16
- .export instca_16
- .export instcb_16
- .export instcc_16
- .export instcd_16
- .export instce_16
- .export instcf_16
- .export instd0_16
- .export instd1_16
- .export instd2_16
- .export instd3_16
- .export instd4_16
- .export instd5_16
- .export instd6_16
- .export instd7_16
- .export instd8_16
- .export instd9_16
- .export instda_16
- .export instdb_16
- .export instdc_16
- .export instdd_16
- .export instde_16
- .export instdf_16
- .export inste0_16
- .export inste1_16
- .export inste2_16
- .export inste3_16
- .export inste4_16
- .export inste5_16
- .export inste6_16
- .export inste7_16
- .export inste8_16
- .export inste9_16
- .export instea_16
- .export insteb_16
- .export instec_16
- .export insted_16
- .export instee_16
- .export instef_16
- .export instf0_16
- .export instf1_16
- .export instf2_16
- .export instf3_16
- .export instf4_16
- .export instf5_16
- .export instf6_16
- .export instf7_16
- .export instf8_16
- .export instf9_16
- .export instfa_16
- .export instfb_16
- .export instfc_16
- .export instfd_16
- .export instfe_16
- .export instff_16
-
-
- .data
-#include "8size_s.h"
-
- .export table8,data
-table8
-#include "8size_s.h"
-
- .export table16,data
-table16
-#include "16size_s.h"
-
- .export sizes_tab,data
-sizes_tab
-#include "size_s.h"
-
-
- .export g_engine_c_mode,data
-g_engine_c_mode
- .word 0
-
- .bss
-
- .export slow_memory,data
- .export rom_fc_ff,data
- .export rom_cards,data
- .export dummy_memory1,data
- .align 0x100
-slow_memory .block 128*1024
-dummy_memory1 .block 3*1024
-rom_fc_ff .block 256*1024
-rom_cards .block 256*16
diff --git a/src/instable.h b/src/instable.h
index 5ff6a5e..9f3972b 100644
--- a/src/instable.h
+++ b/src/instable.h
@@ -6,74 +6,6 @@
*/
inst00_SYM /* brk */
-#ifdef ASM
- ldb 1(scratch1),ret0
- ldil l%g_testing,arg3
- ldil l%g_num_brk,arg1
- ldw r%g_testing(arg3),arg3
- INC_KPC_2;
- ldw r%g_num_brk(arg1),arg2
- comib,<> 0,arg3,brk_testing_SYM
- extru kpc,31,16,arg0
- addi 1,arg2,arg2
- bb,>= psr,23,brk_native_SYM
- stw arg2,r%g_num_brk(arg1)
-
- bl push_16,link
- nop
-
- bl push_8,link
- extru psr,31,8,arg0 ;B bit already on in PSR
-
- ldil l%0xfffe,arg0
- bl get_mem_long_16,link
- ldo r%0xfffe(arg0),arg0
-
- zdep ret0,31,16,kpc ;set kbank to 0
-
-#if 0
- bl set_halt_act,link
- ldi 3,arg0
-#endif
-
-
- ldi 0,dbank ;clear dbank in emul mode
- b dispatch
- depi 1,29,2,psr ;ints masked, decimal off
-
-
-brk_native_SYM
- stw arg0,STACK_SAVE_COP_ARG0(sp)
- bl push_8,link
- extru kpc,15,8,arg0
-
- bl push_16,link
- ldw STACK_SAVE_COP_ARG0(sp),arg0
-
- bl push_8,link
- extru psr,31,8,arg0
-
- ldil l%0xffe6,arg0
- bl get_mem_long_16,link
- ldo r%0xffe6(arg0),arg0
-
- zdep ret0,31,16,kpc ;zero kbank in kpc
-
-#if 0
-#endif
- bl set_halt_act,link
- ldi 3,arg0
-
- b dispatch
- depi 1,29,2,psr ;ints masked, decimal off
-
-brk_testing_SYM
- DEC_KPC2;
- CYCLES_PLUS_2
- b dispatch_done
- depi RET_BREAK,3,4,ret0
-
-#else
GET_1BYTE_ARG;
if(g_testing) {
CYCLES_PLUS_2;
@@ -96,7 +28,6 @@ brk_testing_SYM
kpc = kpc & 0xffff;
psr |= 0x4;
psr &= ~(0x8);
-#endif
inst01_SYM /* ORA (Dloc,X) */
/* called with arg = val to ORA in */
@@ -104,55 +35,6 @@ inst01_SYM /* ORA (Dloc,X) */
ORA_INST();
inst02_SYM /* COP */
-#ifdef ASM
- ldil l%g_num_cop,arg1
- INC_KPC_2;
- ldw r%g_num_cop(arg1),arg2
- extru kpc,31,16,arg0
- addi 1,arg2,arg2
- bb,>= psr,23,cop_native_SYM
- stw arg2,r%g_num_cop(arg1)
-
- bl push_16,link
- nop
-
- bl push_8,link
- extru psr,31,8,arg0
-
- ldil l%0xfff4,arg0
- bl get_mem_long_16,link
- ldo r%0xfff4(arg0),arg0
-
- ldi 0,dbank ;clear dbank in emul mode
- zdep ret0,31,16,kpc ;clear kbank
-
- bl set_halt_act,link
- ldi 3,arg0
-
- b dispatch
- depi 1,29,2,psr ;ints masked, decimal off
-
-cop_native_SYM
- stw arg0,STACK_SAVE_COP_ARG0(sp)
- bl push_8,link
- extru kpc,15,8,arg0
-
- bl push_16,link
- ldw STACK_SAVE_COP_ARG0(sp),arg0
-
- bl push_8,link
- extru psr,31,8,arg0
-
- ldil l%0xffe4,arg0
- bl get_mem_long_16,link
- ldo r%0xffe4(arg0),arg0
-
- zdep ret0,31,16,kpc ;clear kbank
- b dispatch
- depi 1,29,2,psr ;ints masked, decimal off
-
-
-#else
g_num_cop++;
INC_KPC_2;
if(psr & 0x100) {
@@ -170,7 +52,6 @@ cop_native_SYM
kpc = kpc & 0xffff;
psr |= 4;
psr &= ~(0x8);
-#endif
inst03_SYM /* ORA Disp8,S */
GET_DISP8_S_RD();
@@ -193,74 +74,31 @@ inst07_SYM /* ORA [Dloc] */
ORA_INST();
inst08_SYM /* PHP */
-#ifdef ASM
- dep neg,24,1,psr
- ldil l%dispatch,link
- INC_KPC_1
- depi 0,30,1,psr
- comiclr,<> 0,zero,0
- depi 1,30,1,psr
- ldo r%dispatch(link),link
- b push_8
- extru psr,31,8,arg0
-#else
INC_KPC_1;
psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1);
PUSH8(psr);
-#endif
+
inst09_SYM /* ORA #imm */
GET_IMM_MEM();
ORA_INST();
inst0a_SYM /* ASL a */
-#ifdef ASM
-# ifdef ACC8
- ldi 0xff,scratch1
- sh1add acc,0,scratch3
- INC_KPC_1
- extru scratch3,24,1,neg
- and scratch3,scratch1,zero
- extru scratch3,23,1,scratch2
- dep zero,31,8,acc
- b dispatch
- dep scratch2,31,1,psr /* set carry */
-# else
- zdepi -1,31,16,scratch1
- sh1add acc,0,scratch3
- INC_KPC_1
- extru scratch3,16,1,neg
- and scratch3,scratch1,zero
- extru scratch3,15,1,scratch2
- dep scratch2,31,1,psr /* set carry */
- b dispatch
- dep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
tmp1 = acc + acc;
-# ifdef ACC8
+#ifdef ACC8
SET_CARRY8(tmp1);
acc = (acc & 0xff00) + (tmp1 & 0xff);
SET_NEG_ZERO8(acc & 0xff);
-# else
+#else
SET_CARRY16(tmp1);
acc = tmp1 & 0xffff;
SET_NEG_ZERO16(acc);
-# endif
#endif
inst0b_SYM /* PHD */
-#ifdef ASM
- ldil l%dispatch,link
- extru direct,31,16,arg0
- INC_KPC_1
- b push_16_unsafe
- ldo r%dispatch(link),link
-#else
INC_KPC_1;
PUSH16_UNSAFE(direct);
-#endif
inst0c_SYM /* TSB abs */
GET_ABS_RD();
@@ -280,16 +118,7 @@ inst0f_SYM /* ORA long */
inst10_SYM /* BPL disp8 */
-#ifdef ASM
- COND_BR1
- comib,<> 0,neg,inst10_2_SYM
- COND_BR2
-
-inst10_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8(neg == 0);
-#endif
inst11_SYM /* ORA (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -320,14 +149,8 @@ inst17_SYM /* ORA [Dloc],Y */
ORA_INST();
inst18_SYM /* CLC */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- depi 0,31,1,psr /* clear carry */
-#else
psr = psr & (~1);
INC_KPC_1;
-#endif
inst19_SYM /* ORA abs,y */
GET_ABS_Y_RD();
@@ -335,50 +158,21 @@ inst19_SYM /* ORA abs,y */
inst1a_SYM /* INC a */
-#ifdef ASM
-# ifdef ACC8
- ldi 0xff,scratch2
- addi 1,acc,scratch1
- extru scratch1,24,1,neg
- INC_KPC_1
- extru scratch1,31,8,zero
- b dispatch
- dep zero,31,8,acc
-# else
- zdepi -1,31,16,scratch2
- addi 1,acc,scratch1
- extru scratch1,16,1,neg
- INC_KPC_1
- extru scratch1,31,16,zero
- b dispatch
- dep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
-# ifdef ACC8
+#ifdef ACC8
acc = (acc & 0xff00) | ((acc + 1) & 0xff);
SET_NEG_ZERO8(acc & 0xff);
-# else
+#else
acc = (acc + 1) & 0xffff;
SET_NEG_ZERO16(acc);
-# endif
#endif
inst1b_SYM /* TCS */
-#ifdef ASM
- copy acc,stack
- extru,= psr,23,1,0 /* in emulation mode, stack page 1 */
- depi 1,23,24,stack
- INC_KPC_1
- b dispatch
- nop
-#else
stack = acc;
INC_KPC_1;
if(psr & 0x100) {
stack = (stack & 0xff) + 0x100;
}
-#endif
inst1c_SYM /* TRB Abs */
GET_ABS_RD();
@@ -398,24 +192,12 @@ inst1f_SYM /* ORA Long,X */
inst20_SYM /* JSR abs */
-#ifdef ASM
- addi 2,kpc,arg0
- ldb 1(scratch1),scratch2
- CYCLES_PLUS_2
- ldb 2(scratch1),scratch1
- ldil l%dispatch,link
- extru arg0,31,16,arg0
- ldo r%dispatch(link),link
- dep scratch2,31,8,kpc
- b push_16
- dep scratch1,23,8,kpc
-#else
GET_2BYTE_ARG;
INC_KPC_2;
PUSH16(kpc);
kpc = (kpc & 0xff0000) + arg;
CYCLES_PLUS_2;
-#endif
+
inst21_SYM /* AND (Dloc,X) */
/* called with arg = val to AND in */
@@ -423,28 +205,12 @@ inst21_SYM /* AND (Dloc,X) */
AND_INST();
inst22_SYM /* JSL Long */
-#ifdef ASM
- INC_KPC_3
- ldb 3(scratch1),scratch2
- copy kpc,arg0
- ldb 1(scratch1),kpc
- ldb 2(scratch1),scratch1
- CYCLES_PLUS_3
- dep scratch2,15,8,kpc
- stw scratch2,STACK_SAVE_INSTR_TMP1(sp)
- bl push_24_unsafe,link
- dep scratch1,23,8,kpc
-
- b dispatch
- nop
-#else
GET_3BYTE_ARG;
tmp1 = arg;
CYCLES_PLUS_3;
INC_KPC_3;
PUSH24_UNSAFE(kpc);
kpc = tmp1 & 0xffffff;
-#endif
inst23_SYM /* AND Disp8,S */
/* called with arg = val to AND in */
@@ -471,20 +237,6 @@ inst27_SYM /* AND [Dloc] */
AND_INST();
inst28_SYM /* PLP */
-#ifdef ASM
- bl pull_8,link
- ldi 0,zero
-
- extru psr,27,2,scratch2 /* save old x & m */
- dep ret0,31,8,psr
- CYCLES_PLUS_1
- INC_KPC_1
- extru,<> ret0,30,1,0
- ldi 1,zero
- copy scratch2,arg0
- b update_system_state
- extru ret0,24,1,neg
-#else
PULL8(tmp1);
tmp2 = psr;
CYCLES_PLUS_1;
@@ -493,7 +245,6 @@ inst28_SYM /* PLP */
zero = !(psr & 2);
neg = (psr >> 7) & 1;
UPDATE_PSR(psr, tmp2);
-#endif
inst29_SYM /* AND #imm */
@@ -501,60 +252,25 @@ inst29_SYM /* AND #imm */
AND_INST();
inst2a_SYM /* ROL a */
-#ifdef ASM
-# ifdef ACC8
- extru psr,31,1,scratch2
- ldi 0xff,scratch1
- sh1add acc,scratch2,scratch3
- INC_KPC_1
- extru scratch3,24,1,neg
- and scratch3,scratch1,zero
- extru scratch3,23,1,scratch2
- dep zero,31,8,acc
- b dispatch
- dep scratch2,31,1,psr /* set carry */
-# else
- extru psr,31,1,scratch2
- INC_KPC_1
- sh1add acc,scratch2,scratch3
- zdepi -1,31,16,scratch1
- extru scratch3,16,1,neg
- and scratch3,scratch1,zero
- extru scratch3,15,1,scratch2
- dep scratch2,31,1,psr /* set carry */
- b dispatch
- dep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
-# ifdef ACC8
+#ifdef ACC8
tmp1 = ((acc & 0xff) << 1) + (psr & 1);
SET_CARRY8(tmp1);
acc = (acc & 0xff00) + (tmp1 & 0xff);
SET_NEG_ZERO8(tmp1 & 0xff);
-# else
+#else
tmp1 = (acc << 1) + (psr & 1);
SET_CARRY16(tmp1);
acc = (tmp1 & 0xffff);
SET_NEG_ZERO16(acc);
-# endif
#endif
+
inst2b_SYM /* PLD */
-#ifdef ASM
- INC_KPC_1
- bl pull_16_unsafe,link
- CYCLES_PLUS_1
- extru ret0,31,16,direct
- extru ret0,16,1,neg
- b dispatch
- copy direct,zero
-#else
INC_KPC_1;
PULL16_UNSAFE(direct);
CYCLES_PLUS_1;
SET_NEG_ZERO16(direct);
-#endif
inst2c_SYM /* BIT abs */
GET_ABS_RD();
@@ -574,16 +290,7 @@ inst2f_SYM /* AND long */
inst30_SYM /* BMI disp8 */
-#ifdef ASM
- COND_BR1
- comib,= 0,neg,inst30_2_SYM
- COND_BR2
-
-inst30_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8(neg);
-#endif
inst31_SYM /* AND (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -614,60 +321,28 @@ inst37_SYM /* AND [Dloc],Y */
AND_INST();
inst38_SYM /* SEC */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- depi 1,31,1,psr /* set carry */
-#else
psr = psr | 1;
INC_KPC_1;
-#endif
inst39_SYM /* AND abs,y */
GET_ABS_Y_RD();
AND_INST();
inst3a_SYM /* DEC a */
-#ifdef ASM
-# ifdef ACC8
- addi -1,acc,scratch1
- extru scratch1,24,1,neg
- INC_KPC_1
- extru scratch1,31,8,zero
- b dispatch
- dep zero,31,8,acc
-# else
- addi -1,acc,scratch1
- extru scratch1,16,1,neg
- INC_KPC_1
- extru scratch1,31,16,zero
- b dispatch
- dep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
-# ifdef ACC8
+#ifdef ACC8
acc = (acc & 0xff00) | ((acc - 1) & 0xff);
SET_NEG_ZERO8(acc & 0xff);
-# else
+#else
acc = (acc - 1) & 0xffff;
SET_NEG_ZERO16(acc);
-# endif
#endif
inst3b_SYM /* TSC */
/* set N,Z according to 16 bit acc */
-#ifdef ASM
- copy stack,acc
- extru stack,16,1,neg
- INC_KPC_1
- b dispatch
- extru acc,31,16,zero
-#else
INC_KPC_1;
acc = stack;
SET_NEG_ZERO16(acc);
-#endif
inst3c_SYM /* BIT Abs,x */
GET_ABS_X_RD();
@@ -687,43 +362,6 @@ inst3f_SYM /* AND Long,X */
inst40_SYM /* RTI */
-#ifdef ASM
- bb,>= psr,23,rti_native_SYM
- CYCLES_PLUS_1
-/* emulation */
- bl pull_24,link
- ldi 0,zero
-
- extru psr,27,2,scratch2
- extru ret0,23,16,scratch3
- copy scratch2,arg0
- extru,<> ret0,30,1,0
- ldi 1,zero
- dep ret0,31,8,psr
-
- extru ret0,24,1,neg
- b update_system_state
- dep scratch3,31,16,kpc
-
-rti_native_SYM
- bl pull_8,link
- ldi 0,zero
-
- copy ret0,scratch1
- extru ret0,24,1,neg
- dep ret0,31,8,scratch1
- bl pull_24,link
- stw scratch1,STACK_SAVE_INSTR_TMP1(sp)
-
- extru psr,27,2,scratch2
- ldw STACK_SAVE_INSTR_TMP1(sp),psr
- extru ret0,31,24,kpc
- extru,<> psr,30,1,0
- ldi 1,zero
-
- b update_system_state_and_change_kbank
- copy scratch2,arg0
-#else
CYCLES_PLUS_1
if(psr & 0x100) {
PULL24(tmp1);
@@ -742,8 +380,6 @@ rti_native_SYM
PULL24(kpc);
UPDATE_PSR(psr, tmp2);
}
-#endif
-
inst41_SYM /* EOR (Dloc,X) */
/* called with arg = val to EOR in */
@@ -751,20 +387,11 @@ inst41_SYM /* EOR (Dloc,X) */
EOR_INST();
inst42_SYM /* WDM */
-#ifdef ASM
- ldb 1(scratch1),ret0
- CYCLES_PLUS_5
- CYCLES_PLUS_2
- INC_KPC_2
- b dispatch_done
- depi RET_WDM,3,4,ret0
-#else
GET_1BYTE_ARG;
INC_KPC_2;
CYCLES_PLUS_5;
CYCLES_PLUS_2;
FINISH(RET_WDM, arg & 0xff);
-#endif
inst43_SYM /* EOR Disp8,S */
/* called with arg = val to EOR in */
@@ -772,65 +399,6 @@ inst43_SYM /* EOR Disp8,S */
EOR_INST();
inst44_SYM /* MVP */
-#ifdef ASM
- ldb 2(scratch1),scratch2 /* src bank */
- bb,< psr,23,inst44_notnat_SYM
- ldb 1(scratch1),dbank /* dest bank */
- bb,< psr,27,inst44_notnat_SYM
- stw scratch2,STACK_SRC_BANK(sp)
-
-inst44_loop_SYM
- CYCLES_PLUS_1
- ldw STACK_SRC_BANK(sp),scratch2
- copy xreg,arg0
-
- bl get_mem_long_8,link
- dep scratch2,15,8,arg0
-/* got byte */
- copy ret0,arg1
- copy yreg,arg0
- bl set_mem_long_8,link
- dep dbank,15,8,arg0
-/* wrote byte, dec acc */
- CYCLES_PLUS_2
- fldds 0(fcycles_stop_ptr),fcycles_stop
- addi -1,xreg,xreg
- zdepi -1,31,16,scratch2
- addi -1,yreg,yreg
- addi -1,acc,acc
- fcmp,<,dbl fcycles,fcycles_stop
- and xreg,scratch2,xreg
- extrs acc,31,16,scratch1
- and yreg,scratch2,yreg
-
- comib,= -1,scratch1,inst44_done_SYM
- and acc,scratch2,acc
-
- ftest
- b inst44_out_of_time_SYM
-
- CYCLES_PLUS_2
- b inst44_loop_SYM
- nop
-
-/* get here if done */
-inst44_done_SYM
- INC_KPC_3
- b dispatch
- nop
-
-inst44_notnat_SYM
- copy dbank,ret0
- dep scratch2,23,8,ret0
- CYCLES_PLUS_3
- depi RET_MVP,3,4,ret0
- b dispatch_done
- CYCLES_PLUS_2
-
-inst44_out_of_time_SYM
-/* cycle have gone positive, just get out, do not update kpc */
- b,n dispatch
-#else
GET_2BYTE_ARG;
/* arg & 0xff = dest bank, arg & 0xff00 = src bank */
if(psr & 0x110) {
@@ -856,7 +424,6 @@ inst44_out_of_time_SYM
break;
}
}
-#endif
inst45_SYM /* EOR Dloc */
@@ -875,27 +442,11 @@ inst47_SYM /* EOR [Dloc] */
EOR_INST();
inst48_SYM /* PHA */
-#ifdef ASM
-# ifdef ACC8
- INC_KPC_1
- ldil l%dispatch,link
- extru acc,31,8,arg0
- b push_8
- ldo r%dispatch(link),link
-# else
- INC_KPC_1
- ldil l%dispatch,link
- extru acc,31,16,arg0
- b push_16
- ldo r%dispatch(link),link
-# endif
-#else
INC_KPC_1;
-# ifdef ACC8
+#ifdef ACC8
PUSH8(acc);
-# else
+#else
PUSH16(acc);
-# endif
#endif
inst49_SYM /* EOR #imm */
@@ -903,64 +454,27 @@ inst49_SYM /* EOR #imm */
EOR_INST();
inst4a_SYM /* LSR a */
-#ifdef ASM
-# ifdef ACC8
- extru acc,31,1,scratch2
- INC_KPC_1
- extru acc,30,7,zero
- ldi 0,neg
- dep scratch2,31,1,psr /* set carry */
- b dispatch
- dep zero,31,8,acc
-# else
- extru acc,31,1,scratch2
- INC_KPC_1
- extru acc,30,15,zero
- ldi 0,neg
- dep scratch2,31,1,psr /* set carry */
- b dispatch
- dep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
-# ifdef ACC8
+#ifdef ACC8
tmp1 = ((acc & 0xff) >> 1);
SET_CARRY8(acc << 8);
acc = (acc & 0xff00) + (tmp1 & 0xff);
SET_NEG_ZERO8(tmp1 & 0xff);
-# else
+#else
tmp1 = (acc >> 1);
SET_CARRY8((acc << 8));
acc = (tmp1 & 0xffff);
SET_NEG_ZERO16(acc);
-# endif
#endif
inst4b_SYM /* PHK */
-#ifdef ASM
- ldil l%dispatch,link
- extru kpc,15,8,arg0
- INC_KPC_1
- b push_8
- ldo r%dispatch(link),link
-#else
PUSH8(kpc >> 16);
INC_KPC_1;
-#endif
inst4c_SYM /* JMP abs */
-#ifdef ASM
- ldb 1(scratch1),scratch2
- CYCLES_PLUS_1
- ldb 2(scratch1),scratch1
- dep scratch2,31,8,kpc
- b dispatch
- dep scratch1,23,8,kpc
-#else
GET_2BYTE_ARG;
CYCLES_PLUS_1;
kpc = (kpc & 0xff0000) + arg;
-#endif
inst4d_SYM /* EOR abs */
@@ -977,17 +491,7 @@ inst4f_SYM /* EOR long */
inst50_SYM /* BVC disp8 */
-#ifdef ASM
- COND_BR1
- bb,< psr,25,inst50_2_SYM
- COND_BR2
-
-inst50_2_SYM
- COND_BR_UNTAKEN
-
-#else
BRANCH_DISP8((psr & 0x40) == 0);
-#endif
inst51_SYM /* EOR (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -1002,66 +506,6 @@ inst53_SYM /* EOR (Disp8,s),y */
EOR_INST();
inst54_SYM /* MVN */
-#ifdef ASM
- ldb 2(scratch1),scratch2 /* src bank */
- bb,< psr,23,inst54_notnat_SYM
- ldb 1(scratch1),dbank /* dest bank */
- bb,< psr,27,inst54_notnat_SYM
- stw scratch2,STACK_SRC_BANK(sp)
-
-/* even in 8bit acc mode, use 16-bit accumulator! */
-
-inst54_loop_SYM
- CYCLES_PLUS_1
- ldw STACK_SRC_BANK(sp),scratch2
- copy xreg,arg0
-
- bl get_mem_long_8,link
- dep scratch2,15,8,arg0
-/* got byte */
- copy ret0,arg1
- copy yreg,arg0
- bl set_mem_long_8,link
- dep dbank,15,8,arg0
-/* wrote byte, dec acc */
- CYCLES_PLUS_2
- fldds 0(fcycles_stop_ptr),fcycles_stop
- addi 1,xreg,xreg
- zdepi -1,31,16,scratch2
- addi 1,yreg,yreg
- addi -1,acc,acc
- fcmp,<,dbl fcycles,fcycles_stop
- and xreg,scratch2,xreg
- extrs acc,31,16,scratch1
- and yreg,scratch2,yreg
-
- comib,= -1,scratch1,inst54_done_SYM
- and acc,scratch2,acc
- ftest
- b,n inst54_out_of_time_SYM
-
- CYCLES_PLUS_2
- b inst54_loop_SYM
- nop
-
-/* get here if done */
-inst54_done_SYM
- INC_KPC_3
- b dispatch
- nop
-
-inst54_out_of_time_SYM
-/* cycle have gone positive, just get out, don't update kpc */
- b,n dispatch
-
-inst54_notnat_SYM
- copy dbank,ret0
- dep scratch2,23,8,ret0
- CYCLES_PLUS_3
- depi RET_MVN,3,4,ret0
- b dispatch_done
- CYCLES_PLUS_3
-#else
GET_2BYTE_ARG;
/* arg & 0xff = dest bank, arg & 0xff00 = src bank */
if(psr & 0x110) {
@@ -1087,7 +531,6 @@ inst54_notnat_SYM
break;
}
}
-#endif
inst55_SYM /* EOR Dloc,x */
GET_DLOC_X_RD();
@@ -1102,71 +545,33 @@ inst57_SYM /* EOR [Dloc],Y */
EOR_INST();
inst58_SYM /* CLI */
-#ifdef ASM
- INC_KPC_1
- b check_irqs_pending /* check for ints pending! */
- depi 0,29,1,psr /* clear int disable */
-#else
psr = psr & (~4);
INC_KPC_1;
if(((psr & 0x4) == 0) && g_irq_pending) {
FINISH(RET_IRQ, 0);
}
-#endif
inst59_SYM /* EOR abs,y */
GET_ABS_Y_RD();
EOR_INST();
inst5a_SYM /* PHY */
-#ifdef ASM
- INC_KPC_1
- ldil l%dispatch,link
- bb,>= psr,27,phy_16_SYM
- ldo r%dispatch(link),link
-
- b push_8
- copy yreg,arg0
-
-phy_16_SYM
- b push_16
- copy yreg,arg0
-#else
INC_KPC_1;
if(psr & 0x10) {
PUSH8(yreg);
} else {
PUSH16(yreg);
}
-#endif
inst5b_SYM /* TCD */
-#ifdef ASM
- extru acc,31,16,direct
- INC_KPC_1
- copy acc,zero
- b dispatch
- extru acc,16,1,neg
-#else
INC_KPC_1;
direct = acc;
SET_NEG_ZERO16(acc);
-#endif
inst5c_SYM /* JMP Long */
-#ifdef ASM
- ldb 1(scratch1),kpc
- ldb 2(scratch1),scratch2
- CYCLES_PLUS_1
- ldb 3(scratch1),arg0 /* new bank */
- dep scratch2,23,8,kpc
- b dispatch
- dep arg0,15,8,kpc
-#else
GET_3BYTE_ARG;
CYCLES_PLUS_1;
kpc = arg;
-#endif
inst5d_SYM /* EOR Abs,X */
GET_ABS_X_RD();
@@ -1182,19 +587,9 @@ inst5f_SYM /* EOR Long,X */
inst60_SYM /* RTS */
-#ifdef ASM
- bl pull_16,link
- CYCLES_PLUS_2
-/* ret0 is new kpc-1 */
- addi 1,ret0,ret0
- b dispatch
- dep ret0,31,16,kpc
-#else
CYCLES_PLUS_2
PULL16(tmp1);
kpc = (kpc & 0xff0000) + ((tmp1 + 1) & 0xffff);
-#endif
-
inst61_SYM /* ADC (Dloc,X) */
/* called with arg = val to ADC in */
@@ -1202,23 +597,10 @@ inst61_SYM /* ADC (Dloc,X) */
ADC_INST();
inst62_SYM /* PER */
-#ifdef ASM
- ldb 1(scratch1),ret0
- INC_KPC_3
- ldb 2(scratch1),scratch1
- CYCLES_PLUS_2
- ldil l%dispatch,link
- dep scratch1,23,8,ret0
- ldo r%dispatch(link),link
- add kpc,ret0,arg0
- b push_16_unsafe
- extru arg0,31,16,arg0
-#else
GET_2BYTE_ARG;
CYCLES_PLUS_2;
INC_KPC_3;
PUSH16_UNSAFE(kpc + arg);
-#endif
inst63_SYM /* ADC Disp8,S */
/* called with arg = val to ADC in */
@@ -1245,110 +627,46 @@ inst67_SYM /* ADC [Dloc] */
ADC_INST();
inst68_SYM /* PLA */
-#ifdef ASM
-# ifdef ACC8
- INC_KPC_1
- bl pull_8,link
- CYCLES_PLUS_1
- extru ret0,31,8,zero
- extru ret0,24,1,neg
- b dispatch
- dep ret0,31,8,acc
-# else
- INC_KPC_1
- bl pull_16,link
- CYCLES_PLUS_1
-
- extru ret0,31,16,zero
- extru ret0,16,1,neg
- b dispatch
- extru ret0,31,16,acc
-# endif
-#else
INC_KPC_1;
CYCLES_PLUS_1;
-# ifdef ACC8
+#ifdef ACC8
PULL8(tmp1);
acc = (acc & 0xff00) + tmp1;
SET_NEG_ZERO8(tmp1);
-# else
+#else
PULL16(tmp1);
acc = tmp1;
SET_NEG_ZERO16(tmp1);
-# endif
#endif
-
inst69_SYM /* ADC #imm */
GET_IMM_MEM();
ADC_INST();
inst6a_SYM /* ROR a */
-#ifdef ASM
-# ifdef ACC8
- extru psr,31,1,neg
- INC_KPC_1
- extru acc,30,7,zero
- dep neg,24,1,zero
- dep acc,31,1,psr /* set carry */
- b dispatch
- dep zero,31,8,acc
-# else
- extru psr,31,1,neg
- INC_KPC_1
- extru acc,30,15,zero
- dep neg,16,1,zero
- dep acc,31,1,psr /* set carry */
- b dispatch
- dep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
-# ifdef ACC8
+#ifdef ACC8
tmp1 = ((acc & 0xff) >> 1) + ((psr & 1) << 7);
SET_CARRY8((acc << 8));
acc = (acc & 0xff00) + (tmp1 & 0xff);
SET_NEG_ZERO8(tmp1 & 0xff);
-# else
+#else
tmp1 = (acc >> 1) + ((psr & 1) << 15);
SET_CARRY16((acc << 16));
acc = (tmp1 & 0xffff);
SET_NEG_ZERO16(acc);
-# endif
#endif
inst6b_SYM /* RTL */
-#ifdef ASM
- bl pull_24,link
- CYCLES_PLUS_1
-/* ret0 is new kpc-1 */
- copy ret0,kpc
- addi 1,ret0,scratch1
- b dispatch
- dep scratch1,31,16,kpc
-
-#else
CYCLES_PLUS_1;
PULL24(tmp1);
kpc = (tmp1 & 0xff0000) + ((tmp1 + 1) & 0xffff);
-#endif
inst6c_SYM /* JMP (abs) */
-#ifdef ASM
- ldb 1(scratch1),arg0
- CYCLES_PLUS_1
- ldb 2(scratch1),scratch1
- bl get_mem_long_16,link
- dep scratch1,23,8,arg0
-/* ret0 is addr to jump to */
- b dispatch
- dep ret0,31,16,kpc
-#else
GET_2BYTE_ARG;
CYCLES_PLUS_1;
GET_MEMORY16(arg, tmp1, 1);
kpc = (kpc & 0xff0000) + tmp1;
-#endif
inst6d_SYM /* ADC abs */
GET_ABS_RD();
@@ -1364,16 +682,7 @@ inst6f_SYM /* ADC long */
inst70_SYM /* BVS disp8 */
-#ifdef ASM
- COND_BR1
- bb,>= psr,25,inst70_2_SYM
- COND_BR2
-
-inst70_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8((psr & 0x40));
-#endif
inst71_SYM /* ADC (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -1388,15 +697,9 @@ inst73_SYM /* ADC (Disp8,s),y */
ADC_INST();
inst74_SYM /* STZ Dloc,x */
-#ifdef ASM
- ldb 1(scratch1),arg0
- GET_DLOC_X_WR();
- STZ_INST(1);
-#else
GET_1BYTE_ARG;
GET_DLOC_X_WR();
STZ_INST(1);
-#endif
inst75_SYM /* ADC Dloc,x */
GET_DLOC_X_RD();
@@ -1411,43 +714,14 @@ inst77_SYM /* ADC [Dloc],Y */
ADC_INST();
inst78_SYM /* SEI */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- depi 1,29,1,psr /* set int disable */
-#else
psr = psr | 4;
INC_KPC_1;
-#endif
inst79_SYM /* ADC abs,y */
GET_ABS_Y_RD();
ADC_INST();
inst7a_SYM /* PLY */
-#ifdef ASM
- INC_KPC_1
- bb,>= psr,27,inst7a_16bit_SYM
- nop
-
- bl pull_8,link
- CYCLES_PLUS_1
-
- extru ret0,31,8,zero
- extru ret0,24,1,neg
- b dispatch
- copy zero,yreg
-
-inst7a_16bit_SYM
- bl pull_16,link
- CYCLES_PLUS_1
-
- extru ret0,31,16,zero
- extru ret0,16,1,neg
- b dispatch
- copy zero,yreg
-
-#else
INC_KPC_1;
CYCLES_PLUS_1
if(psr & 0x10) {
@@ -1457,42 +731,19 @@ inst7a_16bit_SYM
PULL16(yreg);
SET_NEG_ZERO16(yreg);
}
-#endif
inst7b_SYM /* TDC */
-#ifdef ASM
- extru direct,31,16,zero
- copy direct,acc
- INC_KPC_1
- b dispatch
- extru direct,16,1,neg
-#else
INC_KPC_1;
acc = direct;
SET_NEG_ZERO16(direct);
-#endif
inst7c_SYM /* JMP (Abs,x) */
/* always access kbank, xreg cannot wrap into next bank */
-#ifdef ASM
- ldb 1(scratch1),ret0
- copy kpc,scratch2
- ldb 2(scratch1),scratch1
- dep xreg,31,16,scratch2
- CYCLES_PLUS_2
- dep scratch1,23,8,ret0
- add ret0,scratch2,arg0
- bl get_mem_long_16,link
- extru arg0,31,24,arg0
- b dispatch
- dep ret0,31,16,kpc
-#else
GET_2BYTE_ARG;
arg = (kpc & 0xff0000) + ((xreg + arg) & 0xffff);
CYCLES_PLUS_2;
GET_MEMORY16(arg, tmp1, 1);
kpc = (kpc & 0xff0000) + tmp1;
-#endif
inst7d_SYM /* ADC Abs,X */
GET_ABS_X_RD();
@@ -1506,35 +757,17 @@ inst7f_SYM /* ADC Long,X */
GET_LONG_X_RD();
ADC_INST();
-
inst80_SYM /* BRA */
-#ifdef ASM
- COND_BR1
- COND_BR2
-#else
BRANCH_DISP8(1);
-#endif
-
inst81_SYM /* STA (Dloc,X) */
GET_DLOC_X_IND_ADDR();
STA_INST(0);
inst82_SYM /* BRL disp16 */
-#ifdef ASM
- ldb 1(scratch1),ret0
- CYCLES_PLUS_1
- ldb 2(scratch1),scratch1
- addi 3,kpc,scratch2
- dep scratch1,23,8,ret0
- add ret0,scratch2,scratch2
- b dispatch
- dep scratch2,31,16,kpc
-#else
GET_2BYTE_ARG;
CYCLES_PLUS_1;
kpc = (kpc & 0xff0000) + ((kpc + 3 + arg) & 0xffff);
-#endif
inst83_SYM /* STA Disp8,S */
GET_DISP8_S_ADDR();
@@ -1544,7 +777,6 @@ inst84_SYM /* STY Dloc */
GET_DLOC_ADDR();
STY_INST(1);
-
inst85_SYM /* STA Dloc */
GET_DLOC_ADDR();
STA_INST(1);
@@ -1553,86 +785,30 @@ inst86_SYM /* STX Dloc */
GET_DLOC_ADDR();
STX_INST(1);
-
inst87_SYM /* STA [Dloc] */
GET_DLOC_L_IND_ADDR();
STA_INST(0);
inst88_SYM /* DEY */
-#ifdef ASM
- INC_KPC_1
- bb,< psr,27,inst88_8bit_SYM
- addi -1,yreg,yreg
-/* 16 bit */
- extru yreg,31,16,zero
- extru yreg,16,1,neg
- b dispatch
- copy zero,yreg
-
-inst88_8bit_SYM
- extru yreg,31,8,zero
- extru yreg,24,1,neg
- b dispatch
- copy zero,yreg
-#else
INC_KPC_1;
SET_INDEX_REG(yreg - 1, yreg);
-#endif
inst89_SYM /* BIT #imm */
-#ifdef ASM
- GET_IMM_MEM();
-# ifdef ACC8
-/* Immediate BIT does not set condition flags */
- and acc,ret0,zero
- b dispatch
- extru zero,31,8,zero
-# else
- and acc,ret0,zero
- b dispatch
- extru zero,31,16,zero
-# endif
-#else
GET_IMM_MEM();
-# ifdef ACC8
+#ifdef ACC8
zero = (acc & arg) & 0xff;
-# else
+#else
zero = (acc & arg) & 0xffff;
-# endif
#endif
inst8a_SYM /* TXA */
-#ifdef ASM
-# ifdef ACC8
- extru xreg,31,8,zero
- INC_KPC_1
- extru xreg,24,1,neg
- b dispatch
- dep zero,31,8,acc
-# else
- extru xreg,31,16,zero
- INC_KPC_1
- extru xreg,16,1,neg
- b dispatch
- zdep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
arg = xreg;
LDA_INST();
-#endif
inst8b_SYM /* PHB */
-#ifdef ASM
- ldil l%dispatch,link
- extru dbank,31,8,arg0
- INC_KPC_1
- b push_8
- ldo r%dispatch(link),link
-#else
INC_KPC_1;
PUSH8(dbank);
-#endif
inst8c_SYM /* STY abs */
GET_ABS_ADDR();
@@ -1653,17 +829,7 @@ inst8f_SYM /* STA long */
inst90_SYM /* BCC disp8 */
-#ifdef ASM
- COND_BR1
- bb,< psr,31,inst90_2_SYM
- COND_BR2
-
-inst90_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8((psr & 0x01) == 0);
-#endif
-
inst91_SYM /* STA (Dloc),y */
GET_DLOC_IND_Y_ADDR_FOR_WR();
@@ -1694,61 +860,24 @@ inst97_SYM /* STA [Dloc],Y */
STA_INST(0);
inst98_SYM /* TYA */
-#ifdef ASM
-# ifdef ACC8
- extru yreg,31,8,zero
- INC_KPC_1
- extru yreg,24,1,neg
- b dispatch
- dep zero,31,8,acc
-# else
- extru yreg,31,16,zero
- INC_KPC_1
- extru yreg,16,1,neg
- b dispatch
- zdep zero,31,16,acc
-# endif
-#else
INC_KPC_1;
arg = yreg;
LDA_INST();
-#endif
inst99_SYM /* STA abs,y */
GET_ABS_INDEX_ADDR_FOR_WR(yreg)
STA_INST(0);
inst9a_SYM /* TXS */
-#ifdef ASM
- copy xreg,stack
- extru,= psr,23,1,0
- depi 1,23,24,stack
- INC_KPC_1
- b dispatch
- nop
-#else
stack = xreg;
if(psr & 0x100) {
stack = 0x100 | (stack & 0xff);
}
INC_KPC_1;
-#endif
-
inst9b_SYM /* TXY */
-#ifdef ASM
- extru xreg,24,1,neg
- INC_KPC_1
- extru,<> psr,27,1,0 ;skip next if 8bit
- extru xreg,16,1,neg
- copy xreg,yreg
- b dispatch
- copy xreg,zero
-#else
SET_INDEX_REG(xreg, yreg);
INC_KPC_1;
-#endif
-
inst9c_SYM /* STZ Abs */
GET_ABS_ADDR();
@@ -1766,25 +895,7 @@ inst9f_SYM /* STA Long,X */
GET_LONG_X_ADDR_FOR_WR();
STA_INST(0);
-
insta0_SYM /* LDY #imm */
-#ifdef ASM
- INC_KPC_2
- bb,>= psr,27,insta0_16bit_SYM
- ldb 1(scratch1),zero
-
- extru zero,24,1,neg
- b dispatch
- copy zero,yreg
-insta0_16bit_SYM
- ldb 2(scratch1),scratch1
- INC_KPC_1
- CYCLES_PLUS_1
- extru scratch1,24,1,neg
- dep scratch1,23,8,zero
- b dispatch
- copy zero,yreg
-#else
INC_KPC_2;
if((psr & 0x10) == 0) {
GET_2BYTE_ARG;
@@ -1794,8 +905,6 @@ insta0_16bit_SYM
GET_1BYTE_ARG;
}
SET_INDEX_REG(arg, yreg);
-#endif
-
insta1_SYM /* LDA (Dloc,X) */
/* called with arg = val to LDA in */
@@ -1803,23 +912,6 @@ insta1_SYM /* LDA (Dloc,X) */
LDA_INST();
insta2_SYM /* LDX #imm */
-#ifdef ASM
- ldb 1(scratch1),zero
- bb,>= psr,27,insta2_16bit_SYM
- INC_KPC_2;
-
- extru zero,24,1,neg
- b dispatch
- copy zero,xreg
-insta2_16bit_SYM
- ldb 2(scratch1),scratch1
- INC_KPC_1
- CYCLES_PLUS_1
- extru scratch1,24,1,neg
- dep scratch1,23,8,zero
- b dispatch
- copy zero,xreg
-#else
INC_KPC_2;
if((psr & 0x10) == 0) {
GET_2BYTE_ARG;
@@ -1829,7 +921,6 @@ insta2_16bit_SYM
GET_1BYTE_ARG;
}
SET_INDEX_REG(arg, xreg);
-#endif
insta3_SYM /* LDA Disp8,S */
/* called with arg = val to LDA in */
@@ -1837,14 +928,7 @@ insta3_SYM /* LDA Disp8,S */
LDA_INST();
insta4_SYM /* LDY Dloc */
-#ifdef ASM
- ldb 1(scratch1),arg0
- GET_DLOC_WR()
- b get_yreg_from_mem
- nop
-#else
C_LDY_DLOC();
-#endif
insta5_SYM /* LDA Dloc */
/* called with arg = val to LDA in */
@@ -1852,102 +936,39 @@ insta5_SYM /* LDA Dloc */
LDA_INST();
insta6_SYM /* LDX Dloc */
-#ifdef ASM
- ldb 1(scratch1),arg0
- GET_DLOC_WR()
- b get_xreg_from_mem
- nop
-#else
C_LDX_DLOC();
-#endif
insta7_SYM /* LDA [Dloc] */
GET_DLOC_L_IND_RD();
LDA_INST();
insta8_SYM /* TAY */
-#ifdef ASM
- INC_KPC_1
- bb,>= psr,27,insta8_16bit_SYM
- extru acc,31,8,zero
-
- extru acc,24,1,neg
- b dispatch
- copy zero,yreg
-
-insta8_16bit_SYM
- extru acc,31,16,zero
- extru acc,16,1,neg
- b dispatch
- copy zero,yreg
-#else
INC_KPC_1;
SET_INDEX_REG(acc, yreg);
-#endif
insta9_SYM /* LDA #imm */
GET_IMM_MEM();
LDA_INST();
instaa_SYM /* TAX */
-#ifdef ASM
- INC_KPC_1
- bb,>= psr,27,instaa_16bit_SYM
- extru acc,31,8,zero
-
- extru acc,24,1,neg
- b dispatch
- copy zero,xreg
-
-instaa_16bit_SYM
- extru acc,31,16,zero
- extru acc,16,1,neg
- b dispatch
- copy zero,xreg
-#else
INC_KPC_1;
SET_INDEX_REG(acc, xreg);
-#endif
instab_SYM /* PLB */
-#ifdef ASM
- INC_KPC_1
- bl pull_8,link
- CYCLES_PLUS_1
-
- extru ret0,31,8,zero
- extru ret0,24,1,neg
- b dispatch
- copy zero,dbank
-#else
INC_KPC_1;
CYCLES_PLUS_1
PULL8(dbank);
SET_NEG_ZERO8(dbank);
-#endif
instac_SYM /* LDY abs */
-#ifdef ASM
- GET_ABS_ADDR()
- b get_yreg_from_mem
- nop
-#else
C_LDY_ABS();
-#endif
-
instad_SYM /* LDA abs */
GET_ABS_RD();
LDA_INST();
instae_SYM /* LDX abs */
-#ifdef ASM
- GET_ABS_ADDR()
- b get_xreg_from_mem
- nop
-#else
C_LDX_ABS();
-#endif
instaf_SYM /* LDA long */
GET_LONG_RD();
@@ -1955,16 +976,7 @@ instaf_SYM /* LDA long */
instb0_SYM /* BCS disp8 */
-#ifdef ASM
- COND_BR1
- bb,>= psr,31,instb0_2_SYM
- COND_BR2
-
-instb0_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8((psr & 0x01));
-#endif
instb1_SYM /* LDA (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -1979,106 +991,44 @@ instb3_SYM /* LDA (Disp8,s),y */
LDA_INST();
instb4_SYM /* LDY Dloc,x */
-#ifdef ASM
- ldb 1(scratch1),arg0
- GET_DLOC_X_WR();
- b get_yreg_from_mem
- nop
-#else
C_LDY_DLOC_X();
-#endif
instb5_SYM /* LDA Dloc,x */
GET_DLOC_X_RD();
LDA_INST();
instb6_SYM /* LDX Dloc,y */
-#ifdef ASM
- ldb 1(scratch1),arg0
- GET_DLOC_Y_WR();
- b get_xreg_from_mem
- nop
-#else
C_LDX_DLOC_Y();
-#endif
instb7_SYM /* LDA [Dloc],Y */
GET_DLOC_L_IND_Y_RD();
LDA_INST();
instb8_SYM /* CLV */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- depi 0,25,1,psr /* clear overflow */
-#else
psr = psr & ~0x40;
INC_KPC_1;
-#endif
instb9_SYM /* LDA abs,y */
GET_ABS_Y_RD();
LDA_INST();
instba_SYM /* TSX */
-#ifdef ASM
- INC_KPC_1
- bb,>= psr,27,instba_16bit_SYM
- extru stack,31,8,zero
-
- extru stack,24,1,neg
- b dispatch
- copy zero,xreg
-instba_16bit_SYM
- copy stack,zero
- extru stack,16,1,neg
- b dispatch
- copy zero,xreg
-#else
INC_KPC_1;
SET_INDEX_REG(stack, xreg);
-#endif
instbb_SYM /* TYX */
-#ifdef ASM
- INC_KPC_1
- bb,>= psr,27,instbb_16bit_SYM
- copy yreg,xreg
-
-/* 8 bit */
- extru yreg,24,1,neg
- b dispatch
- copy yreg,zero
-instbb_16bit_SYM
- extru yreg,16,1,neg
- b dispatch
- copy yreg,zero
-#else
INC_KPC_1;
SET_INDEX_REG(yreg, xreg);
-#endif
instbc_SYM /* LDY Abs,X */
-#ifdef ASM
- GET_ABS_INDEX_ADDR_FOR_RD(xreg)
- b get_yreg_from_mem
- nop
-#else
C_LDY_ABS_X();
-#endif
instbd_SYM /* LDA Abs,X */
GET_ABS_X_RD();
LDA_INST();
instbe_SYM /* LDX Abs,y */
-#ifdef ASM
- GET_ABS_INDEX_ADDR_FOR_RD(yreg)
- b get_xreg_from_mem
- nop
-#else
C_LDX_ABS_Y();
-#endif
instbf_SYM /* LDA Long,X */
GET_LONG_X_RD();
@@ -2086,21 +1036,7 @@ instbf_SYM /* LDA Long,X */
instc0_SYM /* CPY #imm */
-#ifdef ASM
- ldb 1(scratch1),ret0
- bb,>= psr,27,instc0_16bit_SYM
- INC_KPC_2;
- CMP_INDEX_REG_MEAT8(yreg)
-instc0_16bit_SYM
- ldb 2(scratch1),scratch1
- CYCLES_PLUS_1
- INC_KPC_1
- dep scratch1,23,8,ret0
- CMP_INDEX_REG_MEAT16(yreg)
-#else
C_CPY_IMM();
-#endif
-
instc1_SYM /* CMP (Dloc,X) */
/* called with arg = val to CMP in */
@@ -2108,23 +1044,6 @@ instc1_SYM /* CMP (Dloc,X) */
CMP_INST();
instc2_SYM /* REP #imm */
-#ifdef ASM
- ldb 1(scratch1),ret0
- extru psr,27,2,arg0 /* save old x & m */
- INC_KPC_2;
- dep neg,24,1,psr
- CYCLES_PLUS_1
- depi 0,30,1,psr
- comiclr,<> 0,zero,0
- depi 1,30,1,psr
- andcm psr,ret0,ret0
- ldi 0,zero
- extru,<> ret0,30,1,0
- ldi 1,zero
- dep ret0,31,8,psr
- b update_system_state
- extru ret0,24,1,neg
-#else
GET_1BYTE_ARG;
tmp2 = psr;
CYCLES_PLUS_1;
@@ -2134,8 +1053,6 @@ instc2_SYM /* REP #imm */
zero = !(psr & 2);
neg = (psr >> 7) & 1;
UPDATE_PSR(psr, tmp2);
-#endif
-
instc3_SYM /* CMP Disp8,S */
/* called with arg = val to CMP in */
@@ -2143,13 +1060,7 @@ instc3_SYM /* CMP Disp8,S */
CMP_INST();
instc4_SYM /* CPY Dloc */
-#ifdef ASM
- GET_DLOC_ADDR()
- CMP_INDEX_REG_LOAD(instc4_16bit_SYM, yreg)
-#else
C_CPY_DLOC();
-#endif
-
instc5_SYM /* CMP Dloc */
GET_DLOC_RD();
@@ -2164,73 +1075,27 @@ instc7_SYM /* CMP [Dloc] */
CMP_INST();
instc8_SYM /* INY */
-#ifdef ASM
- INC_KPC_1
- addi 1,yreg,yreg
- bb,>= psr,27,instc8_16bit_SYM
- extru yreg,31,8,zero
-
- extru yreg,24,1,neg
- b dispatch
- copy zero,yreg
-
-instc8_16bit_SYM
- extru yreg,31,16,zero
- extru yreg,16,1,neg
- b dispatch
- copy zero,yreg
-#else
INC_KPC_1;
SET_INDEX_REG(yreg + 1, yreg);
-#endif
instc9_SYM /* CMP #imm */
GET_IMM_MEM();
CMP_INST();
instca_SYM /* DEX */
-#ifdef ASM
- INC_KPC_1
- addi -1,xreg,xreg
- bb,>= psr,27,instca_16bit_SYM
- extru xreg,31,8,zero
-
- extru xreg,24,1,neg
- b dispatch
- copy zero,xreg
-
-instca_16bit_SYM
- extru xreg,31,16,zero
- extru xreg,16,1,neg
- b dispatch
- copy zero,xreg
-#else
INC_KPC_1;
SET_INDEX_REG(xreg - 1, xreg);
-#endif
instcb_SYM /* WAI */
-#ifdef ASM
- ldil l%g_wait_pending,scratch1
- CYCLES_FINISH
- ldi 1,scratch2
- b dispatch
- stw scratch2,r%g_wait_pending(scratch1)
-#else
- g_wait_pending = 1;
- CYCLES_FINISH
-#endif
+ if(g_irq_pending) {
+ g_wait_pending = 0;
+ INC_KPC_1;
+ } else {
+ g_wait_pending = 1;
+ }
instcc_SYM /* CPY abs */
-#ifdef ASM
- GET_ABS_ADDR()
- CMP_INDEX_REG_LOAD(instcc_16bit_SYM, yreg)
-#else
C_CPY_ABS();
-#endif
-
-
-
instcd_SYM /* CMP abs */
GET_ABS_RD();
@@ -2240,23 +1105,12 @@ instce_SYM /* DEC abs */
GET_ABS_RD();
DEC_INST(0);
-
instcf_SYM /* CMP long */
GET_LONG_RD();
CMP_INST();
-
instd0_SYM /* BNE disp8 */
-#ifdef ASM
- COND_BR1
- comib,= 0,zero,instd0_2_SYM
- COND_BR2
-
-instd0_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8(zero != 0);
-#endif
instd1_SYM /* CMP (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -2271,22 +1125,10 @@ instd3_SYM /* CMP (Disp8,s),y */
CMP_INST();
instd4_SYM /* PEI Dloc */
-#ifdef ASM
- GET_DLOC_ADDR()
- bl get_mem_long_16,link
- CYCLES_PLUS_1
-
-/* push ret0 */
- extru ret0,31,16,arg0
- ldil l%dispatch,link
- b push_16_unsafe
- ldo r%dispatch(link),link
-#else
GET_DLOC_ADDR()
GET_MEMORY16(arg, arg, 1);
CYCLES_PLUS_1;
PUSH16_UNSAFE(arg);
-#endif
instd5_SYM /* CMP Dloc,x */
GET_DLOC_X_RD();
@@ -2301,68 +1143,29 @@ instd7_SYM /* CMP [Dloc],Y */
CMP_INST();
instd8_SYM /* CLD */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- depi 0,28,1,psr /* clear decimal */
-#else
psr = psr & (~0x8);
INC_KPC_1;
-#endif
instd9_SYM /* CMP abs,y */
GET_ABS_Y_RD();
CMP_INST();
instda_SYM /* PHX */
-#ifdef ASM
- INC_KPC_1
- bb,>= psr,27,instda_16bit_SYM
- ldil l%dispatch,link
-
- extru xreg,31,8,arg0
- b push_8
- ldo r%dispatch(link),link
-
-instda_16bit_SYM
- extru xreg,31,16,arg0
- b push_16
- ldo r%dispatch(link),link
-#else
INC_KPC_1;
if(psr & 0x10) {
PUSH8(xreg);
} else {
PUSH16(xreg);
}
-#endif
instdb_SYM /* STP */
-#ifdef ASM
- ldb 1(scratch1),ret0
- CYCLES_PLUS_1
- b dispatch_done
- depi RET_STP,3,4,ret0
-#else
CYCLES_FINISH
FINISH(RET_STP, 0);
-#endif
instdc_SYM /* JML (Abs) */
-#ifdef ASM
- ldb 1(scratch1),arg0
- ldb 2(scratch1),scratch1
- CYCLES_PLUS_1
- bl get_mem_long_24,link
- dep scratch1,23,8,arg0
-
- b dispatch
- copy ret0,kpc
-#else
GET_2BYTE_ARG;
CYCLES_PLUS_1;
GET_MEMORY24(arg, kpc, 1);
-#endif
instdd_SYM /* CMP Abs,X */
GET_ABS_X_RD();
@@ -2378,20 +1181,7 @@ instdf_SYM /* CMP Long,X */
inste0_SYM /* CPX #imm */
-#ifdef ASM
- ldb 1(scratch1),ret0
- bb,>= psr,27,inste0_16bit_SYM
- INC_KPC_2;
- CMP_INDEX_REG_MEAT8(xreg)
-inste0_16bit_SYM
- ldb 2(scratch1),scratch1
- CYCLES_PLUS_1
- INC_KPC_1
- dep scratch1,23,8,ret0
- CMP_INDEX_REG_MEAT16(xreg)
-#else
C_CPX_IMM();
-#endif
inste1_SYM /* SBC (Dloc,X) */
@@ -2400,23 +1190,6 @@ inste1_SYM /* SBC (Dloc,X) */
SBC_INST();
inste2_SYM /* SEP #imm */
-#ifdef ASM
- ldb 1(scratch1),ret0
- extru psr,27,2,arg0 /* save old x & m */
- INC_KPC_2;
- dep neg,24,1,psr
- CYCLES_PLUS_1
- depi 0,30,1,psr
- comiclr,<> 0,zero,0
- depi 1,30,1,psr
- or psr,ret0,ret0
- ldi 0,zero
- extru,<> ret0,30,1,0
- ldi 1,zero
- dep ret0,31,8,psr
- b update_system_state
- extru ret0,24,1,neg
-#else
GET_1BYTE_ARG;
tmp2 = psr;
CYCLES_PLUS_1;
@@ -2426,8 +1199,6 @@ inste2_SYM /* SEP #imm */
zero = !(psr & 2);
neg = (psr >> 7) & 1;
UPDATE_PSR(psr, tmp2);
-#endif
-
inste3_SYM /* SBC Disp8,S */
/* called with arg = val to SBC in */
@@ -2435,13 +1206,7 @@ inste3_SYM /* SBC Disp8,S */
SBC_INST();
inste4_SYM /* CPX Dloc */
-#ifdef ASM
- GET_DLOC_ADDR()
- CMP_INDEX_REG_LOAD(inste4_16bit_SYM, xreg)
-#else
C_CPX_DLOC();
-#endif
-
inste5_SYM /* SBC Dloc */
/* called with arg = val to SBC in */
@@ -2457,67 +1222,25 @@ inste7_SYM /* SBC [Dloc] */
SBC_INST();
inste8_SYM /* INX */
-#ifdef ASM
- INC_KPC_1
- addi 1,xreg,xreg
- bb,>= psr,27,inste8_16bit_SYM
- extru xreg,31,8,zero
-
- extru xreg,24,1,neg
- b dispatch
- copy zero,xreg
-
-inste8_16bit_SYM
- extru xreg,31,16,zero
- extru xreg,16,1,neg
- b dispatch
- copy zero,xreg
-#else
INC_KPC_1;
SET_INDEX_REG(xreg + 1, xreg);
-#endif
inste9_SYM /* SBC #imm */
GET_IMM_MEM();
SBC_INST();
instea_SYM /* NOP */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- nop
-#else
INC_KPC_1;
-#endif
insteb_SYM /* XBA */
-#ifdef ASM
- extru acc,16,1,neg /* Z and N reflect status of low 8 */
- CYCLES_PLUS_1 /* bits of final acc value! */
- copy acc,scratch1 /* regardlessof ACC 8 or 16 bit */
- extru acc,23,8,acc
- INC_KPC_1
- copy acc,zero
- b dispatch
- dep scratch1,23,8,acc
-#else
tmp1 = acc & 0xff;
CYCLES_PLUS_1
acc = (tmp1 << 8) + (acc >> 8);
INC_KPC_1;
SET_NEG_ZERO8(acc & 0xff);
-#endif
instec_SYM /* CPX abs */
-#ifdef ASM
- GET_ABS_ADDR()
- CMP_INDEX_REG_LOAD(instec_16bit_SYM, xreg)
-#else
C_CPX_ABS();
-#endif
-
-
-
insted_SYM /* SBC abs */
GET_ABS_RD();
@@ -2527,23 +1250,12 @@ instee_SYM /* INC abs */
GET_ABS_RD();
INC_INST(0);
-
instef_SYM /* SBC long */
GET_LONG_RD();
SBC_INST();
-
instf0_SYM /* BEQ disp8 */
-#ifdef ASM
- COND_BR1
- comib,<> 0,zero,instf0_2_SYM
- COND_BR2
-
-instf0_2_SYM
- COND_BR_UNTAKEN
-#else
BRANCH_DISP8(zero == 0);
-#endif
instf1_SYM /* SBC (Dloc),y */
GET_DLOC_IND_Y_RD();
@@ -2558,21 +1270,10 @@ instf3_SYM /* SBC (Disp8,s),y */
SBC_INST();
instf4_SYM /* PEA Abs */
-#ifdef ASM
- ldb 1(scratch1),arg0
- ldil l%dispatch,link
- ldb 2(scratch1),scratch1
- INC_KPC_3
- CYCLES_PLUS_1
- ldo r%dispatch(link),link
- b push_16_unsafe
- dep scratch1,23,8,arg0
-#else
GET_2BYTE_ARG;
CYCLES_PLUS_1;
INC_KPC_3;
PUSH16_UNSAFE(arg);
-#endif
instf5_SYM /* SBC Dloc,x */
GET_DLOC_X_RD();
@@ -2587,43 +1288,14 @@ instf7_SYM /* SBC [Dloc],Y */
SBC_INST();
instf8_SYM /* SED */
-#ifdef ASM
- INC_KPC_1
- b dispatch
- depi 1,28,1,psr /* set decimal */
-#else
INC_KPC_1;
psr |= 0x8;
-#endif
instf9_SYM /* SBC abs,y */
GET_ABS_Y_RD();
SBC_INST();
instfa_SYM /* PLX */
-#ifdef ASM
- bb,< psr,27,instfa_8bit_SYM
- CYCLES_PLUS_1
-
- INC_KPC_1
- bl pull_16,link
- nop
-
- extru ret0,31,16,zero
- extru ret0,16,1,neg
- b dispatch
- copy zero,xreg
-
-instfa_8bit_SYM
- INC_KPC_1
- bl pull_8,link
- nop
-
- extru ret0,31,8,zero
- extru ret0,24,1,neg
- b dispatch
- copy zero,xreg
-#else
INC_KPC_1;
CYCLES_PLUS_1;
if(psr & 0x10) {
@@ -2633,42 +1305,14 @@ instfa_8bit_SYM
PULL16(xreg);
SET_NEG_ZERO16(xreg);
}
-#endif
instfb_SYM /* XCE */
-#ifdef ASM
- extru psr,27,2,arg0 /* save old x & m */
- INC_KPC_1
- extru psr,23,1,scratch1 /* e bit */
- dep psr,23,1,psr /* copy carry to e bit */
- b update_system_state
- dep scratch1,31,1,psr /* copy e bit to carry */
-#else
tmp2 = psr;
INC_KPC_1;
psr = (tmp2 & 0xfe) | ((tmp2 & 1) << 8) | ((tmp2 >> 8) & 1);
UPDATE_PSR(psr, tmp2);
-#endif
instfc_SYM /* JSR (Abs,X) */
-#ifdef ASM
- ldb 1(scratch1),ret0
- extru kpc,15,8,scratch2
- ldb 2(scratch1),scratch1
- dep scratch2,15,16,ret0
- INC_KPC_2;
- dep scratch1,23,8,ret0
- add xreg,ret0,arg0
- bl get_mem_long_16,link
- extru arg0,31,24,arg0
-
- CYCLES_PLUS_2
- extru kpc,31,16,arg0
- ldil l%dispatch,link
- dep ret0,31,16,kpc
- b push_16_unsafe
- ldo r%dispatch(link),link
-#else
GET_2BYTE_ARG;
INC_KPC_2;
tmp1 = kpc;
@@ -2677,7 +1321,6 @@ instfc_SYM /* JSR (Abs,X) */
kpc = (kpc & 0xff0000) + tmp2;
CYCLES_PLUS_2
PUSH16_UNSAFE(tmp1);
-#endif
instfd_SYM /* SBC Abs,X */
GET_ABS_X_RD();
diff --git a/src/rawnet/CMakeLists.txt b/src/rawnet/CMakeLists.txt
new file mode 100644
index 0000000..a38b88b
--- /dev/null
+++ b/src/rawnet/CMakeLists.txt
@@ -0,0 +1,28 @@
+
+if(WIN32)
+ set(rawnetarch rawnetarch_win32.c)
+elseif(APPLE)
+ set(rawnetarch rawnetarch_vmnet_helper.c)
+ #set(rawnetarch rawnetarch_unix.c)
+elseif(UNIX)
+ set(rawnetarch rawnetarch_unix.c)
+endif()
+
+add_library(rawnet cs8900.c rawnet.c rawnetsupp.c rawnetarch.c ${rawnetarch})
+
+target_compile_definitions(rawnet PUBLIC HAVE_RAWNET)
+target_compile_definitions(rawnet PRIVATE CS8900_DEBUG RAWNET_DEBUG_FRAMES)
+
+target_compile_options(rawnet PRIVATE -g)
+
+if(WIN32)
+ target_link_libraries(rawnet ws2_32) # winsock2
+elseif(APPLE)
+ #target_link_libraries(rawnet PRIVATE pcap)
+ #target_link_libraries(rawnet PRIVATE "-framework vmnet")
+ add_executable(vmnet_helper vmnet_helper.c)
+ target_link_libraries(vmnet_helper PRIVATE "-framework vmnet")
+
+elseif(UNIX)
+ target_link_libraries(rawnet PRIVATE pcap)
+endif()
\ No newline at end of file
diff --git a/src/rawnet/Networking.txt b/src/rawnet/Networking.txt
new file mode 100644
index 0000000..084797c
--- /dev/null
+++ b/src/rawnet/Networking.txt
@@ -0,0 +1,35 @@
+Networking
+----------
+
+GS+ can emulate an Uthernet (the original) card in slot 3. Marinetti is supported with the Uthernet Link Layer. Version 1.0.2 or newer is recommended.
+
+Configuration:
+
+In the settings menu, select Ethernet Card Configuration.
+
+Make sure Uthernet Card in Slot 3 is set to On.
+
+Select the Interface menu to choose the selected interface from a menu.
+
+Win32:
+
+Ethernet support uses Winpcap or its modern successor, npcap. You need to install them.
+
+Winpcap/npcap require a hardwired ethernet connection in promiscuous mode -- they work by tapping into the ethernet stream.
+
+Interface names are not particularly meaningful. Sorry. Run `getmac /v` from cmd.exe to get a human friendly name for the interface device.
+
+In marinetti, hardcode the ip address, gateway, and dns servers.
+
+OS X:
+
+Ethernet support uses the vmnet framework. This provides a virtual ethernet device, dhcp server, and dns server, all bridged to the Macintosh's network.
+
+Unfortunately, vmnet requires root permissions or a codesigning entitlment which may only valid for applications through the Mac App Store.
+
+In marinetti, use DHCP.
+
+Linux:
+
+Ethernet support uses the tap ethernet device. This require setting up the device and bridging it to your local network.
+
diff --git a/src/rawnet/cs8900.c b/src/rawnet/cs8900.c
new file mode 100644
index 0000000..616f9a4
--- /dev/null
+++ b/src/rawnet/cs8900.c
@@ -0,0 +1,1675 @@
+/*
+ * cs8900.c - CS8900 Ethernet Core
+ *
+ * Written by
+ * Spiro Trikaliotis
+ * Christian Vogelgsang
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+//#include "vice.h"
+
+#ifdef HAVE_RAWNET
+
+#include
+#include
+#include
+#include
+//#ifdef DOS_TFE
+//#include /* FIXME: remove? */
+//#endif
+
+//#include "archdep.h"
+#include "cs8900.h"
+// #include "crc32.h"
+// #include "lib.h"
+// #include "log.h"
+// #include "monitor.h"
+#include "rawnetarch.h"
+#include "rawnetsupp.h"
+// #include "resources.h"
+// #include "snapshot.h"
+// #include "types.h"
+// #include "util.h"
+
+/* FIXME:
+ - add register dump
+*/
+
+/* warn illegal behaviour */
+/* #define CS8900_DEBUG_WARN_REG 1 */ /* warn about invalid register accesses */
+/* #define CS8900_DEBUG_WARN_RXTX 1 */ /* warn about invalid rx or tx conditions */
+
+/** #define CS8900_DEBUG_INIT 1 **/
+/** #define CS8900_DEBUG_LOAD 1 **/ /* enable to see tfe port reads */
+/** #define CS8900_DEBUG_STORE 1 **/ /* enable to see tfe port writes */
+/** #define CS8900_DEBUG_REGISTERS 1 **/ /* enable to see CS8900a register I/O */
+/** #define CS8900_DEBUG_IGNORE_RXEVENT 1 **/ /* enable to ignore RXEVENT in DEBUG_REGISTERS */
+/** #define CS8900_DEBUG_RXTX_STATE 1 **/ /* enable to see tranceiver state changes */
+/** #define CS8900_DEBUG_RXTX_DATA 1 **/ /* enable to see data in/out flow */
+/** #define RAWNET_DEBUG_FRAMES 1 **/ /* enable to see arch frame send/recv - might be defined in rawnetarch.h ! */
+
+/* ------------------------------------------------------------------------- */
+/* variables needed */
+
+//static log_t cs8900_log = LOG_ERR;
+
+/* status which received packages to accept
+ This is used in cs8900_should_accept().
+*/
+static uint8_t cs8900_ia_mac[6] = { 0, 0, 0, 0, 0, 0 };
+
+/* remember the value of the hash mask */
+static uint32_t cs8900_hash_mask[2];
+
+/* reveiver setup */
+static uint16_t cs8900_recv_control = 0; /* copy of CC_RXCTL (contains all bits below) */
+static int cs8900_recv_broadcast = 0; /* broadcast */
+static int cs8900_recv_mac = 0; /* individual address (IA) */
+static int cs8900_recv_multicast = 0; /* multicast if address passes the hash filter */
+static int cs8900_recv_correct = 0; /* accept correct frames */
+static int cs8900_recv_promiscuous = 0; /* promiscuous mode */
+static int cs8900_recv_hashfilter = 0; /* accept if IA passes the hash filter */
+
+/* TFE registers */
+/* these are the 8 16-bit-ports for "I/O space configuration"
+ (see 4.10 on page 75 of cs8900a-4.pdf, the cs8900a data sheet)
+
+ REMARK: The TFE operates the cs8900a in IO space configuration, as
+ it generates I/OW and I/OR signals.
+*/
+#define CS8900_COUNT_IO_REGISTER 0x10 /* we have 16 I/O register */
+
+static uint8_t *cs8900 = NULL;
+/*
+ RW: RXTXDATA = DE00/DE01
+ RW: RXTXDATA2 = DE02/DE03 (for 32-bit-operation)
+ -W: TXCMD = DE04/DE05 (TxCMD, Transmit Command) mapped to PP + 0144 (Reg. 9, Sec. 4.4, page 46)
+ -W: TXLENGTH = DE06/DE07 (TxLenght, Transmit Length) mapped to PP + 0146
+ R-: INTSTQUEUE = DE08/DE09 (Interrupt Status Queue) mapped to PP + 0120 (ISQ, Sec. 5.1, page 78)
+ RW: PP_PTR = DE0A/DE0B (PacketPage Pointer) (see. page 75p: Read -011.---- ----.----)
+ RW: PP_DATA0 = DE0C/DE0D (PacketPage Data (Port 0))
+ RW: PP_DATA1 = DE0E/DE0F (PacketPage Data (Port 1)) (for 32 bit only)
+*/
+
+#define CS8900_ADDR_RXTXDATA 0x00 /* RW */
+#define CS8900_ADDR_RXTXDATA2 0x02 /* RW 32 bit only! */
+#define CS8900_ADDR_TXCMD 0x04 /* -W Maps to PP+0144 */
+#define CS8900_ADDR_TXLENGTH 0x06 /* -W Maps to PP+0146 */
+#define CS8900_ADDR_INTSTQUEUE 0x08 /* R- Interrupt status queue, maps to PP + 0120 */
+#define CS8900_ADDR_PP_PTR 0x0a /* RW PacketPage Pointer */
+#define CS8900_ADDR_PP_DATA 0x0c /* RW PacketPage Data, Port 0 */
+#define CS8900_ADDR_PP_DATA2 0x0e /* RW PacketPage Data, Port 1 - 32 bit only */
+
+/* Makros for reading and writing the visible TFE register: */
+#define GET_CS8900_8(_xxx_) (assert(_xxx_ < CS8900_COUNT_IO_REGISTER), cs8900[_xxx_])
+
+#define SET_CS8900_8(_xxx_, _val_) \
+ do { \
+ assert(_xxx_ < CS8900_COUNT_IO_REGISTER); \
+ cs8900[_xxx_] = (_val_) & 0xff; \
+ } while (0)
+
+#define GET_CS8900_16(_xxx_) (assert(_xxx_ < CS8900_COUNT_IO_REGISTER), cs8900[_xxx_] | (cs8900[_xxx_ + 1] << 8))
+
+#define SET_CS8900_16(_xxx_, _val_) \
+ do { \
+ assert(_xxx_ < CS8900_COUNT_IO_REGISTER); \
+ cs8900[_xxx_] = (_val_) & 0xff; \
+ cs8900[_xxx_ + 1] = (_val_ >> 8) & 0xff; \
+ } while (0)
+
+/* The PacketPage register */
+/* note: The locations 0 to MAX_PACKETPAGE_ARRAY-1 are handled in this array. */
+
+#define MAX_PACKETPAGE_ARRAY 0x1000 /* 4 KB */
+
+static uint8_t *cs8900_packetpage = NULL;
+
+static uint16_t cs8900_packetpage_ptr = 0;
+
+/* Makros for reading and writing the PacketPage register: */
+
+#define GET_PP_8(_xxx_) (assert(_xxx_ < MAX_PACKETPAGE_ARRAY), cs8900_packetpage[_xxx_])
+
+#define GET_PP_16(_xxx_) (assert(_xxx_ < MAX_PACKETPAGE_ARRAY), assert((_xxx_ & 1) == 0), ((uint16_t)cs8900_packetpage[_xxx_]) | ((uint16_t)cs8900_packetpage[_xxx_ + 1] << 8))
+
+#define GET_PP_32(_xxx_) \
+ (assert(_xxx_ < MAX_PACKETPAGE_ARRAY), assert((_xxx_ & 3) == 0), \
+ (((long)cs8900_packetpage[_xxx_])) | (((long)cs8900_packetpage[_xxx_ + 1]) << 8) | (((long)cs8900_packetpage[_xxx_ + 2]) << 16) | (((long)cs8900_packetpage[_xxx_ + 3]) << 24))
+
+#define SET_PP_8(_xxx_, _val_) \
+ do { \
+ assert(_xxx_ < MAX_PACKETPAGE_ARRAY); \
+ cs8900_packetpage[_xxx_] = (_val_) & 0xFF; \
+ } while (0)
+
+#define SET_PP_16(_xxx_, _val_) \
+ do { \
+ assert(_xxx_ < MAX_PACKETPAGE_ARRAY); \
+ assert((_xxx_ & 1) == 0), \
+ cs8900_packetpage[_xxx_] = (_val_) & 0xFF; \
+ cs8900_packetpage[_xxx_ + 1] = (_val_ >> 8) & 0xFF; \
+ } while (0)
+
+#define SET_PP_32(_xxx_, _val_) \
+ do { \
+ assert(_xxx_ < MAX_PACKETPAGE_ARRAY); \
+ assert((_xxx_ & 3) == 0), \
+ cs8900_packetpage[_xxx_] = (_val_) & 0xFF; \
+ cs8900_packetpage[_xxx_ + 1] = (_val_ >> 8) & 0xFF; \
+ cs8900_packetpage[_xxx_ + 2] = (_val_ >> 16) & 0xFF; \
+ cs8900_packetpage[_xxx_ + 3] = (_val_ >> 24) & 0xFF; \
+ } while (0)
+
+/* The packetpage register: see p. 39f */
+#define CS8900_PP_ADDR_PRODUCTID 0x0000 /* R- - 4.3., p. 41 */
+#define CS8900_PP_ADDR_IOBASE 0x0020 /* i RW - 4.3., p. 41 - 4.7., p. 72 */
+#define CS8900_PP_ADDR_INTNO 0x0022 /* i RW - 3.2., p. 17 - 4.3., p. 41 */
+#define CS8900_PP_ADDR_DMA_CHAN 0x0024 /* i RW - 3.2., p. 17 - 4.3., p. 41 */
+#define CS8900_PP_ADDR_DMA_SOF 0x0026 /* ? R- - 4.3., p. 41 - 5.4., p. 89 */
+#define CS8900_PP_ADDR_DMA_FC 0x0028 /* ? R- - 4.3., p. 41, "Receive DMA" */
+#define CS8900_PP_ADDR_RXDMA_BC 0x002a /* ? R- - 4.3., p. 41 - 5.4., p. 89 */
+#define CS8900_PP_ADDR_MEMBASE 0x002c /* i RW - 4.3., p. 41 - 4.9., p. 73 */
+#define CS8900_PP_ADDR_BPROM_BASE 0x0030 /* i RW - 3.6., p. 24 - 4.3., p. 41 */
+#define CS8900_PP_ADDR_BPROM_MASK 0x0034 /* i RW - 3.6., p. 24 - 4.3., p. 41 */
+
+/* 0x0038 - 0x003F: reserved */
+#define CS8900_PP_ADDR_EEPROM_CMD 0x0040 /* i RW - 3.5., p. 23 - 4.3., p. 41 */
+#define CS8900_PP_ADDR_EEPROM_DATA 0x0042 /* i RW - 3.5., p. 23 - 4.3., p. 41 */
+
+/* 0x0044 - 0x004F: reserved */
+#define CS8900_PP_ADDR_REC_FRAME_BC 0x0050 /* RW - 4.3., p. 41 - 5.2.9., p. 86 */
+
+/* 0x0052 - 0x00FF: reserved */
+#define CS8900_PP_ADDR_CONF_CTRL 0x0100 /* - RW - 4.4., p. 46; see below */
+#define CS8900_PP_ADDR_STATUS_EVENT 0x0120 /* - R- - 4.4., p. 46; see below */
+
+/* 0x0140 - 0x0143: reserved */
+#define CS8900_PP_ADDR_TXCMD 0x0144 /* # -W - 4.5., p. 70 - 5.7., p. 98 */
+#define CS8900_PP_ADDR_TXLENGTH 0x0146 /* # -W - 4.5., p. 70 - 5.7., p. 98 */
+
+/* 0x0148 - 0x014F: reserved */
+#define CS8900_PP_ADDR_LOG_ADDR_FILTER 0x0150 /* RW - 4.6., p. 71 - 5.3., p. 86 */
+#define CS8900_PP_ADDR_MAC_ADDR 0x0158 /* # RW - 4.6., p. 71 - 5.3., p. 86 */
+
+/* 0x015E - 0x03FF: reserved */
+#define CS8900_PP_ADDR_RXSTATUS 0x0400 /* R- - 4.7., p. 72 - 5.2., p. 78 */
+#define CS8900_PP_ADDR_RXLENGTH 0x0402 /* R- - 4.7., p. 72 - 5.2., p. 78 */
+#define CS8900_PP_ADDR_RX_FRAMELOC 0x0404 /* R- - 4.7., p. 72 - 5.2., p. 78 */
+
+/* here, the received frame is stored */
+#define CS8900_PP_ADDR_TX_FRAMELOC 0x0A00 /* -W - 4.7., p. 72 - 5.7., p. 98 */
+
+/* here, the frame to transmit is stored */
+#define CS8900_PP_ADDR_END 0x1000 /* memory to TFE_PP_ADDR_END-1 is used */
+
+/* TFE_PP_ADDR_CONF_CTRL is subdivided: */
+#define CS8900_PP_ADDR_CC_RXCFG 0x0102 /* # RW - 4.4.6., p. 52 - 0003 */
+#define CS8900_PP_ADDR_CC_RXCTL 0x0104 /* # RW - 4.4.8., p. 54 - 0005 */
+#define CS8900_PP_ADDR_CC_TXCFG 0x0106 /* RW - 4.4.9., p. 55 - 0007 */
+#define CS8900_PP_ADDR_CC_TXCMD 0x0108 /* R- - 4.4.11., p. 57 - 0009 */
+#define CS8900_PP_ADDR_CC_BUFCFG 0x010A /* RW - 4.4.12., p. 58 - 000B */
+#define CS8900_PP_ADDR_CC_LINECTL 0x0112 /* # RW - 4.4.16., p. 62 - 0013 */
+#define CS8900_PP_ADDR_CC_SELFCTL 0x0114 /* RW - 4.4.18., p. 64 - 0015 */
+#define CS8900_PP_ADDR_CC_BUSCTL 0x0116 /* RW - 4.4.20., p. 66 - 0017 */
+#define CS8900_PP_ADDR_CC_TESTCTL 0x0118 /* RW - 4.4.22., p. 68 - 0019 */
+
+/* CS8900_PP_ADDR_STATUS_EVENT is subdivided: */
+#define CS8900_PP_ADDR_SE_ISQ 0x0120 /* R- - 4.4.5., p. 51 - 0000 */
+#define CS8900_PP_ADDR_SE_RXEVENT 0x0124 /* # R- - 4.4.7., p. 53 - 0004 */
+#define CS8900_PP_ADDR_SE_TXEVENT 0x0128 /* R- - 4.4.10., p. 56 - 0008 */
+#define CS8900_PP_ADDR_SE_BUFEVENT 0x012C /* R- - 4.4.13., p. 59 - 000C */
+#define CS8900_PP_ADDR_SE_RXMISS 0x0130 /* R- - 4.4.14., p. 60 - 0010 */
+#define CS8900_PP_ADDR_SE_TXCOL 0x0132 /* R- - 4.4.15., p. 61 - 0012 */
+#define CS8900_PP_ADDR_SE_LINEST 0x0134 /* R- - 4.4.17., p. 63 - 0014 */
+#define CS8900_PP_ADDR_SE_SELFST 0x0136 /* R- - 4.4.19., p. 65 - 0016 */
+#define CS8900_PP_ADDR_SE_BUSST 0x0138 /* # R- - 4.4.21., p. 67 - 0018 */
+#define CS8900_PP_ADDR_SE_TDR 0x013C /* R- - 4.4.23., p. 69 - 001C */
+
+/* ------------------------------------------------------------------------- */
+/* more variables needed */
+
+static uint16_t tx_buffer = CS8900_PP_ADDR_TX_FRAMELOC;
+static uint16_t rx_buffer = CS8900_PP_ADDR_RXSTATUS;
+
+static uint16_t tx_count = 0;
+static uint16_t rx_count = 0;
+static uint16_t tx_length = 0;
+static uint16_t rx_length = 0;
+
+#define CS8900_TX_IDLE 0
+#define CS8900_TX_GOT_CMD 1
+#define CS8900_TX_GOT_LEN 2
+#define CS8900_TX_READ_BUSST 3
+
+#define CS8900_RX_IDLE 0
+#define CS8900_RX_GOT_FRAME 1
+
+/* tranceiver state */
+static int tx_state = CS8900_TX_IDLE;
+static int rx_state = CS8900_RX_IDLE;
+static int tx_enabled = 0;
+static int rx_enabled = 0;
+
+static int rxevent_read_mask = 3; /* set if L and/or H byte was read in RXEVENT? */
+
+/* ------------------------------------------------------------------------- */
+/* some parameter definitions */
+
+#define MAX_TXLENGTH 1518
+#define MIN_TXLENGTH 4
+
+#define MAX_RXLENGTH 1518
+#define MIN_RXLENGTH 64
+
+/* ------------------------------------------------------------------------- */
+/* debugging functions */
+
+#ifdef RAWNET_DEBUG_FRAMES
+
+#define MAXLEN_DEBUG 1600
+
+static int cs8900DebugMaxFrameLengthToDump = 150;
+
+static char *debug_outbuffer(const int length, const unsigned char * const buffer)
+{
+ int i;
+ static char outbuffer[MAXLEN_DEBUG * 4 + 1];
+ char *p = outbuffer;
+
+ assert(cs8900DebugMaxFrameLengthToDump <= MAXLEN_DEBUG);
+
+ *p = 0;
+
+ for (i = 0; i < cs8900DebugMaxFrameLengthToDump; i++) {
+ if (i >= length) {
+ break;
+ }
+ sprintf( p, "%02X%c", buffer[i], ((i + 1) % 16 == 0) ? '*' : (((i + 1) % 8 == 0) ? '-' : ' '));
+ p += 3;
+ }
+
+ return outbuffer;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* initialization and deinitialization functions */
+
+static void cs8900_set_tx_status(int ready, int error)
+{
+ uint16_t old_status = GET_PP_16(CS8900_PP_ADDR_SE_BUSST);
+
+ /* mask out TxBidErr and Rdy4TxNOW */
+ uint16_t new_status = old_status & ~0x180;
+ if (ready) {
+ new_status |= 0x100; /* set Rdy4TxNOW */
+ }
+ if (error) {
+ new_status |= 0x080; /* set TxBidErr */
+ }
+
+ if (new_status != old_status) {
+ SET_PP_16(CS8900_PP_ADDR_SE_BUSST, new_status);
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: set status Rdy4TxNOW=%d TxBidErr=%d", ready, error);
+#endif
+ }
+}
+
+static void cs8900_set_receiver(int enabled)
+{
+ rx_enabled = enabled;
+ rx_state = CS8900_RX_IDLE;
+
+ rxevent_read_mask = 3; /* was L or H byte read in RXEVENT? */
+}
+
+static void cs8900_set_transmitter(int enabled)
+{
+ tx_enabled = enabled;
+ tx_state = CS8900_TX_IDLE;
+
+ cs8900_set_tx_status(0, 0);
+}
+
+void cs8900_reset(void)
+{
+ int i;
+
+ assert(cs8900);
+ assert(cs8900_packetpage);
+
+ rawnet_arch_pre_reset();
+
+ /* initialize visible IO register and PacketPage registers */
+ memset(cs8900, 0, CS8900_COUNT_IO_REGISTER);
+ memset(cs8900_packetpage, 0, MAX_PACKETPAGE_ARRAY);
+
+ /* according to page 19 unless stated otherwise */
+ SET_PP_32(CS8900_PP_ADDR_PRODUCTID, 0x0900630E ); /* p.41: 0E630009 for Rev. D; reversed order! */
+ SET_PP_16(CS8900_PP_ADDR_IOBASE, 0x0300);
+ SET_PP_16(CS8900_PP_ADDR_INTNO, 0x0004); /* xxxx xxxx xxxx x100b */
+ SET_PP_16(CS8900_PP_ADDR_DMA_CHAN, 0x0003); /* xxxx xxxx xxxx xx11b */
+
+ /* according to descriptions of the registers, see definitions of
+ CS8900_PP_ADDR_CC_... and CS8900_PP_ADDR_SE_... above! */
+
+ SET_PP_16(CS8900_PP_ADDR_CC_RXCFG, 0x0003);
+ SET_PP_16(CS8900_PP_ADDR_CC_RXCTL, 0x0005);
+ SET_PP_16(CS8900_PP_ADDR_CC_TXCFG, 0x0007);
+ SET_PP_16(CS8900_PP_ADDR_CC_TXCMD, 0x0009);
+ SET_PP_16(CS8900_PP_ADDR_CC_BUFCFG, 0x000B);
+ SET_PP_16(CS8900_PP_ADDR_CC_LINECTL, 0x0013);
+ SET_PP_16(CS8900_PP_ADDR_CC_SELFCTL, 0x0015);
+ SET_PP_16(CS8900_PP_ADDR_CC_BUSCTL, 0x0017);
+ SET_PP_16(CS8900_PP_ADDR_CC_TESTCTL, 0x0019);
+
+ SET_PP_16(CS8900_PP_ADDR_SE_ISQ, 0x0000);
+ SET_PP_16(CS8900_PP_ADDR_SE_RXEVENT, 0x0004);
+ SET_PP_16(CS8900_PP_ADDR_SE_TXEVENT, 0x0008);
+ SET_PP_16(CS8900_PP_ADDR_SE_BUFEVENT, 0x000C);
+ SET_PP_16(CS8900_PP_ADDR_SE_RXMISS, 0x0010);
+ SET_PP_16(CS8900_PP_ADDR_SE_TXCOL, 0x0012);
+ /* according to specs the reset value is 0x0014, however we also set
+ bit 7 - Link OK
+ bit 9 - 10Base-T
+ bit 12 - Polarity OK
+ which makes 0x1294 ... because some software might check these and
+ expects them to be "Up".
+ FIXME: we should perhaps maintain these bits elsewhere
+ */
+ SET_PP_16(CS8900_PP_ADDR_SE_LINEST, 0x1294);
+ SET_PP_16(CS8900_PP_ADDR_SE_SELFST, 0x0016);
+ SET_PP_16(CS8900_PP_ADDR_SE_BUSST, 0x0018);
+ SET_PP_16(CS8900_PP_ADDR_SE_TDR, 0x001C);
+
+ SET_PP_16(CS8900_PP_ADDR_TXCMD, 0x0009);
+
+ /* 4.4.19 Self Status Register, p. 65
+ Important: set INITD (Bit 7) to signal device is ready */
+ SET_PP_16(CS8900_PP_ADDR_SE_SELFST, 0x0896);
+
+ cs8900_recv_control = GET_PP_16(CS8900_PP_ADDR_CC_RXCTL);
+
+ /* spec: mac address is undefined after reset.
+ real HW: keeps the last set address. */
+ for (i = 0; i < 6; i++) {
+ SET_PP_8(CS8900_PP_ADDR_MAC_ADDR + i, cs8900_ia_mac[i]);
+ }
+
+ /* reset state */
+ cs8900_set_transmitter(0);
+ cs8900_set_receiver(0);
+
+ rawnet_arch_post_reset();
+
+ log_message(cs8900_log, "CS8900a rev.D reset");
+}
+
+int cs8900_activate(const char *net_interface)
+{
+ assert(cs8900 == NULL);
+ assert(cs8900_packetpage == NULL);
+
+#ifdef CS8900_DEBUG
+ log_message(cs8900_log, "cs8900_activate().");
+#endif
+
+ /* allocate memory for visible IO register */
+ cs8900 = lib_malloc(CS8900_COUNT_IO_REGISTER);
+ if (cs8900 == NULL) {
+#ifdef CS8900_DEBUG_INIT
+ log_message(cs8900_log, "cs8900_activate: Allocating cs8900 failed.");
+#endif
+ return -1;
+ }
+
+ /* allocate memory for PacketPage register */
+ cs8900_packetpage = lib_malloc(MAX_PACKETPAGE_ARRAY);
+ if (cs8900_packetpage == NULL) {
+#ifdef CS8900_DEBUG_INIT
+ log_message(cs8900_log, "cs8900_activate: Allocating cs8900_packetpage failed.");
+#endif
+ lib_free(cs8900);
+ cs8900 = NULL;
+ return -1;
+ }
+
+#ifdef CS8900_DEBUG_INIT
+ log_message(cs8900_log, "cs8900_activate: Allocated memory successfully.");
+ log_message(cs8900_log, "\tcs8900 at $%08X, cs8900_packetpage at $%08X", cs8900, cs8900_packetpage);
+#endif
+
+ if (!rawnet_arch_activate(net_interface)) {
+ lib_free(cs8900_packetpage);
+ lib_free(cs8900);
+ cs8900 = NULL;
+ cs8900_packetpage = NULL;
+ return -2;
+ }
+
+ /* virtually reset the LAN chip */
+ cs8900_reset();
+ return 0;
+}
+
+int cs8900_deactivate(void)
+{
+#ifdef CS8900_DEBUG
+ log_message(cs8900_log, "cs8900_deactivate().");
+#endif
+
+ assert(cs8900 && cs8900_packetpage);
+
+ rawnet_arch_deactivate();
+
+ lib_free(cs8900);
+ cs8900 = NULL;
+ lib_free(cs8900_packetpage);
+ cs8900_packetpage = NULL;
+ return 0;
+}
+
+void cs8900_shutdown(void)
+{
+#ifdef CS8900_DEBUG
+ log_message(cs8900_log, "cs8900_shutdown().");
+#endif
+
+ assert((cs8900 && cs8900_packetpage) || (!cs8900 && !cs8900_packetpage));
+
+ if (cs8900) {
+#ifdef CS8900_DEBUG
+ log_message(cs8900_log, "...1");
+#endif
+ cs8900_deactivate();
+ }
+
+#ifdef CS8900_DEBUG
+ log_message(cs8900_log, "cs8900_shutdown() done.");
+#endif
+}
+
+int cs8900_init(void)
+{
+ //cs8900_log = log_open("CS8900");
+ if (!rawnet_arch_init()) {
+ return -1;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* reading and writing CS8900 register functions */
+
+/*
+These registers are currently fully or partially supported:
+
+CS8900_PP_ADDR_CC_RXCFG 0x0102 * # RW - 4.4.6., p. 52 - 0003 *
+CS8900_PP_ADDR_CC_RXCTL 0x0104 * # RW - 4.4.8., p. 54 - 0005 *
+CS8900_PP_ADDR_CC_LINECTL 0x0112 * # RW - 4.4.16., p. 62 - 0013 *
+CS8900_PP_ADDR_SE_RXEVENT 0x0124 * # R- - 4.4.7., p. 53 - 0004 *
+CS8900_PP_ADDR_SE_BUSST 0x0138 * # R- - 4.4.21., p. 67 - 0018 *
+CS8900_PP_ADDR_TXCMD 0x0144 * # -W - 4.5., p. 70 - 5.7., p. 98 *
+CS8900_PP_ADDR_TXLENGTH 0x0146 * # -W - 4.5., p. 70 - 5.7., p. 98 *
+CS8900_PP_ADDR_MAC_ADDR 0x0158 * # RW - 4.6., p. 71 - 5.3., p. 86 *
+ 0x015a
+ 0x015c
+*/
+
+#ifdef RAWNET_DEBUG_FRAMES
+#define return( _x_ ) \
+ { \
+ int retval = _x_; \
+ \
+ log_message(cs8900_log, "%s correct_mac=%u, broadcast=%u, multicast=%u, hashed=%u, hash_index=%u", \
+ (retval ? "+++ ACCEPTED" : "--- rejected"), *pcorrect_mac, *pbroadcast, *pmulticast, *phashed, *phash_index); \
+ return retval; \
+ }
+#endif
+
+/*
+ This is a helper for cs8900_receive() to determine if the received frame should be accepted
+ according to the settings.
+
+ This function is even allowed to be called in rawnetarch.c from rawnet_arch_receive()
+ (via rawnet_should_accept) if necessary, and must be registered using rawnet_set_should_accept_func,
+ which is the reason why its prototype is included in cs8900.h.
+*/
+int cs8900_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, int *pcorrect_mac, int *pbroadcast, int *pmulticast)
+{
+ int hashreg; /* Hash Register (for hash computation) */
+
+ assert(length >= 6); /* we need at least 6 octets since the DA has this length */
+
+ /* first of all, delete any status */
+ *phashed = 0;
+ *phash_index = 0;
+ *pcorrect_mac = 0;
+ *pbroadcast = 0;
+ *pmulticast = 0;
+
+#ifdef RAWNET_DEBUG_FRAMES
+ log_message(cs8900_log, "cs8900_should_accept called with %02X:%02X:%02X:%02X:%02X:%02X, length=%4u and buffer %s",
+ cs8900_ia_mac[0], cs8900_ia_mac[1], cs8900_ia_mac[2], cs8900_ia_mac[3], cs8900_ia_mac[4], cs8900_ia_mac[5], length, debug_outbuffer(length, buffer));
+#endif
+
+ if (buffer[0] == cs8900_ia_mac[0] && buffer[1] == cs8900_ia_mac[1] && buffer[2] == cs8900_ia_mac[2] && buffer[3] == cs8900_ia_mac[3] && buffer[4] == cs8900_ia_mac[4] && buffer[5] == cs8900_ia_mac[5]) {
+ /* this is our individual address (IA) */
+
+ *pcorrect_mac = 1;
+
+ /* if we don't want "correct MAC", we might have the chance
+ * that this address fits the hash index
+ */
+ if (cs8900_recv_mac || cs8900_recv_promiscuous) {
+ return(1);
+ }
+ }
+
+ if (buffer[0] == 0xFF && buffer[1] == 0xFF && buffer[2] == 0xFF && buffer[3] == 0xFF && buffer[4] == 0xFF && buffer[5] == 0xFF) {
+ /* this is a broadcast address */
+ *pbroadcast = 1;
+
+ /* broadcasts cannot be accepted by the hash filter */
+ return ((cs8900_recv_broadcast || cs8900_recv_promiscuous) ? 1 : 0);
+ }
+
+ /* now check if DA passes the hash filter */
+ hashreg = (~crc32_buf((char *)buffer, 6) >> 26) & 0x3F;
+
+ *phashed = (cs8900_hash_mask[(hashreg >= 32) ? 1 : 0] & (1 << (hashreg & 0x1F))) ? 1 : 0;
+ if (*phashed) {
+ *phash_index = hashreg;
+
+ if (buffer[0] & 0x80) {
+ /* we have a multicast address */
+ *pmulticast = 1;
+
+ /* if the multicast address fits into the hash filter,
+ * the hashed bit has to be clear
+ */
+ *phashed = 0;
+
+ return ((cs8900_recv_multicast || cs8900_recv_promiscuous) ? 1 : 0);
+ }
+ return ((cs8900_recv_hashfilter || cs8900_recv_promiscuous) ? 1 : 0);
+ }
+
+ return(cs8900_recv_promiscuous ? 1 : 0);
+}
+
+#ifdef RAWNET_DEBUG_FRAMES
+ #undef return
+#endif
+
+/* buffer - where to store a frame */
+/* &len - length of received frame */
+/* &hashed - set if the dest. address is accepted by the hash filter */
+/* &hash_index - hash table index if hashed == TRUE */
+/* &rx_ok - set if good CRC and valid length */
+/* &correct_mac - set if dest. address is exactly our IA */
+/* &broadcast - set if dest. address is a broadcast address */
+/* &crc_error - set if received frame had a CRC error */
+
+static uint16_t cs8900_receive(void)
+{
+ uint16_t ret_val = 0x0004;
+
+ uint8_t buffer[MAX_RXLENGTH];
+
+ int len;
+ int hashed;
+ int hash_index;
+ int rx_ok;
+ int correct_mac;
+ int broadcast;
+ int multicast = 0; /* avoid warning */
+ int crc_error;
+
+ int newframe;
+
+ int ready;
+
+ do {
+ len = MAX_RXLENGTH;
+
+ ready = 1; /* assume we will find a good frame */
+
+ newframe = rawnet_arch_receive(buffer, &len, &hashed, &hash_index, &rx_ok, &correct_mac, &broadcast, &crc_error);
+
+ assert((len & 1) == 0); /* length has to be even! */
+
+ if (newframe) {
+ if (hashed || correct_mac || broadcast) {
+ /* we already know the type of frame: Trust it! */
+#ifdef RAWNET_DEBUG_FRAMES
+ log_message( cs8900_log, "+++ cs8900_receive(): *** hashed=%u, correct_mac=%u, broadcast=%u", hashed, correct_mac, broadcast);
+#endif
+ } else {
+ /* determine ourself the type of frame */
+ if (!cs8900_should_accept(buffer, len, &hashed, &hash_index, &correct_mac, &broadcast, &multicast)) {
+ /* if we should not accept this frame, just do nothing
+ * now, look for another one */
+ ready = 0; /* try another frame */
+ continue;
+ }
+ }
+
+ /* we did receive a frame, return that status */
+ ret_val |= rx_ok ? 0x0100 : 0;
+ ret_val |= multicast ? 0x0200 : 0;
+
+ if (!multicast) {
+ ret_val |= hashed ? 0x0040 : 0;
+ }
+
+ if (hashed && rx_ok) {
+ /* we have the 2nd, special format with hash index: */
+ assert(hash_index < 64);
+ ret_val |= hash_index << 9;
+ } else {
+ /* we have the regular format */
+ ret_val |= correct_mac ? 0x0400 : 0;
+ ret_val |= broadcast ? 0x0800 : 0;
+ ret_val |= crc_error ? 0x1000 : 0;
+ ret_val |= (len < MIN_RXLENGTH) ? 0x2000 : 0;
+ ret_val |= (len > MAX_RXLENGTH) ? 0x4000 : 0;
+ }
+
+ /* discard any octets that are beyond the MAX_RXLEN */
+ if (len > MAX_RXLENGTH) {
+ len = MAX_RXLENGTH;
+ }
+
+ if (rx_ok) {
+ int i;
+
+ /* set relevant parts of the PP area to correct values */
+ SET_PP_16(CS8900_PP_ADDR_RXLENGTH, len);
+
+ for (i = 0; i < len; i++) {
+ SET_PP_8(CS8900_PP_ADDR_RX_FRAMELOC + i, buffer[i]);
+ }
+
+ /* set rx_buffer to where start reading *
+ * According to 4.10.9 (pp. 76-77), we start with RxStatus and RxLength!
+ */
+ rx_buffer = CS8900_PP_ADDR_RXSTATUS;
+ rx_length = len;
+ rx_count = 0;
+#ifdef CS8900_DEBUG_WARN_RXTX
+ if (rx_state != CS8900_RX_IDLE) {
+ log_message(cs8900_log, "WARNING! New frame overwrites pending one!");
+ }
+#endif
+ rx_state = CS8900_RX_GOT_FRAME;
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "RX: recvd frame (length=%04x,status=%04x)", rx_length, ret_val);
+#endif
+ }
+ }
+ } while (!ready);
+
+#ifdef RAWNET_DEBUG_FRAMES
+ if (ret_val != 0x0004) {
+ log_message( cs8900_log, "+++ cs8900_receive(): ret_val=%04X", ret_val);
+ }
+#endif
+
+ return ret_val;
+}
+
+/* ------------------------------------------------------------------------- */
+/* TX/RX buffer handling */
+
+static void cs8900_write_tx_buffer(uint8_t value, int odd_address)
+{
+ /* write tx data only if valid buffer is ready */
+ if (tx_state != CS8900_TX_READ_BUSST) {
+#ifdef CS8900_DEBUG_WARN_RXTX
+ log_message(cs8900_log, "WARNING! Ignoring TX Write without correct Transmit Condition! (odd=%d,value=%02x)", odd_address, value);
+#endif
+ /* ensure correct tx state (needed if transmit < 4 was started) */
+ cs8900_set_tx_status(0, 0);
+ } else {
+#ifdef CS8900_DEBUG_RXTX_STATE
+ if (tx_count == 0) {
+ log_message(cs8900_log, "TX: write frame (length=%04x)", tx_length);
+ }
+#endif
+
+ /* always write LH, LH... to tx buffer */
+ uint16_t addr = tx_buffer;
+ if (odd_address) {
+ addr++;
+ tx_buffer += 2;
+ }
+ tx_count++;
+ SET_PP_8(addr, value);
+
+#ifdef CS8900_DEBUG_RXTX_DATA
+ log_message(cs8900_log, "TX: %04x/%04x: %02x (buffer=%04x,odd=%d)", tx_count, tx_length, value, addr, odd_address);
+#endif
+
+ /* full frame transmitted? */
+ if (tx_count == tx_length) {
+#ifdef RAWNET_DEBUG_FRAMES
+ log_message(cs8900_log, "rawnet_arch_transmit() called with: length=%4u and buffer %s", tx_length, debug_outbuffer(tx_length, &cs8900_packetpage[CS8900_PP_ADDR_TX_FRAMELOC]));
+#endif
+
+ if (!tx_enabled) {
+#ifdef CS8900_DEBUG_WARN_RXTX
+ log_message(cs8900_log, "WARNING! Can't transmit frame (Transmitter is not enabled)!");
+#endif
+ } else {
+ /* send frame */
+ uint16_t txcmd = GET_PP_16(CS8900_PP_ADDR_CC_TXCMD);
+ rawnet_arch_transmit(
+ txcmd & 0x0100 ? 1 : 0, /* FORCE: Delete waiting frames in transmit buffer */
+ txcmd & 0x0200 ? 1 : 0, /* ONECOLL: Terminate after just one collision */
+ txcmd & 0x1000 ? 1 : 0, /* INHIBITCRC: Do not append CRC to the transmission */
+ txcmd & 0x2000 ? 1 : 0, /* TXPADDIS: Disable padding to 60/64 octets */
+ tx_length, &cs8900_packetpage[CS8900_PP_ADDR_TX_FRAMELOC]);
+ }
+
+ /* reset transmitter state */
+ tx_state = CS8900_TX_IDLE;
+
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: sent frame (length=%04x)", tx_length);
+#endif
+
+ /* reset tx status */
+ cs8900_set_tx_status(0, 0);
+ }
+ }
+}
+
+static uint8_t cs8900_read_rx_buffer(int odd_address)
+{
+ if (rx_state != CS8900_RX_GOT_FRAME) {
+#ifdef CS8900_DEBUG_WARN_RXTX
+ log_message(cs8900_log, "WARNING! RX Read without frame available! (odd=%d)", odd_address);
+#endif
+ /* always reads zero on HW */
+ return 0;
+ } else {
+ /*
+ According to the CS8900 spec, the handling is the following:
+ first read H, then L (RX_STATUS), then H, then L (RX_LENGTH).
+ Inside the RX frame data, we always get L then H, until the end is reached.
+
+ even odd
+ CS8900_PP_ADDR_RXSTATUS: - proceed
+ CS8900_PP_ADDR_RXLENGTH: - proceed
+ CS8900_PP_ADDR_RX_FRAMELOC: - -
+ CS8900_PP_ADDR_RX_FRAMELOC+2: proceed -
+ CS8900_PP_ADDR_RX_FRAMELOC+4: proceed -
+
+ */
+ uint16_t addr = odd_address ? 1 : 0;
+ uint8_t value;
+
+ /* read RXSTATUS or RX_LENGTH */
+ if (rx_count < 4) {
+ addr += rx_buffer;
+ value = GET_PP_8(addr);
+ rx_count++;
+
+ /* incr after RXSTATUS or RX_LENGTH even (L) read */
+ if (!odd_address) {
+ rx_buffer += 2;
+ }
+ } else {
+ /* read frame data */
+
+ /* incr before frame read (but not in first word) */
+ if ((rx_count >= 6) && (!odd_address)) {
+ rx_buffer += 2;
+ }
+
+ addr += rx_buffer;
+ value = GET_PP_8(addr);
+ rx_count++;
+ }
+
+#ifdef CS8900_DEBUG_RXTX_DATA
+ log_message(cs8900_log, "RX: %04x/%04x: %02x (buffer=%04x,odd=%d)", rx_count, rx_length + 4, value, addr, odd_address);
+#endif
+
+ /* check frame end */
+ if (rx_count >= rx_length + 4) {
+ /* reset receiver state to idle */
+ rx_state = CS8900_RX_IDLE;
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "RX: read frame (length=%04x)", rx_length);
+#endif
+ }
+ return value;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* handle side-effects of read and write operations */
+
+#define on_off_str(x) ((x) ? on_off[0] : on_off[1])
+
+/*
+ This is called *after* the relevant octets are written
+*/
+static void cs8900_sideeffects_write_pp(uint16_t ppaddress, int odd_address)
+{
+ const char *on_off[2] = { "on", "off" };
+ uint16_t content = GET_PP_16( ppaddress );
+
+ assert((ppaddress & 1) == 0);
+
+ switch (ppaddress) {
+ case CS8900_PP_ADDR_CC_RXCFG:
+ /* Skip_1 Flag: remove current (partial) tx frame and restore state */
+ if (content & 0x40) {
+ /* restore tx state */
+ if (tx_state != CS8900_TX_IDLE) {
+ tx_state = CS8900_TX_IDLE;
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: skipping current frame");
+#endif
+ }
+
+ /* reset transmitter */
+ cs8900_set_transmitter(tx_enabled);
+
+ /* this is an "act once" bit, thus restore it to zero. */
+ content &= ~0x40;
+ SET_PP_16(ppaddress, content);
+ }
+ break;
+ case CS8900_PP_ADDR_CC_RXCTL:
+ if (cs8900_recv_control != content) {
+ cs8900_recv_broadcast = content & 0x0800; /* broadcast */
+ cs8900_recv_mac = content & 0x0400; /* individual address (IA) */
+ cs8900_recv_multicast = content & 0x0200; /* multicast if address passes the hash filter */
+ cs8900_recv_correct = content & 0x0100; /* accept correct frames */
+ cs8900_recv_promiscuous = content & 0x0080; /* promiscuous mode */
+ cs8900_recv_hashfilter = content & 0x0040; /* accept if IA passes the hash filter */
+ cs8900_recv_control = content;
+
+ log_message(cs8900_log, "setup receiver: broadcast=%s mac=%s multicast=%s correct=%s promiscuous=%s hashfilter=%s",
+ on_off_str(cs8900_recv_broadcast), on_off_str(cs8900_recv_mac), on_off_str(cs8900_recv_multicast), on_off_str(cs8900_recv_correct), on_off_str(cs8900_recv_promiscuous), on_off_str(cs8900_recv_hashfilter));
+
+ rawnet_arch_recv_ctl(cs8900_recv_broadcast, cs8900_recv_mac, cs8900_recv_multicast, cs8900_recv_correct, cs8900_recv_promiscuous, cs8900_recv_hashfilter);
+ }
+ break;
+ case CS8900_PP_ADDR_CC_LINECTL:
+ {
+ int enable_tx = (content & 0x0080) == 0x0080;
+ int enable_rx = (content & 0x0040) == 0x0040;
+
+ if ((enable_tx != tx_enabled) || (enable_rx != rx_enabled)) {
+ rawnet_arch_line_ctl(enable_tx, enable_rx);
+ cs8900_set_transmitter(enable_tx);
+ cs8900_set_receiver(enable_rx);
+
+ log_message(cs8900_log, "line control: transmitter=%s receiver=%s", on_off_str(enable_tx), on_off_str(enable_rx));
+ }
+ }
+ break;
+ case CS8900_PP_ADDR_CC_SELFCTL:
+ {
+ /* reset chip? */
+ if ((content & 0x40) == 0x40) {
+ cs8900_reset();
+ }
+ }
+ break;
+ case CS8900_PP_ADDR_TXCMD:
+ {
+ if (odd_address) {
+ uint16_t txcommand = GET_PP_16(CS8900_PP_ADDR_TXCMD);
+
+ /* already transmitting? */
+ if (tx_state == CS8900_TX_READ_BUSST) {
+#ifdef CS8900_DEBUG_WARN_RXTX
+ log_message(cs8900_log, "WARNING! Early abort of transmitted frame");
+#endif
+ }
+
+ /* The transmit status command gets the last transmit command */
+ SET_PP_16(CS8900_PP_ADDR_CC_TXCMD, txcommand);
+
+ /* set transmit state */
+ tx_state = CS8900_TX_GOT_CMD;
+ cs8900_set_tx_status(0, 0);
+
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: COMMAND accepted (%04x)", txcommand);
+#endif
+ }
+ }
+ break;
+ case CS8900_PP_ADDR_TXLENGTH:
+ {
+ if (odd_address && (tx_state == CS8900_TX_GOT_CMD)) {
+ uint16_t txlength = GET_PP_16(CS8900_PP_ADDR_TXLENGTH);
+ uint16_t txcommand = GET_PP_16(CS8900_PP_ADDR_CC_TXCMD);
+
+ if (txlength < 4) {
+ /* frame to short */
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: LENGTH rejected - too short! (%04x)", txlength);
+#endif
+ /* mask space available but do not commit */
+ tx_state = CS8900_TX_IDLE;
+ cs8900_set_tx_status(1, 0);
+ } else if ((txlength > MAX_TXLENGTH) || ((txlength > MAX_TXLENGTH - 4) && (!(txcommand & 0x1000)))) {
+ tx_state = CS8900_TX_IDLE;
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: LENGTH rejected - too long! (%04x)", txlength);
+#endif
+ /* txlength too big, mark an error */
+ cs8900_set_tx_status(0, 1);
+ } else {
+ /* make sure we put the octets to transmit at the right place */
+ tx_buffer = CS8900_PP_ADDR_TX_FRAMELOC;
+ tx_count = 0;
+ tx_length = txlength;
+ tx_state = CS8900_TX_GOT_LEN;
+
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: LENGTH accepted (%04x)", txlength);
+#endif
+ /* all right, signal that we're ready for the next frame */
+ cs8900_set_tx_status(1, 0);
+ }
+ }
+ }
+ break;
+ case CS8900_PP_ADDR_LOG_ADDR_FILTER:
+ case CS8900_PP_ADDR_LOG_ADDR_FILTER + 2:
+ case CS8900_PP_ADDR_LOG_ADDR_FILTER + 4:
+ case CS8900_PP_ADDR_LOG_ADDR_FILTER + 6:
+ {
+ unsigned int pos = 8 * (ppaddress - CS8900_PP_ADDR_LOG_ADDR_FILTER + odd_address);
+ uint32_t *p = (pos < 32) ? &cs8900_hash_mask[0] : &cs8900_hash_mask[1];
+
+ *p &= ~(0xFF << pos); /* clear out relevant bits */
+ *p |= GET_PP_8(ppaddress + odd_address) << pos;
+
+ rawnet_arch_set_hashfilter(cs8900_hash_mask);
+
+#if 0
+ if (odd_address && (ppaddress == CS8900_PP_ADDR_LOG_ADDR_FILTER + 6)) {
+ log_message(cs8900_log, "set hash filter: %02x:%02x:%02x:%02x:%02x:%02x",
+ cs8900_hash_mask[0], cs8900_hash_mask[1], cs8900_hash_mask[2], cs8900_hash_mask[3], cs8900_hash_mask[4], cs8900_hash_mask[5]);
+ }
+#endif
+ }
+ break;
+ case CS8900_PP_ADDR_MAC_ADDR:
+ case CS8900_PP_ADDR_MAC_ADDR + 2:
+ case CS8900_PP_ADDR_MAC_ADDR + 4:
+ /* the MAC address has been changed */
+ cs8900_ia_mac[ppaddress - CS8900_PP_ADDR_MAC_ADDR + odd_address] = GET_PP_8(ppaddress + odd_address);
+ rawnet_arch_set_mac(cs8900_ia_mac);
+ if (odd_address && (ppaddress == CS8900_PP_ADDR_MAC_ADDR + 4)) {
+ log_message(cs8900_log, "set MAC address: %02x:%02x:%02x:%02x:%02x:%02x",
+ cs8900_ia_mac[0], cs8900_ia_mac[1], cs8900_ia_mac[2], cs8900_ia_mac[3], cs8900_ia_mac[4], cs8900_ia_mac[5]);
+ }
+ break;
+ }
+}
+#undef on_off_str
+
+/*
+ This is called *before* the relevant octets are read
+*/
+static void cs8900_sideeffects_read_pp(uint16_t ppaddress, int odd_address)
+{
+ switch (ppaddress) {
+ case CS8900_PP_ADDR_SE_RXEVENT:
+ /* reading this before all octets of the frame are read
+ performs an "implied skip" */
+ {
+ int access_mask = (odd_address) ? 1 : 2;
+ /* update the status register only if the full word of the last
+ status was read! unfortunately different access patterns are
+ possible: either the status is read LH, LH, LH...
+ or HL, HL, HL, or even L, L, L or H, H, H */
+ if ((access_mask & rxevent_read_mask) != 0) {
+ /* receiver is not enabled */
+ if (!rx_enabled) {
+#ifdef CS8900_DEBUG_WARN_RXTX
+ log_message(cs8900_log, "WARNING! Can't receive any frame (Receiver is not enabled)!");
+#endif
+ } else {
+ /* perform frame reception */
+ uint16_t ret_val = cs8900_receive();
+
+ /* RXSTATUS and RXEVENT are the same, except that RXSTATUS buffers
+ the old value while RXEVENT sets a new value whenever it is called
+ */
+ SET_PP_16(CS8900_PP_ADDR_RXSTATUS, ret_val);
+ SET_PP_16(CS8900_PP_ADDR_SE_RXEVENT, ret_val);
+ }
+ /* reset read mask of (possible) other access */
+ rxevent_read_mask = access_mask;
+ } else {
+ /* add access bit to mask */
+ rxevent_read_mask |= access_mask;
+ }
+ }
+ break;
+ case CS8900_PP_ADDR_SE_BUSST:
+ if (odd_address) {
+ /* read busst before transmit condition is fullfilled */
+ if (tx_state == CS8900_TX_GOT_LEN) {
+ uint16_t bus_status = GET_PP_16(CS8900_PP_ADDR_SE_BUSST);
+
+ /* check Rdy4TXNow flag */
+ if ((bus_status & 0x100) == 0x100) {
+ tx_state = CS8900_TX_READ_BUSST;
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: Ready4TXNow set! (%04x)", bus_status);
+#endif
+ } else {
+#ifdef CS8900_DEBUG_RXTX_STATE
+ log_message(cs8900_log, "TX: waiting for Ready4TXNow! (%04x)", bus_status);
+#endif
+ }
+ }
+ }
+ break;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* read/write from packet page register */
+
+/* read a register from packet page */
+static uint16_t cs8900_read_register(uint16_t ppaddress)
+{
+ uint16_t value = GET_PP_16(ppaddress);
+
+ /* --- check the register address --- */
+ if (ppaddress < 0x100) {
+ /* reserved range reads 0x0300 on real HW */
+ if ((ppaddress >= 0x0004) && (ppaddress < 0x0020)) {
+ return 0x0300;
+ }
+ } else if (ppaddress < 0x120) {
+ /* --- read control register range --- */
+ uint16_t regNum = ppaddress - 0x100;
+
+ regNum &= ~1;
+ regNum++;
+#ifdef CS8900_DEBUG_REGISTERS
+ log_message(cs8900_log, "Read Control Register %04x: %04x (reg=%02x)", ppaddress, value, regNum);
+#endif
+
+ /* reserved register? */
+ if ((regNum == 0x01) || (regNum == 0x11) || (regNum > 0x19)) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read reserved Control Register %04x (reg=%02x)", ppaddress, regNum);
+#endif
+ /* real HW returns 0x0300 in reserved register range */
+ return 0x0300;
+ }
+
+ /* make sure internal address is always valid */
+ assert((value & 0x3f) == regNum);
+ } else if (ppaddress < 0x140) {
+ /* --- read status register range --- */
+ uint16_t regNum = ppaddress - 0x120;
+
+ regNum &= ~1;
+#ifdef CS8900_DEBUG_REGISTERS
+#ifdef CS8900_DEBUG_IGNORE_RXEVENT
+ if (regNum != 4) /* do not show RXEVENT */
+#endif
+ log_message(cs8900_log, "Read Status Register %04x: %04x (reg=%02x)", ppaddress, value, regNum);
+#endif
+
+ /* reserved register? */
+ if ((regNum == 0x02) || (regNum == 0x06) || (regNum == 0x0a) || (regNum == 0x0e) || (regNum == 0x1a) || (regNum == 0x1e)) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read reserved Status Register %04x (reg=%02x)", ppaddress, regNum);
+#endif
+ /* real HW returns 0x0300 in reserved register range */
+ return 0x0300;
+ }
+
+ /* make sure internal address is always valid */
+ assert((value & 0x3f) == regNum);
+ } else if (ppaddress < 0x150) {
+ /* --- read transmit register range --- */
+ if (ppaddress == 0x144) {
+ /* make sure internal address is always valid */
+ assert((value & 0x3f) == 0x09);
+#ifdef CS8900_DEBUG_REGISTERS
+ log_message(cs8900_log, "Read TX Cmd Register %04x: %04x", ppaddress, value);
+#endif
+ } else if (ppaddress == 0x146) {
+#ifdef CS8900_DEBUG_REGISTERS
+ log_message(cs8900_log, "Read TX Len Register %04x: %04x", ppaddress, value);
+#endif
+ } else {
+ /* reserved range */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read reserved Initiate Transmit Register %04x", ppaddress);
+#endif
+ /* real HW returns 0x0300 in reserved register range */
+ return 0x0300;
+ }
+ } else if (ppaddress < 0x160) {
+ /* --- read address filter register range --- */
+ /* reserved range */
+ if (ppaddress >= 0x15e) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read reserved Address Filter Register %04x", ppaddress);
+#endif
+ /* real HW returns 0x0300 in reserved register range */
+ return 0x0300;
+ }
+ } else if (ppaddress < 0x400) {
+ /* --- reserved range below 0x400 ---
+ returns 0x300 on real HW
+ */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read reserved Register %04x", ppaddress);
+#endif
+ return 0x0300;
+ } else if (ppaddress < 0xa00) {
+ /* --- range from 0x400 .. 0x9ff --- RX Frame */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read from RX Buffer Range %04x", ppaddress);
+#endif
+ return 0x0000;
+ } else {
+ /* --- range from 0xa00 .. 0xfff --- TX Frame */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Read from TX Buffer Range %04x", ppaddress);
+#endif
+ return 0x0000;
+ }
+
+ /* actually read from pp memory */
+ return value;
+}
+
+static void cs8900_write_register(uint16_t ppaddress, uint16_t value)
+{
+ /* --- write bus interface register range --- */
+ if (ppaddress < 0x100) {
+ int ignore = 0;
+
+ if (ppaddress < 0x20) {
+ ignore = 1;
+ } else if ((ppaddress >= 0x26) && (ppaddress < 0x2c)) {
+ ignore = 1;
+ } else if (ppaddress == 0x38) {
+ ignore = 1;
+ } else if (ppaddress >= 0x44) {
+ ignore = 1;
+ }
+ if (ignore) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ignoring write to read only/reserved Bus Interface Register %04x", ppaddress);
+#endif
+ return;
+ }
+ } else if (ppaddress < 0x120) {
+ /* --- write to control register range --- */
+ uint16_t regNum = ppaddress - 0x100;
+
+ regNum &= ~1;
+ regNum += 1;
+ /* validate internal address */
+ if ((value & 0x3f) != regNum) {
+ /* fix internal address */
+ value &= ~0x3f;
+ value |= regNum;
+ }
+#ifdef CS8900_DEBUG_REGISTERS
+ log_message(cs8900_log, "Write Control Register %04x: %04x (reg=%02x)", ppaddress, value, regNum);
+#endif
+
+ /* invalid register? -> ignore! */
+ if ((regNum == 0x01) || (regNum == 0x11) || (regNum > 0x19)) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ignoring write to reserved Control Register %04x (reg=%02x)", ppaddress, regNum);
+#endif
+ return;
+ }
+ } else if (ppaddress < 0x140) {
+ /* --- write to status register range --- */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ignoring write to read-only Status Register %04x", ppaddress);
+#endif
+ return;
+ } else if (ppaddress < 0x150) {
+ /* --- write to initiate transmit register range --- */
+ /* check tx_cmd register */
+ if (ppaddress == 0x144) {
+ /* validate internal address */
+ if ((value & 0x3f) != 0x09) {
+ /* fix internal address */
+ value &= ~0x3f;
+ value |= 0x09;
+ }
+ /* mask out reserved bits */
+ value &= 0x33ff;
+#ifdef CS8900_DEBUG_REGISTERS
+ log_message(cs8900_log, "Write TX Cmd Register %04x: %04x", ppaddress, value);
+#endif
+ } else if (ppaddress == 0x146) {
+ /* check tx_length register */
+ /* HW always masks 0x0fff */
+ value &= 0x0fff;
+#ifdef CS8900_DEBUG_REGISTERS
+ log_message(cs8900_log, "Write TX Len Register %04x: %04x", ppaddress, value);
+#endif
+ } else if ((ppaddress < 0x144) || (ppaddress > 0x147)) {
+ /* reserved range */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ignoring write to reserved Initiate Transmit Register %04x", ppaddress);
+#endif
+ return;
+ }
+ } else if (ppaddress < 0x160) {
+ /* --- write to address filter register range --- */
+ /* reserved range */
+ if (ppaddress >= 0x15e) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ingoring write to reserved Address Filter Register %04x", ppaddress);
+#endif
+ return;
+ }
+ } else if (ppaddress < 0x400) {
+ /* --- ignore write outside --- */
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ingoring write to reserved Register %04x", ppaddress);
+#endif
+ return;
+ } else if (ppaddress < 0xa00) {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ignoring write to RX Buffer Range %04x", ppaddress);
+#endif
+ return;
+ } else {
+#ifdef CS8900_DEBUG_WARN_REG
+ log_message(cs8900_log, "WARNING! Ignoring write to TX Buffer Range %04x", ppaddress);
+#endif
+ return;
+ }
+
+ /* actually set value */
+ SET_PP_16(ppaddress, value);
+}
+
+#define PP_PTR_AUTO_INCR_FLAG 0x8000 /* auto increment flag in package pointer */
+#define PP_PTR_FLAG_MASK 0xf000 /* is always : x y 1 1 (with x=auto incr) */
+#define PP_PTR_ADDR_MASK 0x0fff /* address portion of packet page pointer */
+
+static void cs8900_auto_incr_pp_ptr(void)
+{
+ /* perform auto increment of packet page pointer */
+ if ((cs8900_packetpage_ptr & PP_PTR_AUTO_INCR_FLAG) == PP_PTR_AUTO_INCR_FLAG) {
+ /* pointer is always increment by one on real HW */
+ uint16_t ptr = cs8900_packetpage_ptr & PP_PTR_ADDR_MASK;
+ uint16_t flags = cs8900_packetpage_ptr & PP_PTR_FLAG_MASK;
+
+ ptr++;
+ cs8900_packetpage_ptr = ptr | flags;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* read/write CS8900 registers from VICE */
+
+#define LO_uint8_t(x) (uint8_t)((x) & 0xff)
+#define HI_uint8_t(x) (uint8_t)(((x) >> 8) & 0xff)
+#define LOHI_uint16_t(x, y) ((uint16_t)(x) | (((uint16_t)(y)) << 8 ))
+
+/* ----- read byte from I/O range in VICE ----- */
+uint8_t cs8900_read(uint16_t io_address)
+{
+ uint8_t retval, lo, hi;
+ uint16_t word_value;
+ uint16_t reg_base;
+
+ assert(cs8900);
+ assert(cs8900_packetpage);
+ assert(io_address < 0x10);
+
+ /* register base addr */
+ reg_base = io_address & ~1;
+
+ /* RX register is special as it reads from RX buffer directly */
+ if ((reg_base == CS8900_ADDR_RXTXDATA) || (reg_base == CS8900_ADDR_RXTXDATA2)) {
+ return cs8900_read_rx_buffer(io_address & 0x01);
+ }
+
+ /* read packet page pointer */
+ if (reg_base == CS8900_ADDR_PP_PTR) {
+ word_value = cs8900_packetpage_ptr;
+ } else {
+ /* read a register from packet page */
+ uint16_t ppaddress = 0;
+
+ /* determine read addr in packet page */
+ switch (reg_base) {
+ /* PP_DATA2 behaves like PP_DATA on real HW
+ both show the contents at the page pointer */
+ case CS8900_ADDR_PP_DATA:
+ case CS8900_ADDR_PP_DATA2:
+ /* mask and align address of packet pointer */
+ ppaddress = cs8900_packetpage_ptr & PP_PTR_ADDR_MASK;
+ ppaddress &= ~1;
+ /* if flags match then auto incr pointer */
+ cs8900_auto_incr_pp_ptr();
+ break;
+ case CS8900_ADDR_INTSTQUEUE:
+ ppaddress = CS8900_PP_ADDR_SE_ISQ;
+ break;
+ case CS8900_ADDR_TXCMD:
+ ppaddress = CS8900_PP_ADDR_TXCMD;
+ break;
+ case CS8900_ADDR_TXLENGTH:
+ ppaddress = CS8900_PP_ADDR_TXLENGTH;
+ break;
+ default:
+ /* invalid! */
+ assert(0);
+ break;
+ }
+
+ /* do side effects before access */
+ cs8900_sideeffects_read_pp(ppaddress, io_address & 1);
+
+ /* read register value */
+ word_value = cs8900_read_register(ppaddress);
+
+#ifdef CS8900_DEBUG_LOAD
+ log_message(cs8900_log, "reading PP Ptr: $%04X => $%04X.", ppaddress, word_value);
+#endif
+ }
+
+ /* extract return value from word_value */
+ lo = LO_uint8_t(word_value);
+ hi = HI_uint8_t(word_value);
+ if ((io_address & 1) == 0) {
+ /* low byte on even address */
+ retval = lo;
+ } else {
+ /* high byte on odd address */
+ retval = hi;
+ }
+
+#ifdef CS8900_DEBUG_LOAD
+ log_message(cs8900_log, "read [$%02X] => $%02X.", io_address, retval);
+#endif
+
+ /* update _word_ value in register bank */
+ cs8900[reg_base] = lo;
+ cs8900[reg_base + 1] = hi;
+
+ return retval;
+}
+
+/* ----- peek byte without side effects from I/O range in VICE ----- */
+uint8_t cs8900_peek(uint16_t io_address)
+{
+ uint8_t retval, lo, hi;
+ uint16_t word_value;
+ uint16_t reg_base;
+
+ assert(cs8900);
+ assert(cs8900_packetpage);
+ assert(io_address < 0x10);
+
+ /* register base addr */
+ reg_base = io_address & ~1;
+
+ /* RX register is special as it reads from RX buffer directly */
+ if ((reg_base == CS8900_ADDR_RXTXDATA) || (reg_base == CS8900_ADDR_RXTXDATA2)) {
+ return 0; /* FIXME: peek rx buffer */
+ }
+
+ /* read packet page pointer */
+ if (reg_base == CS8900_ADDR_PP_PTR) {
+ word_value = cs8900_packetpage_ptr;
+ } else {
+ /* read a register from packet page */
+ uint16_t ppaddress = 0;
+
+ /* determine read addr in packet page */
+ switch (reg_base) {
+ /* PP_DATA2 behaves like PP_DATA on real HW
+ both show the contents at the page pointer */
+ case CS8900_ADDR_PP_DATA:
+ case CS8900_ADDR_PP_DATA2:
+ /* mask and align address of packet pointer */
+ ppaddress = cs8900_packetpage_ptr & PP_PTR_ADDR_MASK;
+ ppaddress &= ~1;
+ /* if flags match then auto incr pointer */
+ cs8900_auto_incr_pp_ptr();
+ break;
+ case CS8900_ADDR_INTSTQUEUE:
+ ppaddress = CS8900_PP_ADDR_SE_ISQ;
+ break;
+ case CS8900_ADDR_TXCMD:
+ ppaddress = CS8900_PP_ADDR_TXCMD;
+ break;
+ case CS8900_ADDR_TXLENGTH:
+ ppaddress = CS8900_PP_ADDR_TXLENGTH;
+ break;
+ default:
+ /* invalid! */
+ assert(0);
+ break;
+ }
+
+ /* read register value */
+ word_value = cs8900_read_register(ppaddress);
+ }
+
+ /* extract return value from word_value */
+ lo = LO_uint8_t(word_value);
+ hi = HI_uint8_t(word_value);
+ if ((io_address & 1) == 0) {
+ /* low byte on even address */
+ retval = lo;
+ } else {
+ /* high byte on odd address */
+ retval = hi;
+ }
+ return retval;
+}
+
+/* ----- write byte to I/O range of VICE ----- */
+void cs8900_store(uint16_t io_address, uint8_t byte)
+{
+ uint16_t reg_base;
+ uint16_t word_value;
+
+ assert(cs8900);
+ assert(cs8900_packetpage);
+ assert(io_address < 0x10);
+
+#ifdef CS8900_DEBUG_STORE
+ log_message(cs8900_log, "store [$%02X] <= $%02X.", io_address, (int)byte);
+#endif
+
+ /* register base addr */
+ reg_base = io_address & ~1;
+
+ /* TX Register is special as it writes to TX buffer directly */
+ if ((reg_base == CS8900_ADDR_RXTXDATA) || (reg_base == CS8900_ADDR_RXTXDATA2)) {
+ cs8900_write_tx_buffer(byte, io_address & 1);
+ return;
+ }
+
+ /* combine stored value with new written byte */
+ if ((io_address & 1) == 0) {
+ /* overwrite low byte */
+ word_value = LOHI_uint16_t(byte, cs8900[reg_base + 1]);
+ } else {
+ /* overwrite high byte */
+ word_value = LOHI_uint16_t(cs8900[reg_base], byte);
+ }
+
+ if (reg_base == CS8900_ADDR_PP_PTR) {
+ /* we store the full package pointer in cs8900_packetpage_ptr variable.
+ this includes the mask area (0xf000) and the addr range (0x0fff).
+ we ensure that the bits 0x3000 are always set (as in real HW).
+ odd values of the pointer are valid and supported.
+ only register read and write have to be mapped to word boundary. */
+ word_value |= 0x3000;
+ cs8900_packetpage_ptr = word_value;
+
+#ifdef CS8900_DEBUG_STORE
+ log_message(cs8900_log, "set PP Ptr to $%04X.", cs8900_packetpage_ptr);
+#endif
+ } else {
+ /* write a register */
+
+ /*! \TODO: Find a reasonable default */
+ uint16_t ppaddress = CS8900_PP_ADDR_PRODUCTID;
+
+ /* now determine address of write in packet page */
+ switch (reg_base) {
+ case CS8900_ADDR_PP_DATA:
+ case CS8900_ADDR_PP_DATA2:
+ /* mask and align ppaddress from page pointer */
+ ppaddress = cs8900_packetpage_ptr & (MAX_PACKETPAGE_ARRAY - 1);
+ ppaddress &= ~1;
+ /* auto increment pp ptr */
+ cs8900_auto_incr_pp_ptr();
+ break;
+ case CS8900_ADDR_TXCMD:
+ ppaddress = CS8900_PP_ADDR_TXCMD;
+ break;
+ case CS8900_ADDR_TXLENGTH:
+ ppaddress = CS8900_PP_ADDR_TXLENGTH;
+ break;
+ case CS8900_ADDR_INTSTQUEUE:
+ ppaddress = CS8900_PP_ADDR_SE_ISQ;
+ break;
+ case CS8900_ADDR_PP_PTR:
+ break;
+ default:
+ /* invalid */
+ assert(0);
+ break;
+ }
+
+#ifdef CS8900_DEBUG_STORE
+ log_message(cs8900_log, "before writing to PP Ptr: $%04X <= $%04X.", ppaddress, word_value);
+#endif
+
+ /* perform the write */
+ cs8900_write_register(ppaddress, word_value);
+
+ /* handle sideeffects */
+ cs8900_sideeffects_write_pp(ppaddress, io_address & 1);
+
+ /* update word value if it was changed in write register or by side effect */
+ word_value = GET_PP_16(ppaddress);
+
+#ifdef CS8900_DEBUG_STORE
+ log_message(cs8900_log, "after writing to PP Ptr: $%04X <= $%04X.", ppaddress, word_value);
+#endif
+ }
+
+ /* update cs8900 registers */
+ cs8900[reg_base] = LO_uint8_t(word_value);
+ cs8900[reg_base + 1] = HI_uint8_t(word_value);
+}
+
+int cs8900_dump(void)
+{
+ /* FIXME: this is incomplete */
+ // mon_out("Link status: %s\n", (GET_PP_16(CS8900_PP_ADDR_SE_LINEST) & 0x80) ? "up" : "no link");
+ // mon_out("Package Page Ptr: $%04X (autoincrement %s)\n", cs8900_packetpage_ptr & PP_PTR_ADDR_MASK, (cs8900_packetpage_ptr & PP_PTR_AUTO_INCR_FLAG) != 0 ? "enabled" : "disabled");
+ return 0;
+}
+
+/* ---------------------------------------------------------------------*/
+/* snapshot support functions */
+
+#define CART_DUMP_VER_MAJOR 0
+#define CART_DUMP_VER_MINOR 0
+#define SNAP_MODULE_NAME "CS8900"
+
+/* FIXME: implement snapshot support */
+int cs8900_snapshot_write_module(snapshot_t *s)
+{
+ return -1;
+#if 0
+ snapshot_module_t *m;
+
+ m = snapshot_module_create(s, SNAP_MODULE_NAME,
+ CART_DUMP_VER_MAJOR, CART_DUMP_VER_MINOR);
+ if (m == NULL) {
+ return -1;
+ }
+
+ if (0) {
+ snapshot_module_close(m);
+ return -1;
+ }
+
+ snapshot_module_close(m);
+ return 0;
+#endif
+}
+
+int cs8900_snapshot_read_module(snapshot_t *s)
+{
+ return -1;
+#if 0
+ uint8_t vmajor, vminor;
+ snapshot_module_t *m;
+
+ m = snapshot_module_open(s, SNAP_MODULE_NAME, &vmajor, &vminor);
+ if (m == NULL) {
+ return -1;
+ }
+
+ if ((vmajor != CART_DUMP_VER_MAJOR) || (vminor != CART_DUMP_VER_MINOR)) {
+ snapshot_module_close(m);
+ return -1;
+ }
+
+ if (0) {
+ snapshot_module_close(m);
+ return -1;
+ }
+
+ snapshot_module_close(m);
+ return 0;
+#endif
+}
+
+#endif /* #ifdef HAVE_RAWNET */
diff --git a/src/rawnet/cs8900.h b/src/rawnet/cs8900.h
new file mode 100644
index 0000000..97b23fb
--- /dev/null
+++ b/src/rawnet/cs8900.h
@@ -0,0 +1,64 @@
+/*
+ * cs8900.h - CS8900 Ethernet Core
+ *
+ * Written by
+ * Spiro Trikaliotis
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+#include
+
+#ifndef HAVE_RAWNET
+ #error CS8900.H should not be included if HAVE_RAWNET is not defined!
+#endif /* #ifdef HAVE_RAWNET */
+
+#ifndef VICE_CS8900_H
+#define VICE_CS8900_H
+
+//#include <"types.h">
+
+typedef struct snapshot_s snapshot_t;
+extern int cs8900_snapshot_read_module(snapshot_t *s);
+extern int cs8900_snapshot_write_module(snapshot_t *s);
+
+extern int cs8900_init(void);
+extern void cs8900_reset(void);
+
+extern int cs8900_activate(const char *net_interface);
+extern int cs8900_deactivate(void);
+extern void cs8900_shutdown(void);
+
+extern uint8_t cs8900_read(uint16_t io_address);
+extern uint8_t cs8900_peek(uint16_t io_address);
+extern void cs8900_store(uint16_t io_address, uint8_t byte);
+extern int cs8900_dump(void);
+
+/*
+ This is a helper for cs8900_receive() to determine if the received frame should be accepted
+ according to the settings.
+
+ This function is even allowed to be called (indirectly via rawnet_should_accept) in rawnetarch.c
+ from rawnet_arch_receive() if necessary, and must be registered using rawnet_set_should_accept_func
+ at init time.
+*/
+extern int cs8900_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, int *pcorrect_mac, int *pbroadcast, int *pmulticast);
+
+#endif
diff --git a/src/rawnet/rawnet.c b/src/rawnet/rawnet.c
new file mode 100644
index 0000000..3146130
--- /dev/null
+++ b/src/rawnet/rawnet.c
@@ -0,0 +1,85 @@
+/*
+ * rawnet.c - raw ethernet interface
+ *
+ * Written by
+ * Spiro Trikaliotis
+ * Christian Vogelgsang
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+// #include "vice.h"
+
+#ifdef HAVE_RAWNET
+
+#include
+#include
+#include
+
+#include "rawnet.h"
+#include "rawnetsupp.h"
+#include "rawnetarch.h"
+
+static int (*should_accept)(unsigned char *, int, int *, int *, int *, int *, int *) = NULL;
+
+int rawnet_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, int *pcorrect_mac, int *pbroadcast, int *pmulticast)
+{
+ assert(should_accept);
+ return should_accept(buffer, length, phashed, phash_index, pcorrect_mac, pbroadcast, pmulticast);
+}
+
+void rawnet_set_should_accept_func(int (*func)(unsigned char *, int, int *, int *, int *, int *, int *))
+{
+ should_accept = func;
+}
+
+/* ------------------------------------------------------------------------- */
+/* functions for selecting and querying available NICs */
+
+int rawnet_enumadapter_open(void)
+{
+ if (!rawnet_arch_enumadapter_open()) {
+ /* tfe_cannot_use = 1; */
+ return 0;
+ }
+ return 1;
+}
+
+int rawnet_enumadapter(char **ppname, char **ppdescription)
+{
+ return rawnet_arch_enumadapter(ppname, ppdescription);
+}
+
+int rawnet_enumadapter_close(void)
+{
+ return rawnet_arch_enumadapter_close();
+}
+
+char *rawnet_get_standard_interface(void)
+{
+ return rawnet_arch_get_standard_interface();
+}
+
+int rawnet_status(void)
+{
+ return rawnet_arch_status();
+}
+
+#endif /* #ifdef HAVE_RAWNET */
diff --git a/src/rawnet/rawnet.h b/src/rawnet/rawnet.h
new file mode 100644
index 0000000..bc61944
--- /dev/null
+++ b/src/rawnet/rawnet.h
@@ -0,0 +1,77 @@
+/*
+ * rawnet.h - raw ethernet interface
+ *
+ * Written by
+ * Spiro Trikaliotis
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+#ifdef HAVE_RAWNET
+#else
+ #error RAWNET.H should not be included if HAVE_RAWNET is not defined!
+#endif /* #ifdef HAVE_RAWNET */
+
+#ifndef VICE_RAWNET_H
+#define VICE_RAWNET_H
+
+/*
+ This is a helper for the _receive() function of the emulated ethernet chip to determine
+ if the received frame should be accepted according to the settings.
+
+ This function is even allowed to be called in rawnetarch.c from rawnet_arch_receive() if
+ necessary. the respective helper function of the emulated ethernet chip must be registered
+ using rawnet_set_should_accept_func at init time.
+*/
+
+extern int rawnet_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, int *pcorrect_mac, int *pbroadcast, int *pmulticast);
+extern void rawnet_set_should_accept_func(int (*func)(unsigned char *, int, int *, int *, int *, int *, int *));
+
+/*
+
+ These functions let the UI enumerate the available interfaces.
+
+ First, rawnet_enumadapter_open() is used to start enumeration.
+
+ rawnet_enumadapter() is then used to gather information for each adapter present
+ on the system, where:
+
+ ppname points to a pointer which will hold the name of the interface
+ ppdescription points to a pointer which will hold the description of the interface
+
+ For each of these parameters, new memory is allocated, so it has to be
+ freed with lib_free().
+ Note: The description can be NULL, since pcap_if_t.desc can be NULL, so
+ check the description before calling lib_free() on it.
+
+ rawnet_enumadapter_close() must be used to stop processing.
+
+ Each function returns 1 on success, and 0 on failure.
+ rawnet_enumadapter() only fails if there is no more adpater; in this case,
+ *ppname and *ppdescription are not altered.
+*/
+extern int rawnet_enumadapter_open(void);
+extern int rawnet_enumadapter(char **ppname, char **ppdescription);
+extern int rawnet_enumadapter_close(void);
+extern char *rawnet_get_standard_interface(void);
+
+extern int rawnet_status(void);
+
+#endif
diff --git a/src/rawnet/rawnetarch.c b/src/rawnet/rawnetarch.c
new file mode 100644
index 0000000..7149de8
--- /dev/null
+++ b/src/rawnet/rawnetarch.c
@@ -0,0 +1,144 @@
+/** \file rawnetarch.c
+ * \brief raw ethernet interface, architecture-dependant stuff
+ *
+ * \author Bas Wassink
+
+#ifdef HAVE_RAWNET
+
+/* backward compatibility junk */
+
+
+/** \brief Transmit a frame
+ *
+ * \param[in] force Delete waiting frames in transmit buffer
+ * \param[in] onecoll Terminate after just one collision
+ * \param[in] inhibit_crc Do not append CRC to the transmission
+ * \param[in] tx_pad_dis Disable padding to 60 Bytes
+ * \param[in] txlength Frame length
+ * \param[in] txframe Pointer to the frame to be transmitted
+ */
+void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc,
+ int tx_pad_dis, int txlength, uint8_t *txframe)
+{
+
+ int ok;
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log,
+ "rawnet_arch_transmit() called, with: force = %s, onecoll = %s, "
+ "inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
+ force ? "TRUE" : "FALSE",
+ onecoll ? "TRUE" : "FALSE",
+ inhibit_crc ? "TRUE" : "FALSE",
+ tx_pad_dis ? "TRUE" : "FALSE",
+ txlength);
+#endif
+
+ ok = rawnet_arch_write(txframe, txlength);
+ if (ok < 0) {
+ log_message(rawnet_arch_log, "WARNING! Could not send packet!");
+ }
+}
+
+/**
+ * \brief Check if a frame was received
+ *
+ * This function checks if there was a frame received. If so, it returns 1,
+ * else 0.
+ *
+ * If there was no frame, none of the parameters is changed!
+ *
+ * If there was a frame, the following actions are done:
+ *
+ * - at maximum \a plen byte are transferred into the buffer given by \a pbuffer
+ * - \a plen gets the length of the received frame, EVEN if this is more
+ * than has been copied to \a pbuffer!
+ * - if the dest. address was accepted by the hash filter, \a phashed is set,
+ * else cleared.
+ * - if the dest. address was accepted by the hash filter, \a phash_index is
+ * set to the number of the rule leading to the acceptance
+ * - if the receive was ok (good CRC and valid length), \a *prx_ok is set, else
+ * cleared.
+ * - if the dest. address was accepted because it's exactly our MAC address
+ * (set by rawnet_arch_set_mac()), \a pcorrect_mac is set, else cleared.
+ * - if the dest. address was accepted since it was a broadcast address,
+ * \a pbroadcast is set, else cleared.
+ * - if the received frame had a crc error, \a pcrc_error is set, else cleared
+ *
+ * \param[out] buffer where to store a frame
+ * \param[in,out] plen IN: maximum length of frame to copy;
+ * OUT: length of received frame OUT
+ * can be bigger than IN if received frame was
+ * longer than supplied buffer
+ * \param[out] phashed set if the dest. address is accepted by the
+ * hash filter
+ * \param[out] phash_index hash table index if hashed == TRUE
+ * \param[out] prx_ok set if good CRC and valid length
+ * \param[out] pcorrect_mac set if dest. address is exactly our IA
+ * \param[out[ pbroadcast set if dest. address is a broadcast address
+ * \param[out] pcrc_error set if received frame had a CRC error
+*/
+int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed,
+ int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast,
+ int *pcrc_error)
+{
+ int ok;
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log,
+ "rawnet_arch_receive() called, with *plen=%u.",
+ *plen);
+#endif
+
+
+
+ assert((*plen & 1) == 0);
+
+ ok = rawnet_arch_read(pbuffer, *plen);
+ if (ok <= 0) return 0;
+
+ if (ok & 1) ++ok;
+ *plen = ok;
+
+ *phashed =
+ *phash_index =
+ *pbroadcast =
+ *pcorrect_mac =
+ *pcrc_error = 0;
+
+ /* this frame has been received correctly */
+ *prx_ok = 1;
+ return 1;
+
+}
+
+
+
+
+#endif /* ifdef HAVE_RAWNET */
diff --git a/src/rawnet/rawnetarch.h b/src/rawnet/rawnetarch.h
new file mode 100644
index 0000000..68ddc68
--- /dev/null
+++ b/src/rawnet/rawnetarch.h
@@ -0,0 +1,77 @@
+/*
+ * rawnetarch.h - raw ethernet interface
+ * architecture-dependant stuff
+ *
+ * Written by
+ * Spiro Trikaliotis
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+#include
+
+#ifdef HAVE_RAWNET
+#else
+ #error RAWNETARCH.H should not be included if HAVE_RAWNET is not defined!
+#endif /* #ifdef HAVE_RAWNET */
+
+#ifndef VICE_RAWNETARCH_H
+#define VICE_RAWNETARCH_H
+
+/* define this only if VICE should write each and every frame received
+ and send into the VICE log
+ WARNING: The log grows very fast!
+*/
+/* #define RAWNET_DEBUG_FRAMES */
+
+// #include "types.h"
+
+extern int rawnet_arch_init(void);
+extern void rawnet_arch_pre_reset(void);
+extern void rawnet_arch_post_reset(void);
+extern int rawnet_arch_activate(const char *interface_name);
+extern void rawnet_arch_deactivate(void);
+extern void rawnet_arch_set_mac(const uint8_t mac[6]);
+extern void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2]);
+
+extern void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash);
+
+extern void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver);
+
+extern void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc, int tx_pad_dis, int txlength, uint8_t *txframe);
+
+extern int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed, int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast, int *pcrc_error);
+
+extern int rawnet_arch_enumadapter_open(void);
+extern int rawnet_arch_enumadapter(char **ppname, char **ppdescription);
+extern int rawnet_arch_enumadapter_close(void);
+
+extern char *rawnet_arch_get_standard_interface(void);
+
+
+extern int rawnet_arch_read(void *buffer, int length);
+extern int rawnet_arch_write(const void *buffer, int length);
+
+extern int rawnet_arch_get_mtu(void);
+extern int rawnet_arch_get_mac(uint8_t mac[6]);
+
+extern int rawnet_arch_status(void);
+
+#endif
diff --git a/src/rawnet/rawnetarch_tap.c b/src/rawnet/rawnetarch_tap.c
new file mode 100644
index 0000000..a7c7e88
--- /dev/null
+++ b/src/rawnet/rawnetarch_tap.c
@@ -0,0 +1,481 @@
+/* tun/tap support */
+/* for Linux, *BSD */
+
+/*
+ * tap is a virtual ethernet devices.
+ * open the device, configure, and read/write ethernet frames.
+ *
+ * Linux setup: (from Network Programmability and Automation, Appendix A)
+ *
+ * Notes:
+ * - this assumes eth0 is your main interface device
+ * - may need to install the iproute/iproute2 package (ip command)
+ * - do this stuff as root.
+ *
+ * 1. create a tap interface
+ * $ ip tuntap add tap65816 mode tap user YOUR_USER_NAME
+ * $ ip link set tap65816 up
+ *
+ * 2. create a network bridge
+ * $ ip link add name br0 type bridge
+ * $ ip link set br0 up
+ *
+ * 3. bridge the physical network and virtual network.
+ * $ ip link set eth0 master br0
+ * $ ip link set tap65816 master br0
+ *
+ * 4. remove ip address from physical device (This will kill networking)
+ * ip address flush dev eth0
+ *
+ * 5. and add the ip address to the bridge
+ * dhclient br0 # if using dhcp
+ * ip address add 192.168.1.1/24 dev eth0 # if using static ip address.
+ *
+ * *BSD:
+ * - assumes eth0 is your main interface device.
+ * $ ifconfig bridge0 create
+ * $ ifconfig tap65816 create
+ * $ ifconfig bridge0 addm eth0 addm tap65816 up
+ *
+ * allow normal users to open tap devices?
+ * $ sysctl net.link.tap.user_open=1
+ * $ sysctl net.link.tap.up_on_open=1
+ *
+ * set permissions
+ * $ chown YOUR_USER_NAME /dev/tap65816
+ * $ chmod 660 /dev/tap65816
+ */
+
+
+
+#define _GNU_SOURCE
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#if defined(__linux__)
+#include
+#include
+#endif
+
+#include "rawnetarch.h"
+#include "rawnetsupp.h"
+
+#if defined(__linux__)
+#define TAP_DEVICE "/dev/net/tun"
+#endif
+
+#if defined(__FreeBSD__)
+#define TAP_DEVICE "/dev/tap"
+#endif
+
+static int interface_fd = -1;
+static char *interface_dev = NULL;
+
+static uint8_t interface_mac[6];
+static uint8_t interface_fake_mac[6];
+
+static uint8_t *interface_buffer = NULL;
+static int interface_buffer_size = 0;
+
+int rawnet_arch_init(void) {
+ interface_fd = -1;
+ return 1;
+}
+void rawnet_arch_pre_reset(void) {
+ /* NOP */
+}
+
+void rawnet_arch_post_reset(void) {
+ /* NOP */
+}
+
+/* memoized buffer for ethernet packets, etc */
+static int make_buffer(int size) {
+ if (size <= interface_buffer_size) return 0;
+ if (interface_buffer) free(interface_buffer);
+ if (size < 1500) size = 1500; /* good mtu size */
+ interface_buffer_size = 0;
+ size *= 2;
+ interface_buffer = malloc(size);
+ if (!interface_buffer) return -1;
+ interface_buffer_size = size;
+ return 0;
+}
+
+#if defined(__linux__)
+/* interface name. default is tap65816. */
+int rawnet_arch_activate(const char *interface_name) {
+
+ struct ifreq ifr;
+
+ int ok;
+ int one = 1;
+ int fd;
+
+ if (!interface_name || !*interface_name) {
+ interface_name = "tap65816";
+ }
+
+ fd = open(TAP_DEVICE, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "rawnet_arch_activate: open(%s): %s\n", TAP_DEVICE, strerror(errno));
+ return 0;
+ }
+
+ ok = ioctl(fd, FIONBIO, &one);
+ if (ok < 0) {
+ perror("ioctl(FIONBIO");
+ close(fd);
+ return 0;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(&if.ifr_name, interface_name);
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ ok = ioctl(fd, TUNSETIFF, (void *) &ifr);
+ if (ok < 0) {
+ perror("ioctl(TUNSETIFF)");
+ close(fd);
+ return 0;
+ }
+
+ if (rawnet_arch_get_mac(interface_mac) < 0) {
+ perror("rawnet_arch_get_mac");
+ close(fd);
+ return 0;
+ }
+ /* copy mac to fake mac */
+ memcpy(interface_fake_mac, interface_mac, 6);
+
+
+ interface_dev = strdup(interface_name);
+ interface_fd = fd;
+ return 1;
+}
+#endif
+
+#if defined(__FreeBSD__)
+/* man tap(4) */
+/* interface name. default is tap65816. */
+int rawnet_arch_activate(const char *interface_name) {
+
+ struct ifreq ifr;
+
+ int ok;
+ int one = 1;
+ int fd;
+ char *path[64];
+
+ if (!interface_name || !*interface_name) {
+ interface_name = "tap65816";
+ }
+
+ ok = snprintf(path, sizeof(path), "/dev/%s", interface_name);
+ if (ok >= sizeof(path)) return 0;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "rawnet_arch_activate: open(%s): %s\n", path, strerror(errno));
+ return 0;
+ }
+
+ ok = ioctl(fd, FIONBIO, &one);
+ if (ok < 0) {
+ perror("ioctl(FIONBIO");
+ close(fd);
+ return 0;
+ }
+
+ if (rawnet_arch_get_mac(interface_mac) < 0) {
+ perror("rawnet_arch_get_mac");
+ close(fd);
+ return 0;
+ }
+ /* copy mac to fake mac */
+ memcpy(interface_fake_mac, interface_mac, 6);
+
+
+
+ interface_dev = strdup(interface_name);
+ interface_fd = fd;
+ return 1;
+}
+#endif
+
+
+
+
+void rawnet_arch_deactivate(void) {
+ if (interface_fd >= 0)
+ close(interface_fd);
+ free(interface_dev);
+
+ free(interface_buffer);
+ interface_buffer = 0;
+ interface_buffer_size = 0;
+
+ interface_dev = NULL;
+ interface_fd = -1;
+}
+
+
+void rawnet_arch_set_mac(const uint8_t mac[6]) {
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+#endif
+
+ memcpy(interface_fake_mac, mac, 6);
+
+ /* in theory, SIOCSIFHWADDR (linux) or SIOCSIFADDR (bsd) will set the mac address. */
+ /* in testing, (linux) I get EBUSY or EOPNOTSUPP */
+
+
+#if 0
+ if (interface_fd < 0) return;
+
+
+ #if defined(__linux__)
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
+ if (ioctl(interface_fd, SIOCSIFHWADDR, (void *)&ifr) < 0)
+ perror("ioctl(SIOCSIFHWADDR)");
+ #endif
+
+ #if defined(__FreeBSD__)
+ if (ioctl(interface_fd, SIOCSIFADDR, mac) < 0)
+ perror("ioctl(SIOCSIFADDR)");
+ #endif
+#endif
+}
+void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2]) {
+ /* NOP */
+}
+
+void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash) {
+ /* NOP */
+}
+
+void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) {
+ /* NOP */
+}
+
+int rawnet_arch_read(void *buffer, int nbyte) {
+ int ok;
+
+ if (make_buffer(nbyte) < 0) return -1;
+
+ ok = read(interface_fd, interface_buffer, nbyte);
+ if (ok <= 0) return -1;
+
+ rawnet_fix_incoming_packet(interface_buffer, ok, interface_mac, interface_fake_mac);
+ memcpy(buffer, interface_buffer, ok);
+ return ok;
+}
+
+int rawnet_arch_write(const void *buffer, int nbyte) {
+ int ok;
+
+ if (make_buffer(nbyte) < 0) return -1;
+
+
+ memcpy(interface_buffer, buffer, nbyte);
+ rawnet_fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac);
+
+ ok = write(interface_fd, interface_buffer, nbyte);
+ return ok;
+}
+
+
+static unsigned adapter_index = 0;
+static unsigned adapter_count = 0;
+static char **devices = NULL;
+
+static int cmp(const void *a, const void *b) {
+ return strcasecmp(*(const char **)a, *(const char **)b);
+}
+
+int rawnet_arch_enumadapter_open(void) {
+ adapter_index = 0;
+ adapter_count = 0;
+ devices = NULL;
+
+ char buffer[MAXPATHLEN];
+
+ unsigned capacity = 0;
+ unsigned count = 0;
+ DIR *dp = NULL;
+
+ int i;
+
+
+ capacity = 20;
+ devices = (char **)malloc(sizeof(char *) * capacity);
+ if (!devices) return 0;
+
+
+#if defined(__linux__)
+
+ dp = opendir("/sys/class/net/");
+ if (!dp) goto fail;
+
+ for(;;) {
+ char *cp;
+ FILE *fp;
+ struct dirent *d = readdir(dp);
+ if (!d) break;
+
+ if (d->d_name[0] == '.') continue;
+
+ sprintf(buffer, "/sys/class/net/%s/tun_flags", d->d_name);
+ fp = fopen(buffer, "r");
+ if (!fp) continue;
+ cp = fgets(buffer, sizeof(buffer), fp);
+ fclose(fp);
+ if (cp) {
+ /* expect 0x1002 */
+ int flags = strtol(cp, (char **)NULL, 16);
+ if ((flags & TUN_TYPE_MASK) == IFF_TAP) {
+
+ devices[count++] = strdup(d->d_name);
+ if (count == capacity) {
+ char **tmp;
+ capacity *= 2;
+ tmp = (char **)realloc(devices, sizeof(char *) * capacity);
+ if (tmp) devices = tmp;
+ else break; /* no mem? */
+ }
+
+ }
+ }
+
+ }
+ closedir(dp);
+#endif
+
+#if defined(__FreeBSD__)
+ /* dev/tapxxxx */
+ dp = opendir("/dev/");
+ if (!dp) goto fail;
+ for(;;) {
+ struct dirent *d = readdir(dp);
+ if (!d) break;
+
+ if (d->d_name[0] == '.') continue;
+ if (strncmp(d->d_name, "tap", 3) == 0 && isdigit(d->d_name[3])) {
+
+ devices[count++] = strdup(d->d_name);
+ if (count == capacity) {
+ char **tmp;
+ capacity *= 2;
+ tmp = (char **)realloc(devices, sizeof(char *) * capacity);
+ if (tmp) devices = tmp;
+ else break; /* no mem? */
+ }
+ }
+
+ }
+ closedir(dp);
+#endif
+
+ /* sort them ... */
+ qsort(devices, count, sizeof(char *), cmp);
+
+ adapter_count = count;
+ return 1;
+
+fail:
+ if (dp) closedir(dp);
+ if (devices) for(i = 0; i = adapter_count) return 0;
+
+ if (ppdescription) *ppdescription = NULL;
+ if (ppname) *ppname = strdup(devices[adapter_index]);
+ ++adapter_index;
+ return 1;
+}
+
+
+char *rawnet_arch_get_standard_interface(void) {
+ return lib_stralloc("tap65816");
+}
+
+int rawnet_arch_get_mtu(void) {
+ if (interface_fd < 0) return -1;
+
+ #if defined(__linux__)
+ /* n.b. linux tap driver doesn't actually support SIOCGIFMTU */
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ if (ioctl(interface_fd, SIOCGIFMTU, (void *) &ifr) < 0) return -1; /* ? */
+ return ifr.ifr_mtu;
+ #endif
+
+ #if defined(__FreeBSD__)
+ struct tapinfo ti;
+ if (ioctl(interface_fd, TAPSIFINFO, &ti) < 0) return -1;
+ return ti.mtu;
+ #endif
+
+ return -1;
+}
+
+int rawnet_arch_get_mac(uint8_t mac[6]) {
+
+
+ if (interface_fd < 0) return -1;
+
+ #if defined(__linux__)
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ if (ioctl(interface_fd, SIOCGIFHWADDR, (void *)&ifr) < 0) return -1;
+ memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
+ return 0;
+ #endif
+
+ #if defined(__FreeBSD__)
+ if (ioctl(interface_fd, SIOCSIFADDR, mac) < 0) return -1;
+ return 0;
+ #endif
+
+ return -1;
+
+}
+
+int rawnet_arch_status(void) {
+ return interface_fd >= 0 ? 1 : 0;
+}
+
diff --git a/src/rawnet/rawnetarch_unix.c b/src/rawnet/rawnetarch_unix.c
new file mode 100644
index 0000000..0609995
--- /dev/null
+++ b/src/rawnet/rawnetarch_unix.c
@@ -0,0 +1,511 @@
+/** \file rawnetarch_unix.c
+ * \brief Raw ethernet interface, architecture-dependent stuff
+ *
+ * \author Spiro Trikaliotis
+ * \author Bas Wassink
+ *
+ * These functions let the UI enumerate the available interfaces.
+ *
+ * First, rawnet_arch_enumadapter_open() is used to start enumeration.
+ *
+ * rawnet_arch_enumadapter() is then used to gather information for each adapter
+ * present on the system, where:
+ *
+ * ppname points to a pointer which will hold the name of the interface
+ * ppdescription points to a pointer which will hold the description of the
+ * interface
+ *
+ * For each of these parameters, new memory is allocated, so it has to be
+ * freed with lib_free(), except ppdescription, which can be `NULL`, though
+ * calling lib_free() on `NULL` is safe.
+ *
+ * rawnet_arch_enumadapter_close() must be used to stop processing.
+ *
+ * Each function returns 1 on success, and 0 on failure.
+ * rawnet_arch_enumadapter() only fails if there is no more adpater; in this
+ * case, *ppname and *ppdescription are not altered.
+ */
+
+/*
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+#include
+
+// #include "vice.h"
+
+#ifdef HAVE_RAWNET
+
+#include
+
+#include
+#include
+#include
+#include
+
+// #include "lib.h"
+// #include "log.h"
+#include "rawnetarch.h"
+#include "rawnetsupp.h"
+
+#if defined(__linux__)
+#include
+#include
+#include
+#endif
+
+/*
+ * FIXME: rename all remaining tfe_ stuff to rawnet_
+ */
+
+#define RAWNET_DEBUG_WARN 1 /* this should not be deactivated
+ * If this should not be deactived, why is this
+ * here at all? --compyx
+ */
+
+
+/** \brief Only select devices that are PCAP_IF_UP
+ *
+ * Since on Linux pcap_findalldevs() returns all interfaces, including special
+ * kernal devices such as nfqueue, filtering the list returned by pcap makes
+ * sense. Should this filtering cause trouble on other Unices, this define can
+ * be guarded with #ifdef SOME_UNIX_VERSION to disable the filtering.
+ */
+#ifdef PCAP_IF_UP
+#define RAWNET_ONLY_IF_UP
+#endif
+
+
+/** #define RAWNET_DEBUG_ARCH 1 **/
+/** #define RAWNET_DEBUG_PKTDUMP 1 **/
+
+/* ------------------------------------------------------------------------- */
+/* variables needed */
+
+// static log_t rawnet_arch_log = LOG_ERR;
+
+
+/** \brief Iterator for the list returned by pcap_findalldevs()
+ */
+static pcap_if_t *rawnet_pcap_dev_iter = NULL;
+
+
+/** \brief Device list returned by pcap_findalldevs()
+ *
+ * Can be `NULL` since pcap_findalldevs() considers not finding any devices a
+ * succesful outcome.
+ */
+static pcap_if_t *rawnet_pcap_dev_list = NULL;
+
+
+static pcap_t *rawnet_pcap_fp = NULL;
+static char *rawnet_device_name = NULL;
+
+
+/** \brief Buffer for pcap error messages
+ */
+static char rawnet_pcap_errbuf[PCAP_ERRBUF_SIZE];
+
+
+#ifdef RAWNET_DEBUG_PKTDUMP
+
+static void debug_output( const char *text, uint8_t *what, int count )
+{
+ char buffer[256];
+ char *p = buffer;
+ char *pbuffer1 = what;
+ int len1 = count;
+ int i;
+
+ sprintf(buffer, "\n%s: length = %u\n", text, len1);
+ fprintf(stderr, "%s", buffer);
+ do {
+ p = buffer;
+ for (i=0; (i<8) && len1>0; len1--, i++) {
+ sprintf(p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++);
+ p += 3;
+ }
+ *(p-1) = '\n'; *p = 0;
+ fprintf(stderr, "%s", buffer);
+ } while (len1>0);
+}
+#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
+
+
+int rawnet_arch_enumadapter_open(void)
+{
+ if (pcap_findalldevs(&rawnet_pcap_dev_list, rawnet_pcap_errbuf) == -1) {
+ log_message(rawnet_arch_log,
+ "ERROR in rawnet_arch_enumadapter_open: pcap_findalldevs: '%s'",
+ rawnet_pcap_errbuf);
+ return 0;
+ }
+
+ if (!rawnet_pcap_dev_list) {
+ log_message(rawnet_arch_log,
+ "ERROR in rawnet_arch_enumadapter_open, finding all pcap "
+ "devices - Do we have the necessary privilege rights?");
+ return 0;
+ }
+
+ rawnet_pcap_dev_iter = rawnet_pcap_dev_list;
+ return 1;
+}
+
+
+/** \brief Get current pcap device iterator values
+ *
+ * The \a ppname and \a ppdescription are heap-allocated via lib_stralloc()
+ * and should thus be freed after use with lib_free(). Please not that
+ * \a ppdescription can be `NULL` due to pcap_if_t->description being `NULL`,
+ * so check against `NULL` before using it. Calling lib_free() on it is safe
+ * though, free(`NULL`) is guaranteed to just do nothing.
+ *
+ * \param[out] ppname device name
+ * \param[out] ppdescription device description
+ *
+ * \return bool (1 on success, 0 on failure)
+ */
+int rawnet_arch_enumadapter(char **ppname, char **ppdescription)
+{
+#ifdef RAWNET_ONLY_IF_UP
+ /* only select devices that are up */
+ while (rawnet_pcap_dev_iter != NULL
+ && !(rawnet_pcap_dev_iter->flags & PCAP_IF_UP)) {
+ rawnet_pcap_dev_iter = rawnet_pcap_dev_iter->next;
+ }
+#endif
+
+ if (rawnet_pcap_dev_iter == NULL) {
+ return 0;
+ }
+
+ *ppname = lib_stralloc(rawnet_pcap_dev_iter->name);
+ /* carefull: pcap_if_t->description can be NULL and lib_stralloc() fails on
+ * passing `NULL` */
+ if (rawnet_pcap_dev_iter->description != NULL) {
+ *ppdescription = lib_stralloc(rawnet_pcap_dev_iter->description);
+ } else {
+ *ppdescription = NULL;
+ }
+
+ rawnet_pcap_dev_iter = rawnet_pcap_dev_iter->next;
+
+ return 1;
+}
+
+int rawnet_arch_enumadapter_close(void)
+{
+ if (rawnet_pcap_dev_list) {
+ pcap_freealldevs(rawnet_pcap_dev_list);
+ rawnet_pcap_dev_list = NULL;
+ }
+ return 1;
+}
+
+static int rawnet_pcap_open_adapter(const char *interface_name)
+{
+ rawnet_pcap_fp = pcap_open_live((char*)interface_name, 1700, 1, 20, rawnet_pcap_errbuf);
+ if ( rawnet_pcap_fp == NULL) {
+ log_message(rawnet_arch_log, "ERROR opening adapter: '%s'", rawnet_pcap_errbuf);
+ return 0;
+ }
+
+ if (pcap_setnonblock(rawnet_pcap_fp, 1, rawnet_pcap_errbuf) < 0) {
+ log_message(rawnet_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", rawnet_pcap_errbuf);
+ }
+
+ /* Check the link layer. We support only Ethernet for simplicity. */
+ if (pcap_datalink(rawnet_pcap_fp) != DLT_EN10MB) {
+ log_message(rawnet_arch_log, "ERROR: TFE works only on Ethernet networks.");
+ pcap_close(rawnet_pcap_fp);
+ rawnet_pcap_fp = NULL;
+ return 0;
+ }
+ rawnet_device_name = strdup(interface_name);
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+/* the architecture-dependend functions */
+
+int rawnet_arch_init(void)
+{
+ //rawnet_arch_log = log_open("TFEARCH");
+
+ return 1;
+}
+
+void rawnet_arch_pre_reset(void)
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "rawnet_arch_pre_reset()." );
+#endif
+}
+
+void rawnet_arch_post_reset(void)
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "rawnet_arch_post_reset()." );
+#endif
+}
+
+int rawnet_arch_activate(const char *interface_name)
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "rawnet_arch_activate()." );
+#endif
+ if (!rawnet_pcap_open_adapter(interface_name)) {
+ return 0;
+ }
+ return 1;
+}
+
+void rawnet_arch_deactivate( void )
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "rawnet_arch_deactivate()." );
+#endif
+}
+
+void rawnet_arch_set_mac( const uint8_t mac[6] )
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+#endif
+}
+
+void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2])
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "New hash filter set: %08X:%08X.", hash_mask[1], hash_mask[0]);
+#endif
+}
+
+/* int bBroadcast - broadcast */
+/* int bIA - individual address (IA) */
+/* int bMulticast - multicast if address passes the hash filter */
+/* int bCorrect - accept correct frames */
+/* int bPromiscuous - promiscuous mode */
+/* int bIAHash - accept if IA passes the hash filter */
+
+void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash)
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log, "rawnet_arch_recv_ctl() called with the following parameters:" );
+ log_message(rawnet_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE");
+ log_message(rawnet_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE");
+ log_message(rawnet_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE");
+ log_message(rawnet_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE");
+ log_message(rawnet_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE");
+ log_message(rawnet_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE");
+#endif
+}
+
+void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver )
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log,
+ "rawnet_arch_line_ctl() called with the following parameters:");
+ log_message(rawnet_arch_log,
+ "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE");
+ log_message(rawnet_arch_log,
+ "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE");
+#endif
+}
+
+
+/** \brief Raw pcap packet
+ */
+typedef struct rawnet_pcap_internal_s {
+ unsigned int len; /**< length of packet data */
+ uint8_t *buffer; /**< packet data */
+} rawnet_pcap_internal_t;
+
+
+/** \brief Callback function invoked by libpcap for every incoming packet
+ *
+ * \param[in,out] param reference to internal VICE packet struct
+ * \param[in] header pcap header
+ * \param[in] pkt_data packet data
+ */
+static void rawnet_pcap_packet_handler(u_char *param,
+ const struct pcap_pkthdr *header, const u_char *pkt_data)
+{
+ rawnet_pcap_internal_t *pinternal = (void*)param;
+
+ /* determine the count of bytes which has been returned,
+ * but make sure not to overrun the buffer
+ */
+ if (header->caplen < pinternal->len) {
+ pinternal->len = header->caplen;
+ }
+
+ memcpy(pinternal->buffer, pkt_data, pinternal->len);
+}
+
+
+/** \brief Receives a frame
+ *
+ * If there's none, it returns a -1 in \a pinternal->len, if there is one,
+ * it returns the length of the frame in bytes in \a pinternal->len.
+ *
+ * It copies the frame to \a buffer and returns the number of copied bytes as
+ * the return value.
+ *
+ * \param[in,out] pinternal internal VICE packet struct
+ *
+ * \note At most 'len' bytes are copied.
+ *
+ * \return number of bytes copied or -1 on failure
+ */
+static int rawnet_arch_receive_frame(rawnet_pcap_internal_t *pinternal)
+{
+ int ret = -1;
+
+ /* check if there is something to receive */
+ if (pcap_dispatch(rawnet_pcap_fp, 1, rawnet_pcap_packet_handler,
+ (void*)pinternal) != 0) {
+ /* Something has been received */
+ ret = pinternal->len;
+ }
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log,
+ "rawnet_arch_receive_frame() called, returns %d.", ret);
+#endif
+
+ return ret;
+}
+
+int rawnet_arch_read(void *buffer, int nbyte) {
+
+ int len;
+
+ rawnet_pcap_internal_t internal = { nbyte, (uint8_t *)buffer };
+
+ len = rawnet_arch_receive_frame(&internal);
+
+ if (len <= 0) return len;
+
+#ifdef RAWNET_DEBUG_PKTDUMP
+ debug_output("Received frame: ", internal.buffer, internal.len);
+#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
+ return len;
+
+}
+
+
+int rawnet_arch_write(const void *buffer, int nbyte) {
+
+#ifdef RAWNET_DEBUG_PKTDUMP
+ debug_output("Transmit frame: ", buffer, nbyte);
+#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
+
+ if (pcap_sendpacket(rawnet_pcap_fp, buffer, nbyte) < 0) {
+ log_message(rawnet_arch_log, "WARNING! Could not send packet!");
+ return -1;
+ }
+ return nbyte;
+}
+
+
+
+/** \brief Find default device on which to capture
+ *
+ * \return name of standard interface
+ *
+ * \note pcap_lookupdev() has been deprecated, so the correct way to get
+ * the default device is to use the first entry returned by
+ * pcap_findalldevs().
+ * See http://www.tcpdump.org/manpages/pcap_lookupdev.3pcap.html
+ *
+ * \return default interface name or `NULL` when not found
+ *
+ * \note free the returned value with lib_free() if not `NULL`
+ */
+char *rawnet_arch_get_standard_interface(void)
+{
+ char *dev = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ pcap_if_t *list;
+
+ if (pcap_findalldevs(&list, errbuf) == 0 && list != NULL) {
+ dev = lib_stralloc(list[0].name);
+ pcap_freealldevs(list);
+ }
+ return dev;
+}
+
+extern int rawnet_arch_get_mtu(void) {
+
+ #if defined(__linux__)
+ int fd;
+ int ok;
+ struct ifreq ifr;
+
+ if (!rawnet_device_name) return -1;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, rawnet_device_name);
+ ok = ioctl(fd, SIOCGIFMTU, (void *)&ifr);
+ close(fd);
+ if (ok < 0) return -1;
+ return ifr.ifr_mtu;
+ #endif
+
+ return -1;
+}
+
+extern int rawnet_arch_get_mac(uint8_t mac[6]) {
+
+ #if defined(__linux__)
+
+ int fd;
+ struct ifreq ifr;
+ int ok;
+
+ if (!rawnet_device_name) return -1;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, rawnet_device_name);
+ ok = ioctl(fd, SIOCGIFHWADDR, &ifr);
+ close(fd);
+ if (ok < 0) return -1;
+ memcpy(mac, &ifr.ifr_hwaddr.sa_data, 6);
+ return 0;
+ #endif
+
+ return -1;
+}
+
+int rawnet_arch_status(void) {
+ return rawnet_pcap_fp ? 1 : 0;
+}
+
+
+#endif /* #ifdef HAVE_RAWNET */
diff --git a/src/rawnet/rawnetarch_vmnet.c b/src/rawnet/rawnetarch_vmnet.c
new file mode 100644
index 0000000..8a1cbb1
--- /dev/null
+++ b/src/rawnet/rawnetarch_vmnet.c
@@ -0,0 +1,281 @@
+/*
+ * OS X 10.10+
+ * vmnet support (clang -framework vmnet -framework Foundation)
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "rawnetarch.h"
+#include "rawnetsupp.h"
+
+
+static interface_ref interface;
+static uint8_t interface_mac[6];
+static uint8_t interface_fake_mac[6];
+static uint64_t interface_mtu;
+static uint64_t interface_packet_size;
+static uint8_t *interface_buffer = NULL;
+static vmnet_return_t interface_status;
+
+int rawnet_arch_init(void) {
+ interface = NULL;
+ return 1;
+}
+void rawnet_arch_pre_reset(void) {
+ /* NOP */
+}
+
+void rawnet_arch_post_reset(void) {
+ /* NOP */
+}
+
+int rawnet_arch_activate(const char *interface_name) {
+
+ xpc_object_t dict;
+ dispatch_queue_t q;
+ dispatch_semaphore_t sem;
+
+ /*
+ * there's no way to set the MAC address directly.
+ * using vmnet_interface_id_key w/ the previous interface id
+ * *MIGHT* re-use the previous MAC address.
+ */
+
+ if (interface) return 1;
+
+ memset(interface_mac, 0, sizeof(interface_mac));
+ memset(interface_fake_mac, 0, sizeof(interface_fake_mac));
+ interface_status = 0;
+ interface_mtu = 0;
+ interface_packet_size = 0;
+
+ dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, vmnet_operation_mode_key, VMNET_SHARED_MODE);
+ sem = dispatch_semaphore_create(0);
+ q = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
+
+ interface = vmnet_start_interface(dict, q, ^(vmnet_return_t status, xpc_object_t params){
+ interface_status = status;
+ if (status == VMNET_SUCCESS) {
+ const char *cp;
+ cp = xpc_dictionary_get_string(params, vmnet_mac_address_key);
+ fprintf(stderr, "vmnet mac: %s\n", cp);
+ sscanf(cp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &interface_mac[0],
+ &interface_mac[1],
+ &interface_mac[2],
+ &interface_mac[3],
+ &interface_mac[4],
+ &interface_mac[5]
+ );
+
+ interface_mtu = xpc_dictionary_get_uint64(params, vmnet_mtu_key);
+ interface_packet_size = xpc_dictionary_get_uint64(params, vmnet_max_packet_size_key);
+
+ fprintf(stderr, "vmnet mtu: %u\n", (unsigned)interface_mtu);
+
+ }
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+ if (interface_status == VMNET_SUCCESS) {
+ interface_buffer = (uint8_t *)malloc(interface_packet_size);
+
+ /* copy mac to fake mac */
+ memcpy(interface_fake_mac, interface_mac, 6);
+
+ } else {
+ log_message(rawnet_arch_log, "vmnet_start_interface failed");
+ if (interface) {
+ vmnet_stop_interface(interface, q, ^(vmnet_return_t status){
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ interface = NULL;
+ }
+ }
+
+
+ dispatch_release(sem);
+ xpc_release(dict);
+ return interface_status == VMNET_SUCCESS;
+}
+
+void rawnet_arch_deactivate(void) {
+
+ dispatch_queue_t q;
+ dispatch_semaphore_t sem;
+
+
+ if (interface) {
+ sem = dispatch_semaphore_create(0);
+ q = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
+
+ vmnet_stop_interface(interface, q, ^(vmnet_return_t status){
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ dispatch_release(sem);
+
+ interface = NULL;
+ interface_status = 0;
+ }
+ free(interface_buffer);
+ interface_buffer = NULL;
+
+}
+
+void rawnet_arch_set_mac(const uint8_t mac[6]) {
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+#endif
+ memcpy(interface_fake_mac, mac, 6);
+}
+void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2]) {
+ /* NOP */
+}
+
+void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash) {
+ /* NOP */
+}
+
+void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) {
+ /* NOP */
+}
+
+
+int rawnet_arch_read(void *buffer, int nbyte) {
+
+ int count = 1;
+ int xfer;
+ vmnet_return_t st;
+ struct vmpktdesc v;
+ struct iovec iov;
+
+ iov.iov_base = interface_buffer;
+ iov.iov_len = interface_packet_size;
+
+ v.vm_pkt_size = interface_packet_size;
+ v.vm_pkt_iov = &iov;
+ v.vm_pkt_iovcnt = 1;
+ v.vm_flags = 0;
+
+ st = vmnet_read(interface, &v, &count);
+ if (st != VMNET_SUCCESS) {
+ log_message(rawnet_arch_log, "vmnet_read failed!");
+ return -1;
+ }
+
+ if (count < 1) {
+ return 0;
+ }
+
+ rawnet_fix_incoming_packet(interface_buffer, v.vm_pkt_size, interface_mac, interface_fake_mac);
+
+ // iov.iov_len is not updated with the read count, apparently.
+ /* don't sebug multicast packets */
+ if (interface_buffer[0] == 0xff || (interface_buffer[0] & 0x01) == 0 ) {
+ fprintf(stderr, "\nrawnet_arch_receive: %u\n", (unsigned)v.vm_pkt_size);
+ rawnet_hexdump(interface_buffer, v.vm_pkt_size);
+ }
+
+ xfer = v.vm_pkt_size;
+ memcpy(buffer, interface_buffer, xfer);
+
+ return xfer;
+}
+
+int rawnet_arch_write(const void *buffer, int nbyte) {
+
+ int count = 1;
+ vmnet_return_t st;
+ struct vmpktdesc v;
+ struct iovec iov;
+
+ if (nbyte <= 0) return 0;
+
+ if (nbyte > interface_packet_size) {
+ log_message(rawnet_arch_log, "packet is too big: %d", nbyte);
+ return -1;
+ }
+
+ /* copy the buffer and fix the source mac address. */
+ memcpy(interface_buffer, buffer, nbyte);
+ rawnet_fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac);
+
+ iov.iov_base = interface_buffer;
+ iov.iov_len = nbyte;
+
+ v.vm_pkt_size = nbyte;
+ v.vm_pkt_iov = &iov;
+ v.vm_pkt_iovcnt = 1;
+ v.vm_flags = 0;
+
+
+ fprintf(stderr, "\nrawnet_arch_transmit: %u\n", (unsigned)iov.iov_len);
+ rawnet_hexdump(interface_buffer, v.vm_pkt_size);
+
+
+ st = vmnet_write(interface, &v, &count);
+
+ if (st != VMNET_SUCCESS) {
+ log_message(rawnet_arch_log, "vmnet_write failed!");
+ return -1;
+ }
+ return nbyte;
+}
+
+
+
+
+static unsigned adapter_index = 0;
+int rawnet_arch_enumadapter_open(void) {
+ adapter_index = 0;
+ return 1;
+}
+
+int rawnet_arch_enumadapter(char **ppname, char **ppdescription) {
+
+ if (adapter_index == 0) {
+ ++adapter_index;
+ if (ppname) *ppname = lib_stralloc("vmnet");
+ if (ppdescription) *ppdescription = lib_stralloc("vmnet");
+ return 1;
+ }
+ return 0;
+}
+
+int rawnet_arch_enumadapter_close(void) {
+ return 1;
+}
+
+char *rawnet_arch_get_standard_interface(void) {
+ return lib_stralloc("vmnet");
+}
+
+int rawnet_arch_get_mtu(void) {
+ return interface ? interface_mtu : -1;
+}
+
+int rawnet_arch_get_mac(uint8_t mac[6]) {
+ if (interface) {
+ memcpy(mac, interface_mac, 6);
+ return 1;
+ }
+ return -1;
+}
+
+
+int rawnet_arch_status(void) {
+ return interface ? 1 : 0;
+}
+
diff --git a/src/rawnet/rawnetarch_vmnet_helper.c b/src/rawnet/rawnetarch_vmnet_helper.c
new file mode 100644
index 0000000..1e8eb23
--- /dev/null
+++ b/src/rawnet/rawnetarch_vmnet_helper.c
@@ -0,0 +1,512 @@
+/*
+ * OS X 10.10+
+ * vmnet support (clang -framework vmnet -framework Foundation)
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "rawnetarch.h"
+#include "rawnetsupp.h"
+
+
+enum {
+ MSG_QUIT,
+ MSG_STATUS,
+ MSG_READ,
+ MSG_WRITE
+};
+#define MAKE_MSG(msg, extra) (msg | ((extra) << 8))
+
+static uint8_t interface_mac[6];
+static uint8_t interface_fake_mac[6];
+static uint32_t interface_mtu;
+static uint32_t interface_packet_size;
+static uint8_t *interface_buffer = NULL;
+
+static pid_t interface_pid = 0;
+static int interface_pipe[2];
+
+
+static pid_t safe_waitpid(pid_t pid, int *stat_loc, int options) {
+ for(;;) {
+ pid_t rv = waitpid(pid, stat_loc,options);
+ if (rv < 0 && errno == EINTR) continue;
+ return rv;
+ }
+}
+
+static ssize_t safe_read(void *data, size_t nbytes) {
+ for (;;) {
+ ssize_t rv = read(interface_pipe[0], data, nbytes);
+ if (rv < 0 && errno == EINTR) continue;
+ return rv;
+ }
+}
+
+static ssize_t safe_readv(const struct iovec *iov, int iovcnt) {
+
+ for(;;) {
+ ssize_t rv = readv(interface_pipe[0], iov, iovcnt);
+ if (rv < 0 && errno == EINTR) continue;
+ return rv;
+ }
+}
+
+
+static ssize_t safe_write(const void *data, size_t nbytes) {
+ for (;;) {
+ ssize_t rv = write(interface_pipe[1], data, nbytes);
+ if (rv < 0 && errno == EINTR) continue;
+ return rv;
+ }
+}
+
+static ssize_t safe_writev(const struct iovec *iov, int iovcnt) {
+
+ for(;;) {
+ ssize_t rv = writev(interface_pipe[1], iov, iovcnt);
+ if (rv < 0 && errno == EINTR) continue;
+ return rv;
+ }
+}
+
+/* block the sigpipe signal */
+static int block_pipe(struct sigaction *oact) {
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_IGN;
+ act.sa_flags = SA_RESTART;
+
+ return sigaction(SIGPIPE, &act, oact);
+}
+static int restore_pipe(const struct sigaction *oact) {
+ return sigaction(SIGPIPE, oact, NULL);
+}
+
+#if 0
+static int block_pipe(sigset_t *oldset) {
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ sigaddset(&set, SIGCHLD);
+
+ return sigprocmask(SIG_BLOCK, &set, oldset);
+}
+#endif
+
+static int check_child_status(void) {
+ pid_t pid;
+ int stat;
+ pid = safe_waitpid(interface_pid, &stat, WNOHANG);
+
+ if (pid < 0 && errno == ECHILD) {
+ fprintf(stderr, "child process does not exist.\n");
+ close(interface_pipe[0]);
+ close(interface_pipe[1]);
+ interface_pid = 0;
+ return 0;
+ }
+ if (pid == interface_pid) {
+ if (WIFEXITED(stat)) fprintf(stderr, "child process exited.\n");
+ if (WIFSIGNALED(stat)) fprintf(stderr, "child process signalled.\n");
+
+ close(interface_pipe[0]);
+ close(interface_pipe[1]);
+ interface_pid = 0;
+ return 0;
+ }
+ return 1;
+}
+
+static char *get_relative_path(const char *leaf) {
+
+ uint32_t size = 0;
+ char *buffer = 0;
+ int ok;
+ char *cp;
+ int l;
+
+ l = strlen(leaf);
+ ok = _NSGetExecutablePath(NULL, &size);
+ size += l + 1;
+ buffer = malloc(size);
+ if (buffer) {
+ ok = _NSGetExecutablePath(buffer, &size);
+ if (ok < 0) {
+ free(buffer);
+ return NULL;
+ }
+ cp = strrchr(buffer, '/');
+ if (cp)
+ strcpy(cp + 1 , leaf);
+ else {
+ free(buffer);
+ buffer = NULL;
+ }
+ }
+ return buffer;
+}
+
+
+int rawnet_arch_init(void) {
+ //interface = NULL;
+ return 1;
+}
+void rawnet_arch_pre_reset(void) {
+ /* NOP */
+}
+
+void rawnet_arch_post_reset(void) {
+ /* NOP */
+}
+
+
+
+
+int rawnet_arch_activate(const char *interface_name) {
+
+
+ int ok;
+
+ char *argv[] = { "vmnet_helper", NULL };
+ char *path = NULL;
+
+ int pipe_stdin[2];
+ int pipe_stdout[2];
+
+ struct sigaction oldaction;
+
+
+ if (interface_pid > 0) return 1;
+
+ /* fd[0] = read, fd[1] = write */
+ ok = pipe(pipe_stdin);
+ if (ok < 0) { warn("pipe"); return 0; }
+
+ ok = pipe(pipe_stdout);
+ if (ok < 0) { warn("pipe"); return 0; }
+
+ block_pipe(&oldaction);
+
+#ifdef USE_POSIX_SPAWN
+ posix_spawn_file_actions_t actions;
+ posix_spawnattr_t attr;
+
+ posix_spawn_file_actions_init(&actions);
+ posix_spawnattr_init(&attr);
+
+
+ posix_spawn_file_actions_adddup2(&actions, pipe_stdin[0], STDIN_FILENO);
+ posix_spawn_file_actions_adddup2(&actions, pipe_stdout[1], STDOUT_FILENO);
+
+ posix_spawn_file_actions_addclose(&actions, pipe_stdin[0]);
+ posix_spawn_file_actions_addclose(&actions, pipe_stdin[1]);
+
+ posix_spawn_file_actions_addclose(&actions, pipe_stdout[0]);
+ posix_spawn_file_actions_addclose(&actions, pipe_stdout[1]);
+
+
+ path = get_relative_path("vmnet_helper");
+ ok = posix_spawn(&interface_pid, path, &actions, &attr, argv, NULL);
+ free(path);
+ posix_spawn_file_actions_destroy(&actions);
+ posix_spawnattr_destroy(&attr);
+#else
+ extern char **environ;
+ /* need to setsid() on the child */
+ path = get_relative_path("vmnet_helper");
+
+ interface_pid = fork();
+ if (interface_pid < 0) ok = 0;
+ if (interface_pid == 0) {
+
+ dup2(pipe_stdin[0], STDIN_FILENO);
+ dup2(pipe_stdout[1], STDOUT_FILENO);
+
+ close(pipe_stdin[0]);
+ close(pipe_stdin[1]);
+ close(pipe_stdout[0]);
+ close(pipe_stdout[1]);
+
+ setsid();
+ execve(path, argv, environ);
+ write(STDERR_FILENO, "execve failed\n", 14);
+ _exit(1);
+ }
+ free(path);
+#endif
+ close(pipe_stdin[0]);
+ close(pipe_stdout[1]);
+ /* posix spawn returns 0 on success, error code on failure. */
+
+ if (ok != 0) {
+ fprintf(stderr, "posix_spawn vmnet_helper failed: %d\n", ok);
+ close(pipe_stdin[1]);
+ close(pipe_stdout[0]);
+ interface_pid = -1;
+ return 0;
+ }
+
+ interface_pipe[0] = pipe_stdout[0];
+ interface_pipe[1] = pipe_stdin[1];
+
+ /* now get the mac/mtu/etc */
+
+ uint32_t msg = MAKE_MSG(MSG_STATUS, 0);
+ ok = safe_write(&msg, 4);
+ if (ok != 4) goto fail;
+
+ ok = safe_read(&msg, 4);
+ if (ok != 4) goto fail;
+
+ if (msg != MAKE_MSG(MSG_STATUS, 6 + 4 + 4)) goto fail;
+
+ struct iovec iov[3];
+ iov[0].iov_len = 6;
+ iov[0].iov_base = interface_mac;
+ iov[1].iov_len = 4;
+ iov[1].iov_base = &interface_mtu;
+ iov[2].iov_len = 4;
+ iov[2].iov_base = &interface_packet_size;
+
+ ok = safe_readv(iov, 3);
+ if (ok != 6 + 4 + 4) goto fail;
+
+ /* copy mac to fake mac */
+ memcpy(interface_fake_mac, interface_mac, 6);
+
+ /* sanity check */
+ /* expect MTU = 1500, packet_size = 1518 */
+ if (interface_packet_size < 256) {
+ interface_packet_size = 1518;
+ }
+ interface_buffer = malloc(interface_packet_size);
+ if (!interface_buffer) goto fail;
+
+ restore_pipe(&oldaction);
+ return 1;
+
+fail:
+ close(interface_pipe[0]);
+ close(interface_pipe[1]);
+ safe_waitpid(interface_pid, NULL, 0);
+ interface_pid = 0;
+
+ restore_pipe(&oldaction);
+ return 0;
+}
+
+void rawnet_arch_deactivate(void) {
+
+ if (interface_pid) {
+ close(interface_pipe[0]);
+ close(interface_pipe[1]);
+ for(;;) {
+ int ok = waitpid(interface_pid, NULL, 0);
+ if (ok < 0 && errno == EINTR) continue;
+ break;
+ }
+ interface_pid = 0;
+ }
+ free(interface_buffer);
+ interface_buffer = NULL;
+}
+
+void rawnet_arch_set_mac(const uint8_t mac[6]) {
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message( rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+#endif
+ memcpy(interface_fake_mac, mac, 6);
+}
+void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2]) {
+ /* NOP */
+}
+
+void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash) {
+ /* NOP */
+}
+
+void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) {
+ /* NOP */
+}
+
+
+
+int rawnet_arch_read(void *buffer, int nbyte) {
+
+
+ uint32_t msg;
+ int ok;
+ int xfer;
+ struct sigaction oldaction;
+
+ if (interface_pid <= 0) return -1;
+
+ block_pipe(&oldaction);
+
+ msg = MAKE_MSG(MSG_READ, 0);
+
+ ok = safe_write(&msg, 4);
+ if (ok != 4) goto fail;
+
+ ok = safe_read(&msg, 4);
+ if (ok != 4) goto fail;
+
+ if ((msg & 0xff) != MSG_READ) goto fail;
+
+ xfer = msg >> 8;
+ if (xfer > interface_packet_size) {
+
+ fprintf(stderr, "packet size too big: %d\n", xfer);
+
+ /* drain the message ... */
+ while (xfer) {
+ int count = interface_packet_size;
+ if (count > xfer) count = xfer;
+ ok = safe_read(interface_buffer, count);
+ if (ok < 0) goto fail;
+ xfer -= ok;
+ }
+ return -1;
+ }
+
+ if (xfer == 0) return -1;
+
+ ok = safe_read(interface_buffer, xfer);
+ if (ok != xfer) goto fail;
+
+
+ rawnet_fix_incoming_packet(interface_buffer, xfer, interface_mac, interface_fake_mac);
+
+ /* don't sebug multicast packets */
+ if (interface_buffer[0] == 0xff || (interface_buffer[0] & 0x01) == 0 ) {
+ fprintf(stderr, "\nrawnet_arch_receive: %u\n", (unsigned)xfer);
+ rawnet_hexdump(interface_buffer, xfer);
+ }
+
+ if (xfer > nbyte) xfer = nbyte;
+ memcpy(buffer, interface_buffer, xfer);
+
+ restore_pipe(&oldaction);
+ return xfer;
+
+fail:
+ /* check if process still ok? */
+ check_child_status();
+ restore_pipe(&oldaction);
+ return -1;
+}
+
+int rawnet_arch_write(const void *buffer, int nbyte) {
+
+ int ok;
+ uint32_t msg;
+ struct iovec iov[2];
+ struct sigaction oldaction;
+
+ if (interface_pid <= 0) return -1;
+
+
+
+ if (nbyte <= 0) return 0;
+
+ if (nbyte > interface_packet_size) {
+ log_message(rawnet_arch_log, "packet is too big: %d", nbyte);
+ return -1;
+ }
+
+
+ /* copy the buffer and fix the source mac address. */
+ memcpy(interface_buffer, buffer, nbyte);
+ rawnet_fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac);
+
+
+ fprintf(stderr, "\nrawnet_arch_transmit: %u\n", (unsigned)nbyte);
+ rawnet_hexdump(interface_buffer, nbyte);
+
+
+ block_pipe(&oldaction);
+
+ msg = MAKE_MSG(MSG_WRITE, nbyte);
+
+ iov[0].iov_base = &msg;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = interface_buffer;
+ iov[1].iov_len = nbyte;
+
+
+ ok = safe_writev(iov, 2);
+ if (ok != 4 + nbyte) goto fail;
+
+ ok = safe_read(&msg, 4);
+ if (ok != 4) goto fail;
+
+ if (msg != MAKE_MSG(MSG_WRITE, nbyte)) goto fail;
+
+ restore_pipe(&oldaction);
+ return nbyte;
+
+fail:
+ check_child_status();
+ restore_pipe(&oldaction);
+ return -1;
+}
+
+
+
+
+static unsigned adapter_index = 0;
+int rawnet_arch_enumadapter_open(void) {
+ adapter_index = 0;
+ return 1;
+}
+
+int rawnet_arch_enumadapter(char **ppname, char **ppdescription) {
+
+ if (adapter_index == 0) {
+ ++adapter_index;
+ if (ppname) *ppname = lib_stralloc("vmnet");
+ if (ppdescription) *ppdescription = lib_stralloc("vmnet");
+ return 1;
+ }
+ return 0;
+}
+
+int rawnet_arch_enumadapter_close(void) {
+ return 1;
+}
+
+char *rawnet_arch_get_standard_interface(void) {
+ return lib_stralloc("vmnet");
+}
+
+int rawnet_arch_get_mtu(void) {
+ return interface_pid > 0 ? interface_mtu : -1;
+}
+
+int rawnet_arch_get_mac(uint8_t mac[6]) {
+ if (interface_pid > 0) {
+ memcpy(mac, interface_mac, 6);
+ return 1;
+ }
+ return -1;
+}
+
+
+int rawnet_arch_status(void) {
+ return interface_pid > 0 ? 1 : 0;
+}
+
diff --git a/src/rawnet/rawnetarch_win32.c b/src/rawnet/rawnetarch_win32.c
new file mode 100644
index 0000000..5da1a46
--- /dev/null
+++ b/src/rawnet/rawnetarch_win32.c
@@ -0,0 +1,579 @@
+/** \file rawnetarch_win32.c
+ * \brief Raw ethernet interface, Win32 stuff
+ *
+ * \author Spiro Trikaliotis
+ */
+
+/*
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+// #include "vice.h"
+
+#ifdef HAVE_RAWNET
+
+/* #define WPCAP */
+
+
+
+#include
+/* prevent bpf redeclaration in packet32 */
+#ifndef BPF_MAJOR_VERSION
+#define BPF_MAJOR_VERSION
+#endif
+#include
+#include
+#include
+
+
+#include
+#include
+#include
+#include
+
+// #include "lib.h"
+// #include "log.h"
+#include "rawnet.h"
+#include "rawnetarch.h"
+#include "rawnetsupp.h"
+
+typedef pcap_t *(*pcap_open_live_t)(const char *, int, int, int, char *);
+typedef void *(*pcap_close_t)(pcap_t *);
+typedef int (*pcap_dispatch_t)(pcap_t *, int, pcap_handler, u_char *);
+typedef int (*pcap_setnonblock_t)(pcap_t *, int, char *);
+typedef int (*pcap_datalink_t)(pcap_t *);
+typedef int (*pcap_findalldevs_t)(pcap_if_t **, char *);
+typedef void (*pcap_freealldevs_t)(pcap_if_t *);
+typedef int (*pcap_sendpacket_t)(pcap_t *p, u_char *buf, int size);
+typedef char *(*pcap_lookupdev_t)(char *);
+
+
+typedef VOID (*PacketCloseAdapter_t)(LPADAPTER lpAdapter);
+typedef LPADAPTER (*PacketOpenAdapter_t)(PCHAR AdapterName);
+typedef BOOLEAN (*PacketSendPacket_t)(LPADAPTER AdapterObject, LPPACKET pPacket, BOOLEAN Sync);
+typedef BOOLEAN (*PacketRequest_t)(LPADAPTER AdapterObject, BOOLEAN Set, PPACKET_OID_DATA OidData);
+
+
+/** #define RAWNET_DEBUG_ARCH 1 **/
+/** #define RAWNET_DEBUG_PKTDUMP 1 **/
+
+/* #define RAWNET_DEBUG_FRAMES - might be defined in rawnetarch.h ! */
+
+#define RAWNET_DEBUG_WARN 1 /* this should not be deactivated */
+
+static pcap_open_live_t p_pcap_open_live;
+static pcap_close_t p_pcap_close;
+static pcap_dispatch_t p_pcap_dispatch;
+static pcap_setnonblock_t p_pcap_setnonblock;
+static pcap_findalldevs_t p_pcap_findalldevs;
+static pcap_freealldevs_t p_pcap_freealldevs;
+static pcap_sendpacket_t p_pcap_sendpacket;
+static pcap_datalink_t p_pcap_datalink;
+static pcap_lookupdev_t p_pcap_lookupdev;
+
+static PacketCloseAdapter_t p_PacketCloseAdapter;
+static PacketOpenAdapter_t p_PacketOpenAdapter;
+static PacketSendPacket_t p_PacketSendPacket;
+static PacketRequest_t p_PacketRequest;
+
+static HINSTANCE pcap_library = NULL;
+static HINSTANCE packet_library = NULL;
+
+/* ------------------------------------------------------------------------- */
+/* variables needed */
+
+//static log_t rawnet_arch_log = LOG_ERR;
+
+static pcap_if_t *EthernetPcapNextDev = NULL;
+static pcap_if_t *EthernetPcapAlldevs = NULL;
+static pcap_t *EthernetPcapFP = NULL;
+static char *rawnet_device_name = NULL;
+
+static char EthernetPcapErrbuf[PCAP_ERRBUF_SIZE];
+
+#ifdef RAWNET_DEBUG_PKTDUMP
+
+static void debug_output(const char *text, uint8_t *what, int count)
+{
+ char buffer[256];
+ char *p = buffer;
+ char *pbuffer1 = what;
+ int len1 = count;
+ int i;
+
+ sprintf(buffer, "\n%s: length = %u\n", text, len1);
+ OutputDebugString(buffer);
+ do {
+ p = buffer;
+ for (i = 0; (i < 8) && len1 > 0; len1--, i++) {
+ sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++);
+ p += 3;
+ }
+ *(p - 1) = '\n';
+ *p = 0;
+ OutputDebugString(buffer);
+ } while (len1 > 0);
+}
+#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
+
+
+static void EthernetPcapFreeLibrary(void)
+{
+ if (pcap_library) {
+ if (!FreeLibrary(pcap_library)) {
+ log_message(rawnet_arch_log, "FreeLibrary WPCAP.DLL failed!");
+ }
+ pcap_library = NULL;
+
+ if (packet_library) FreeLibrary(packet_library);
+ packet_library = NULL;
+
+ p_pcap_open_live = NULL;
+ p_pcap_close = NULL;
+ p_pcap_dispatch = NULL;
+ p_pcap_setnonblock = NULL;
+ p_pcap_findalldevs = NULL;
+ p_pcap_freealldevs = NULL;
+ p_pcap_sendpacket = NULL;
+ p_pcap_datalink = NULL;
+ p_pcap_lookupdev = NULL;
+
+ p_PacketOpenAdapter = NULL;
+ p_PacketCloseAdapter = NULL;
+ p_PacketSendPacket = NULL;
+ p_PacketRequest = NULL;
+ }
+}
+
+/* since I don't like typing too much... */
+#define GET_PROC_ADDRESS_AND_TEST( _name_ ) \
+ p_##_name_ = (_name_##_t) GetProcAddress(x, #_name_); \
+ if (!p_##_name_ ) { \
+ log_message(rawnet_arch_log, "GetProcAddress " #_name_ " failed!"); \
+ EthernetPcapFreeLibrary(); \
+ return FALSE; \
+ }
+
+static BOOL EthernetPcapLoadLibrary(void)
+{
+ /*
+ * npcap is c:\System32\Npcap\wpcap.dll
+ * winpcap is c:\System32\wpcap.dll
+ *
+ */
+ HINSTANCE x = NULL;
+ if (!pcap_library) {
+ /* This inserts c:\System32\Npcap\ into the search path. */
+ char buffer[512];
+ unsigned length;
+ length = GetSystemDirectory(buffer, sizeof(buffer) - sizeof("\\Npcap"));
+ if (length) {
+ strcat(buffer + length, "\\Npcap");
+ SetDllDirectory(buffer);
+ }
+
+ pcap_library = LoadLibrary(TEXT("wpcap.dll"));
+
+ if (!pcap_library) {
+ log_message(rawnet_arch_log, "LoadLibrary WPCAP.DLL failed!");
+ return FALSE;
+ }
+
+ x = pcap_library;
+ GET_PROC_ADDRESS_AND_TEST(pcap_open_live);
+ GET_PROC_ADDRESS_AND_TEST(pcap_close);
+ GET_PROC_ADDRESS_AND_TEST(pcap_dispatch);
+ GET_PROC_ADDRESS_AND_TEST(pcap_setnonblock);
+ GET_PROC_ADDRESS_AND_TEST(pcap_findalldevs);
+ GET_PROC_ADDRESS_AND_TEST(pcap_freealldevs);
+ GET_PROC_ADDRESS_AND_TEST(pcap_sendpacket);
+ GET_PROC_ADDRESS_AND_TEST(pcap_datalink);
+ GET_PROC_ADDRESS_AND_TEST(pcap_lookupdev);
+ }
+
+ if (!packet_library) {
+ packet_library = LoadLibrary(TEXT("Packet.dll"));
+
+ if (!packet_library) {
+ log_message(rawnet_arch_log, "LoadLibrary Packet.dll failed!");
+ return FALSE;
+ }
+
+ x = packet_library;
+ GET_PROC_ADDRESS_AND_TEST(PacketOpenAdapter);
+ GET_PROC_ADDRESS_AND_TEST(PacketCloseAdapter);
+ GET_PROC_ADDRESS_AND_TEST(PacketSendPacket);
+ GET_PROC_ADDRESS_AND_TEST(PacketRequest);
+ }
+
+ return TRUE;
+}
+
+#undef GET_PROC_ADDRESS_AND_TEST
+
+
+/*
+ These functions let the UI enumerate the available interfaces.
+
+ First, rawnet_arch_enumadapter_open() is used to start enumeration.
+
+ rawnet_arch_enumadapter is then used to gather information for each adapter present
+ on the system, where:
+
+ ppname points to a pointer which will hold the name of the interface
+ ppdescription points to a pointer which will hold the description of the interface
+
+ For each of these parameters, new memory is allocated, so it has to be
+ freed with lib_free().
+
+ rawnet_arch_enumadapter_close() must be used to stop processing.
+
+ Each function returns 1 on success, and 0 on failure.
+ rawnet_arch_enumadapter() only fails if there is no more adpater; in this case,
+ *ppname and *ppdescription are not altered.
+*/
+int rawnet_arch_enumadapter_open(void)
+{
+ if (!EthernetPcapLoadLibrary()) {
+ return 0;
+ }
+
+ if ((*p_pcap_findalldevs)(&EthernetPcapAlldevs, EthernetPcapErrbuf) == -1) {
+ log_message(rawnet_arch_log, "ERROR in rawnet_arch_enumadapter_open: pcap_findalldevs: '%s'", EthernetPcapErrbuf);
+ return 0;
+ }
+
+ if (!EthernetPcapAlldevs) {
+ log_message(rawnet_arch_log, "ERROR in rawnet_arch_enumadapter_open, finding all pcap devices - Do we have the necessary privilege rights?");
+ return 0;
+ }
+
+ EthernetPcapNextDev = EthernetPcapAlldevs;
+
+ return 1;
+}
+
+int rawnet_arch_enumadapter(char **ppname, char **ppdescription)
+{
+ if (!EthernetPcapNextDev) {
+ return 0;
+ }
+
+ *ppname = lib_stralloc(EthernetPcapNextDev->name);
+ *ppdescription = lib_stralloc(EthernetPcapNextDev->description);
+
+ printf("%s: %s\n",
+ EthernetPcapNextDev->name ? EthernetPcapNextDev->name : "",
+ EthernetPcapNextDev->description ? EthernetPcapNextDev->description : ""
+ );
+ EthernetPcapNextDev = EthernetPcapNextDev->next;
+
+ return 1;
+}
+
+int rawnet_arch_enumadapter_close(void)
+{
+ if (EthernetPcapAlldevs) {
+ (*p_pcap_freealldevs)(EthernetPcapAlldevs);
+ EthernetPcapAlldevs = NULL;
+ }
+ return 1;
+}
+
+static BOOL EthernetPcapOpenAdapter(const char *interface_name)
+{
+ pcap_if_t *EthernetPcapDevice = NULL;
+
+ if (!rawnet_enumadapter_open()) {
+ return FALSE;
+ } else {
+ /* look if we can find the specified adapter */
+ char *pname;
+ char *pdescription;
+ BOOL found = FALSE;
+
+ if (interface_name) {
+ /* we have an interface name, try it */
+ EthernetPcapDevice = EthernetPcapAlldevs;
+
+ while (rawnet_enumadapter(&pname, &pdescription)) {
+ if (strcmp(pname, interface_name) == 0) {
+ found = TRUE;
+ }
+ lib_free(pname);
+ lib_free(pdescription);
+ if (found) break;
+ EthernetPcapDevice = EthernetPcapNextDev;
+ }
+ }
+
+ if (!found) {
+ /* just take the first adapter */
+ EthernetPcapDevice = EthernetPcapAlldevs;
+ }
+ }
+
+ EthernetPcapFP = (*p_pcap_open_live)(EthernetPcapDevice->name, 1700, 1, 20, EthernetPcapErrbuf);
+ if (EthernetPcapFP == NULL) {
+ log_message(rawnet_arch_log, "ERROR opening adapter: '%s'", EthernetPcapErrbuf);
+ rawnet_enumadapter_close();
+ return FALSE;
+ }
+
+ /* Check the link layer. We support only Ethernet for simplicity. */
+ if ((*p_pcap_datalink)(EthernetPcapFP) != DLT_EN10MB) {
+ log_message(rawnet_arch_log, "ERROR: Ethernet works only on Ethernet networks.");
+ rawnet_enumadapter_close();
+ (*p_pcap_close)(EthernetPcapFP);
+ EthernetPcapFP = NULL;
+ return FALSE;
+ }
+
+ if ((*p_pcap_setnonblock)(EthernetPcapFP, 1, EthernetPcapErrbuf) < 0) {
+ log_message(rawnet_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", EthernetPcapErrbuf);
+ }
+
+ rawnet_device_name = strdup(EthernetPcapDevice->name);
+ rawnet_enumadapter_close();
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------- */
+/* the architecture-dependend functions */
+
+int rawnet_arch_init(void)
+{
+ //rawnet_arch_log = log_open("EthernetARCH");
+
+ if (!EthernetPcapLoadLibrary()) {
+ return 0;
+ }
+
+ return 1;
+}
+
+void rawnet_arch_pre_reset( void )
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log, "rawnet_arch_pre_reset().");
+#endif
+}
+
+void rawnet_arch_post_reset( void )
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log, "rawnet_arch_post_reset().");
+#endif
+}
+
+int rawnet_arch_activate(const char *interface_name)
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log, "rawnet_arch_activate().");
+#endif
+ if (!EthernetPcapOpenAdapter(interface_name)) {
+ return 0;
+ }
+ return 1;
+}
+
+void rawnet_arch_deactivate( void )
+{
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log, "rawnet_arch_deactivate().");
+#endif
+}
+
+void rawnet_arch_set_mac( const uint8_t mac[6] )
+{
+#if defined(RAWNET_DEBUG_ARCH) || defined(RAWNET_DEBUG_FRAMES)
+ log_message(rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+#endif
+}
+
+void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2])
+{
+#if defined(RAWNET_DEBUG_ARCH) || defined(RAWNET_DEBUG_FRAMES)
+ log_message(rawnet_arch_log, "New hash filter set: %08X:%08X.", hash_mask[1], hash_mask[0]);
+#endif
+}
+
+/* int bBroadcast - broadcast */
+/* int bIA - individual address (IA) */
+/* int bMulticast - multicast if address passes the hash filter */
+/* int bCorrect - accept correct frames */
+/* int bPromiscuous - promiscuous mode */
+/* int bIAHash - accept if IA passes the hash filter */
+
+
+void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash)
+{
+#if defined(RAWNET_DEBUG_ARCH) || defined(RAWNET_DEBUG_FRAMES)
+ log_message(rawnet_arch_log, "rawnet_arch_recv_ctl() called with the following parameters:" );
+ log_message(rawnet_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" );
+ log_message(rawnet_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE" );
+ log_message(rawnet_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" );
+ log_message(rawnet_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" );
+ log_message(rawnet_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" );
+ log_message(rawnet_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" );
+#endif
+}
+
+void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver)
+{
+#if defined(RAWNET_DEBUG_ARCH) || defined(RAWNET_DEBUG_FRAMES)
+ log_message(rawnet_arch_log, "rawnet_arch_line_ctl() called with the following parameters:" );
+ log_message(rawnet_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" );
+ log_message(rawnet_arch_log, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" );
+#endif
+}
+
+typedef struct Ethernet_PCAP_internal_s {
+ unsigned int len;
+ uint8_t *buffer;
+} Ethernet_PCAP_internal_t;
+
+/* Callback function invoked by libpcap for every incoming packet */
+static void EthernetPcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
+{
+ Ethernet_PCAP_internal_t *pinternal = (void*)param;
+
+ /* determine the count of bytes which has been returned,
+ * but make sure not to overrun the buffer
+ */
+ if (header->caplen < pinternal->len) {
+ pinternal->len = header->caplen;
+ }
+
+ memcpy(pinternal->buffer, pkt_data, pinternal->len);
+}
+
+/* the following function receives a frame.
+
+ If there's none, it returns a -1.
+ If there is one, it returns the length of the frame in bytes.
+
+ It copies the frame to *buffer and returns the number of copied
+ bytes as return value.
+
+ At most 'len' bytes are copied.
+*/
+static int rawnet_arch_receive_frame(Ethernet_PCAP_internal_t *pinternal)
+{
+ int ret = -1;
+
+ /* check if there is something to receive */
+ if ((*p_pcap_dispatch)(EthernetPcapFP, 1, EthernetPcapPacketHandler, (void*)pinternal) != 0) {
+ /* Something has been received */
+ ret = pinternal->len;
+ }
+
+#ifdef RAWNET_DEBUG_ARCH
+ log_message(rawnet_arch_log, "rawnet_arch_receive_frame() called, returns %d.", ret);
+#endif
+
+ return ret;
+}
+
+
+int rawnet_arch_read(void *buffer, int nbyte) {
+
+ int len;
+
+ Ethernet_PCAP_internal_t internal;
+
+ internal.len = nbyte;
+ internal.buffer = (uint8_t *)buffer;
+
+ len = rawnet_arch_receive_frame(&internal);
+
+ if (len <= 0) return len;
+
+#ifdef RAWNET_DEBUG_PKTDUMP
+ debug_output("Received frame: ", internal.buffer, internal.len);
+#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
+ return len;
+
+}
+
+
+int rawnet_arch_write(const void *buffer, int nbyte) {
+
+#ifdef RAWNET_DEBUG_PKTDUMP
+ debug_output("Transmit frame: ", buffer, nbyte);
+#endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
+
+ if ((*p_pcap_sendpacket)(EthernetPcapFP, (u_char *)buffer, nbyte) == -1) {
+ log_message(rawnet_arch_log, "WARNING! Could not send packet!");
+ return -1;
+ }
+ return nbyte;
+}
+
+
+char *rawnet_arch_get_standard_interface(void)
+{
+ char *dev, errbuf[PCAP_ERRBUF_SIZE];
+
+ if (!EthernetPcapLoadLibrary()) {
+ return NULL;
+ }
+
+ dev = lib_stralloc((*p_pcap_lookupdev)(errbuf));
+
+ return dev;
+}
+
+extern int rawnet_arch_get_mtu(void) {
+ return -1;
+}
+
+extern int rawnet_arch_get_mac(uint8_t mac[6]) {
+
+ int rv = -1;
+ LPADAPTER outp = NULL;
+ char buffer[sizeof(PACKET_OID_DATA) + 6];
+ PPACKET_OID_DATA data = (PPACKET_OID_DATA)buffer;
+
+
+ if (!packet_library) return -1;
+
+ /* 802.5 = token ring, 802.3 = wired ethernet */
+ data->Oid = OID_802_3_CURRENT_ADDRESS; // OID_802_3_CURRENT_ADDRESS ? OID_802_3_PERMANENT_ADDRESS ?
+ data->Length = 6;
+
+
+ outp = p_PacketOpenAdapter(rawnet_device_name);
+ if (!outp || outp->hFile == INVALID_HANDLE_VALUE) return -1;
+
+ if (p_PacketRequest(outp, FALSE, data)) {
+ memcpy(mac, data->Data, 6);
+ rv = 0;
+ }
+ p_PacketCloseAdapter(outp);
+ return rv;
+}
+
+int rawnet_arch_status(void) {
+ return EthernetPcapFP ? 1 : 0;
+}
+
+
+#endif /* #ifdef HAVE_RAWNET */
diff --git a/src/rawnet/rawnetsupp.c b/src/rawnet/rawnetsupp.c
new file mode 100644
index 0000000..5fb6db8
--- /dev/null
+++ b/src/rawnet/rawnetsupp.c
@@ -0,0 +1,372 @@
+/*
+ * This file is a consolidation of functions required for tfe
+ * emulation taken from the following files
+ *
+ * lib.c - Library functions.
+ * util.c - Miscellaneous utility functions.
+ * crc32.c
+ *
+ * Written by
+ * Andreas Boose
+ * Ettore Perazzoli
+ * Andreas Matthies
+ * Tibor Biczo
+ * Spiro Trikaliotis *
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+
+#include "rawnetsupp.h"
+
+
+
+#define CRC32_POLY 0xedb88320
+static unsigned long crc32_table[256];
+static int crc32_is_initialized = 0;
+
+void lib_free(void *ptr) {
+ free(ptr);
+}
+
+void *lib_malloc(size_t size) {
+
+ void *ptr = malloc(size);
+
+ if (ptr == NULL && size > 0) {
+ perror("lib_malloc");
+ exit(-1);
+ }
+
+ return ptr;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Malloc enough space for `str', copy `str' into it and return its
+ address. */
+char *lib_stralloc(const char *str) {
+ char *ptr;
+
+ if (str == NULL) {
+ fprintf(stderr, "lib_stralloc\n");
+ exit(-1);
+ }
+
+ ptr = strdup(str);
+ if (!ptr) {
+ perror("lib_stralloc");
+ exit(-1);
+ }
+
+ return ptr;
+}
+
+
+
+/* Like realloc, but abort if not enough memory is available. */
+void *lib_realloc(void *ptr, size_t size) {
+
+
+ void *new_ptr = realloc(ptr, size);
+
+ if (new_ptr == NULL) {
+ perror("lib_realloc");
+ exit(-1);
+ }
+
+ return new_ptr;
+}
+
+// Util Stuff
+
+/* Set a new value to the dynamically allocated string *str.
+ Returns `-1' if nothing has to be done. */
+int util_string_set(char **str, const char *new_value) {
+ if (*str == NULL) {
+ if (new_value != NULL)
+ *str = lib_stralloc(new_value);
+ } else {
+ if (new_value == NULL) {
+ lib_free(*str);
+ *str = NULL;
+ } else {
+ /* Skip copy if src and dest are already the same. */
+ if (strcmp(*str, new_value) == 0)
+ return -1;
+
+ *str = (char *)lib_realloc(*str, strlen(new_value) + 1);
+ strcpy(*str, new_value);
+ }
+ }
+ return 0;
+}
+
+
+// crc32 Stuff
+
+unsigned long crc32_buf(const char *buffer, unsigned int len) {
+ int i, j;
+ unsigned long crc, c;
+ const char *p;
+
+ if (!crc32_is_initialized) {
+ for (i = 0; i < 256; i++) {
+ c = (unsigned long) i;
+ for (j = 0; j < 8; j++)
+ c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1;
+ crc32_table[i] = c;
+ }
+ crc32_is_initialized = 1;
+ }
+
+ crc = 0xffffffff;
+ for (p = buffer; len > 0; ++p, --len)
+ crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff];
+
+ return ~crc;
+}
+
+void rawnet_hexdump(const void *what, int count) {
+ static const char hex[] = "0123456789abcdef";
+ char buffer1[16 * 3 + 1];
+ char buffer2[16 + 1];
+ unsigned offset;
+ unsigned char *cp = (unsigned char *)what;
+
+
+ offset = 0;
+ while (count > 0) {
+ unsigned char x = *cp++;
+
+ buffer1[offset * 3] = hex[x >> 4];
+ buffer1[offset * 3 + 1] = hex[x & 0x0f];
+ buffer1[offset * 3 + 2] = ' ';
+
+ buffer2[offset] = (x < 0x80) && isprint(x) ? x : '.';
+
+
+ --count;
+ ++offset;
+ if (offset == 16 || count == 0) {
+ buffer1[offset * 3] = 0;
+ buffer2[offset] = 0;
+ fprintf(stderr, "%-50s %s\n", buffer1, buffer2);
+ offset = 0;
+ }
+ }
+}
+
+
+
+
+
+enum {
+ eth_dest = 0, // destination address
+ eth_src = 6, // source address
+ eth_type = 12, // packet type
+ eth_data = 14, // packet data
+};
+
+enum {
+ ip_ver_ihl = 0,
+ ip_tos = 1,
+ ip_len = 2,
+ ip_id = 4,
+ ip_frag = 6,
+ ip_ttl = 8,
+ ip_proto = 9,
+ ip_header_cksum = 10,
+ ip_src = 12,
+ ip_dest = 16,
+ ip_data = 20,
+};
+
+enum {
+ udp_source = 0, // source port
+ udp_dest = 2, // destination port
+ udp_len = 4, // length
+ udp_cksum = 6, // checksum
+ udp_data = 8, // total length udp header
+};
+
+enum {
+ bootp_op = 0, // operation
+ bootp_hw = 1, // hardware type
+ bootp_hlen = 2, // hardware len
+ bootp_hp = 3, // hops
+ bootp_transid = 4, // transaction id
+ bootp_secs = 8, // seconds since start
+ bootp_flags = 10, // flags
+ bootp_ipaddr = 12, // ip address knwon by client
+ bootp_ipclient = 16, // client ip from server
+ bootp_ipserver = 20, // server ip
+ bootp_ipgateway = 24, // gateway ip
+ bootp_client_hrd = 28, // client mac address
+ bootp_spare = 34,
+ bootp_host = 44,
+ bootp_fname = 108,
+ bootp_data = 236, // total length bootp packet
+};
+
+enum {
+ arp_hw = 14, // hw type (eth = 0001)
+ arp_proto = 16, // protocol (ip = 0800)
+ arp_hwlen = 18, // hw addr len (eth = 06)
+ arp_protolen = 19, // proto addr len (ip = 04)
+ arp_op = 20, // request = 0001, reply = 0002
+ arp_shw = 22, // sender hw addr
+ arp_sp = 28, // sender proto addr
+ arp_thw = 32, // target hw addr
+ arp_tp = 38, // target protoaddr
+ arp_data = 42, // total length of packet
+};
+
+enum {
+ dhcp_discover = 1,
+ dhcp_offer = 2,
+ dhcp_request = 3,
+ dhcp_decline = 4,
+ dhcp_pack = 5,
+ dhcp_nack = 6,
+ dhcp_release = 7,
+ dhcp_inform = 8,
+};
+
+static uint8_t oo[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static uint8_t ff[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static int is_arp(const uint8_t *packet, unsigned size) {
+ return size == arp_data
+ && packet[12] == 0x08 && packet[13] == 0x06 /* ARP */
+ && packet[14] == 0x00 && packet[15] == 0x01 /* ethernet */
+ && packet[16] == 0x08 && packet[17] == 0x00 /* ipv4 */
+ && packet[18] == 0x06 /* hardware size */
+ && packet[19] == 0x04 /* protocol size */
+ ;
+}
+
+static int is_broadcast(const uint8_t *packet, unsigned size) {
+ return !memcmp(packet + 0, ff, 6);
+}
+
+static int is_unicast(const uint8_t *packet, unsigned size) {
+ return (*packet & 0x01) == 0;
+}
+
+static int is_multicast(const uint8_t *packet, unsigned size) {
+ return (*packet & 0x01) == 0x01 && !is_broadcast(packet, size);
+}
+
+static int is_dhcp_out(const uint8_t *packet, unsigned size) {
+ static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 };
+ return size >= 282
+ //&& !memcmp(&packet[0], ff, 6) /* broadcast */
+ && packet[12] == 0x08 && packet[13] == 0x00
+ && packet[14] == 0x45 /* version 4 */
+ && packet[23] == 0x11 /* UDP */
+ //&& !memcmp(&packet[26], oo, 4) /* source ip */
+ //&& !memcmp(&packet[30], ff, 4) /* dest ip */
+ && packet[34] == 0x00 && packet[35] == 0x44 /* source port */
+ && packet[36] == 0x00 && packet[37] == 0x43 /* dest port */
+ //&& packet[44] == 0x01 /* dhcp boot req */
+ && packet[43] == 0x01 /* ethernet */
+ && packet[44] == 0x06 /* 6 byte mac */
+ && !memcmp(&packet[278], cookie, 4)
+ ;
+}
+
+
+static int is_dhcp_in(const uint8_t *packet, unsigned size) {
+ static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 };
+ return size >= 282
+ //&& !memcmp(&packet[0], ff, 6) /* broadcast */
+ && packet[12] == 0x08 && packet[13] == 0x00
+ && packet[14] == 0x45 /* version 4 */
+ && packet[23] == 0x11 /* UDP */
+ //&& !memcmp(&packet[26], oo, 4) /* source ip */
+ //&& !memcmp(&packet[30], ff, 4) /* dest ip */
+ && packet[34] == 0x00 && packet[35] == 0x43 /* source port */
+ && packet[36] == 0x00 && packet[37] == 0x44 /* dest port */
+ //&& packet[44] == 0x01 /* dhcp boot req */
+ && packet[43] == 0x01 /* ethernet */
+ && packet[44] == 0x06 /* 6 byte mac */
+ && !memcmp(&packet[278], cookie, 4)
+ ;
+}
+
+static unsigned ip_checksum(const uint8_t *packet) {
+ unsigned x = 0;
+ unsigned i;
+ for (i = 0; i < ip_data; i += 2) {
+ if (i == ip_header_cksum) continue;
+ x += packet[eth_data + i + 0 ] << 8;
+ x += packet[eth_data + i + 1];
+ }
+
+ /* add the carry */
+ x += x >> 16;
+ x &= 0xffff;
+ return ~x & 0xffff;
+}
+
+void rawnet_fix_incoming_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) {
+
+ if (memcmp(packet + 0, real_mac, 6) == 0)
+ memcpy(packet + 0, fake_mac, 6);
+
+ /* dhcp request - fix the hardware address */
+ if (is_unicast(packet, size) && is_dhcp_in(packet, size)) {
+ if (!memcmp(packet + 70, real_mac, 6))
+ memcpy(packet + 70, fake_mac, 6);
+ return;
+ }
+
+}
+
+void rawnet_fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) {
+
+
+
+ if (memcmp(packet + 6, fake_mac, 6) == 0)
+ memcpy(packet + 6, real_mac, 6);
+
+ if (is_arp(packet, size)) {
+ /* sender mac address */
+ if (!memcmp(packet + 22, fake_mac, 6))
+ memcpy(packet + 22, real_mac, 6);
+ return;
+ }
+
+ /* dhcp request - fix the hardware address */
+ if (is_broadcast(packet, size) && is_dhcp_out(packet, size)) {
+
+ if (!memcmp(packet + 70, fake_mac, 6))
+ memcpy(packet + 70, real_mac, 6);
+ return;
+ }
+
+}
diff --git a/src/rawnet/rawnetsupp.h b/src/rawnet/rawnetsupp.h
new file mode 100644
index 0000000..012efad
--- /dev/null
+++ b/src/rawnet/rawnetsupp.h
@@ -0,0 +1,62 @@
+/*
+ * This file is a consolidation of functions required for tfe
+ * emulation taken from the following files
+ *
+ * lib.h - Library functions.
+ * util.h - Miscellaneous utility functions.
+ * crc32.h
+ *
+ * Written by
+ * Andreas Boose
+ * Ettore Perazzoli
+ * Manfred Spraul
+ * Andreas Matthies
+ * Tibor Biczo
+ * Spiro Trikaliotis *
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *
+ */
+
+
+
+#ifndef _TFESUPP_H
+#define _TFESUPP_H
+
+#include
+#include
+
+extern FILE* g_fh; // Filehandle for log file
+
+extern void *lib_malloc(size_t size);
+extern void *lib_realloc(void *p, size_t size);
+extern void lib_free(void *ptr);
+extern char *lib_stralloc(const char *str);
+
+extern int util_string_set(char **str, const char *new_value);
+
+extern unsigned long crc32_buf(const char *buffer, unsigned int len);
+
+extern void rawnet_hexdump(const void *what, int count);
+extern void rawnet_fix_incoming_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]);
+extern void rawnet_fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]);
+
+
+#define log_message(level,...) do { fprintf(stderr,__VA_ARGS__); fputs("\n", stderr); } while (0)
+#endif
diff --git a/src/rawnet/vmnet_helper.c b/src/rawnet/vmnet_helper.c
new file mode 100644
index 0000000..6d108d0
--- /dev/null
+++ b/src/rawnet/vmnet_helper.c
@@ -0,0 +1,331 @@
+/* vmnet helper */
+/* because it needs root permissions ... sigh */
+
+/*
+ * basicly... run as root, read messages from stdin, write to stdout.
+ */
+
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+static interface_ref interface;
+static uint8_t interface_mac[6];
+static long interface_mtu;
+static long interface_packet_size;
+static vmnet_return_t interface_status;
+
+static size_t buffer_size = 0;
+static uint8_t *buffer = NULL;
+
+enum {
+ MSG_QUIT,
+ MSG_STATUS,
+ MSG_READ,
+ MSG_WRITE
+};
+#define MAKE_MSG(msg, extra) (msg | ((extra) << 8))
+
+ssize_t safe_read(void *buffer, size_t nbyte) {
+
+ ssize_t rv;
+ for(;;) {
+ rv = read(STDIN_FILENO, buffer, nbyte);
+ if (rv < 0) {
+ if (errno == EINTR) continue;
+ err(1, "read");
+ }
+ break;
+ }
+ return rv;
+}
+
+
+ssize_t safe_readv(const struct iovec *iov, int iovcnt) {
+
+ ssize_t rv;
+ for(;;) {
+ rv = readv(STDIN_FILENO, iov, iovcnt);
+ if (rv < 0) {
+ if (errno == EINTR) continue;
+ err(1, "readv");
+ }
+ break;
+ }
+ return rv;
+}
+
+ssize_t safe_write(const void *buffer, size_t nbyte) {
+
+ ssize_t rv;
+ for(;;) {
+ rv = write(STDOUT_FILENO, buffer, nbyte);
+ if (rv < 0) {
+ if (errno == EINTR) continue;
+ err(1, "write");
+ }
+ break;
+ }
+ return rv;
+}
+
+ssize_t safe_writev(const struct iovec *iov, int iovcnt) {
+
+ ssize_t rv;
+ for(;;) {
+ rv = writev(STDOUT_FILENO, iov, iovcnt);
+ if (rv < 0) {
+ if (errno == EINTR) continue;
+ err(1, "writev");
+ }
+ break;
+ }
+ return rv;
+}
+
+
+void msg_status(uint32_t size) {
+ struct iovec iov[4];
+
+ uint32_t msg = MAKE_MSG(MSG_STATUS, 6 + 4 + 4);
+
+ iov[0].iov_len = 4;
+ iov[0].iov_base = &msg;
+
+ iov[1].iov_len = 6;
+ iov[1].iov_base = interface_mac;
+
+ iov[2].iov_len = 4;
+ iov[2].iov_base = &interface_mtu;
+
+ iov[3].iov_len = 4;
+ iov[3].iov_base = &interface_packet_size;
+
+
+ safe_writev(iov, 4);
+}
+
+int classify_mac(uint8_t *mac) {
+ if ((mac[0] & 0x01) == 0) return 1; /* unicast */
+ if (memcmp(mac, "\xff\xff\xff\xff\xff\xff", 6) == 0) return 0xff; /* broadcast */
+ return 2; /* multicast */
+}
+
+void msg_read(uint32_t flags) {
+ /* flag to block broadcast, multicast, etc? */
+
+ int count = 1;
+ int xfer;
+ vmnet_return_t st;
+ struct vmpktdesc v;
+ struct iovec iov[2];
+
+ uint32_t msg;
+
+
+ for(;;) {
+ int type;
+
+ iov[0].iov_base = buffer;
+ iov[0].iov_len = interface_packet_size;
+
+ v.vm_pkt_size = interface_packet_size;
+ v.vm_pkt_iov = iov;
+ v.vm_pkt_iovcnt = 1;
+ v.vm_flags = 0;
+
+ count = 1;
+ st = vmnet_read(interface, &v, &count);
+ if (st != VMNET_SUCCESS) errx(1, "vmnet_read");
+
+ if (count < 1) break;
+ /* todo -- skip multicast messages based on flag? */
+ type = classify_mac(buffer);
+ if (type == 2) continue; /* multicast */
+ break;
+ }
+
+ xfer = count == 1 ? v.vm_pkt_size : 0;
+ msg = MAKE_MSG(MSG_READ, xfer);
+ iov[0].iov_len = 4;
+ iov[0].iov_base = &msg;
+ iov[1].iov_len = xfer;
+ iov[1].iov_base = buffer;
+
+ safe_writev(iov, count == 1 ? 2 : 1);
+}
+
+
+void msg_write(uint32_t size) {
+
+ ssize_t ok;
+
+ int count = 1;
+ vmnet_return_t st;
+ struct vmpktdesc v;
+ struct iovec iov;
+ uint32_t msg;
+
+ if (size > interface_packet_size) errx(1, "packet too big");
+ for(;;) {
+ ok = safe_read(buffer, size);
+ if (ok < 0) err(1,"read");
+ if (ok != size) errx(1,"message truncated");
+ break;
+ }
+
+ iov.iov_base = buffer;
+ iov.iov_len = size;
+
+ v.vm_pkt_size = size;
+ v.vm_pkt_iov = &iov;
+ v.vm_pkt_iovcnt = 1;
+ v.vm_flags = 0;
+
+ st = vmnet_write(interface, &v, &count);
+
+ if (st != VMNET_SUCCESS) errx(1, "vmnet_write");
+
+
+ msg = MAKE_MSG(MSG_WRITE, size);
+ iov.iov_len = 4;
+ iov.iov_base = &msg;
+
+ safe_writev(&iov, 1);
+}
+
+void startup(void) {
+
+ xpc_object_t dict;
+ dispatch_queue_t q;
+ dispatch_semaphore_t sem;
+
+
+ memset(interface_mac, 0, sizeof(interface_mac));
+ interface_status = 0;
+ interface_mtu = 0;
+ interface_packet_size = 0;
+
+ dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, vmnet_operation_mode_key, VMNET_SHARED_MODE);
+ sem = dispatch_semaphore_create(0);
+ q = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
+
+ interface = vmnet_start_interface(dict, q, ^(vmnet_return_t status, xpc_object_t params){
+ interface_status = status;
+ if (status == VMNET_SUCCESS) {
+ const char *cp;
+ cp = xpc_dictionary_get_string(params, vmnet_mac_address_key);
+ fprintf(stderr, "vmnet mac: %s\n", cp);
+ sscanf(cp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &interface_mac[0],
+ &interface_mac[1],
+ &interface_mac[2],
+ &interface_mac[3],
+ &interface_mac[4],
+ &interface_mac[5]
+ );
+
+ interface_mtu = xpc_dictionary_get_uint64(params, vmnet_mtu_key);
+ interface_packet_size = xpc_dictionary_get_uint64(params, vmnet_max_packet_size_key);
+
+ fprintf(stderr, "vmnet mtu: %u\n", (unsigned)interface_mtu);
+ fprintf(stderr, "vmnet packet size: %u\n", (unsigned)interface_packet_size);
+
+ }
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+ if (interface_status == VMNET_SUCCESS) {
+ buffer_size = (interface_packet_size * 2 + 1023) & ~1023;
+ buffer = (uint8_t *)malloc(buffer_size);
+ } else {
+ if (interface) {
+ vmnet_stop_interface(interface, q, ^(vmnet_return_t status){
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ interface = NULL;
+ }
+ errx(1,"vmnet_start_interface failed");
+ }
+
+
+ dispatch_release(sem);
+ xpc_release(dict);
+
+}
+
+void shutdown(void) {
+
+ dispatch_queue_t q;
+ dispatch_semaphore_t sem;
+
+
+ if (interface) {
+ sem = dispatch_semaphore_create(0);
+ q = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
+
+ vmnet_stop_interface(interface, q, ^(vmnet_return_t status){
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ dispatch_release(sem);
+
+ interface = NULL;
+ interface_status = 0;
+ }
+ free(buffer);
+ buffer = NULL;
+ buffer_size = 0;
+
+}
+
+int main(int argc, char **argv) {
+
+
+ uint32_t msg;
+ uint32_t extra;
+ ssize_t ok;
+
+
+ startup();
+
+ for(;;) {
+ ok = safe_read(&msg, 4);
+ if (ok == 0) break;
+ if (ok != 4) errx(1,"read msg");
+
+ extra = msg >> 8;
+ msg = msg & 0xff;
+
+ switch(msg) {
+ case MSG_STATUS:
+ msg_status(extra);
+ break;
+ case MSG_QUIT:
+ shutdown();
+ exit(0);
+ case MSG_READ:
+ msg_read(extra);
+ break;
+ case MSG_WRITE:
+ msg_write(extra);
+ break;
+ }
+ }
+
+ shutdown();
+ exit(0);
+}
diff --git a/src/sim65816.c b/src/sim65816.c
index 99f846e..05e0191 100644
--- a/src/sim65816.c
+++ b/src/sim65816.c
@@ -14,6 +14,7 @@
#include "debug.h"
#include "glog.h"
#include "options.h"
+#include "version.h"
extern const char *g_config_gsplus_name_list[];
extern char g_config_gsplus_screenshot_dir[];
@@ -168,7 +169,7 @@ int g_imagewriter_paper = 0;
int g_imagewriter_banner = 0;
int g_config_iwm_vbl_count = 0;
-const char g_gsplus_version_str[] = "0.14";
+const char g_gsplus_version_str[] = GSPLUS_VERSION_STRING;
int g_pause=0; // OG Added pause
#define START_DCYCS (0.0)
diff --git a/src/string_extra.c b/src/string_extra.c
new file mode 100644
index 0000000..62adc93
--- /dev/null
+++ b/src/string_extra.c
@@ -0,0 +1,33 @@
+#include
+#include
+
+#include "string_extra.h"
+
+/* from MUSL/MIT */
+
+#ifndef HAVE_STRCASESTR
+char *strcasestr(const char *h, const char *n)
+{
+ size_t l = strlen(n);
+ for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h;
+ return 0;
+}
+#endif
+
+#ifndef HAVE_STRCASECMP
+int strcasecmp(const char *l, const char *r)
+{
+ for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++);
+ return tolower(*l) - tolower(*r);
+}
+#endif
+
+#ifndef HAVE_STRNCASECMP
+
+int strncasecmp(const char *l, const char *r, size_t n)
+{
+ if (!n--) return 0;
+ for (; *l && *r && n && (*l == *r || tolower(*l) == tolower(*r)); l++, r++, n--);
+ return tolower(*l) - tolower(*r);
+}
+#endif
\ No newline at end of file
diff --git a/src/string_extra.h.in b/src/string_extra.h.in
new file mode 100644
index 0000000..7fb7e0f
--- /dev/null
+++ b/src/string_extra.h.in
@@ -0,0 +1,20 @@
+#ifndef STRING_EXTRA_H
+#define STRING_EXTRA_H
+
+#cmakedefine HAVE_STRCASECMP
+#cmakedefine HAVE_STRNCASECMP
+#cmakedefine HAVE_STRCASESTR
+
+#ifndef HAVE_STRCASECMP
+extern int strcasecmp(const char *, const char *);
+#endif
+
+#ifdef HAVE_STRNCASESTR
+extern int strncasecmp(const char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_STRCASESTR
+extern char *strcasestr(const char *, const char *);
+#endif
+
+#endif
diff --git a/src/vars_hp b/src/vars_hp
deleted file mode 100644
index f598cff..0000000
--- a/src/vars_hp
+++ /dev/null
@@ -1,20 +0,0 @@
-
-TARGET = gsportx
-OBJECTS = engine_s.o $(OBJECTS1) sound_driver.o xdriver.o
-CC = cc -Ae +DA1.1
-CCOPTS = -O
-OPTS = -DNDEBUG
-SUFFIX =
-NAME = gsportx
-LDFLAGS =
-LDOPTS = -z
-LD = $(CC)
-EXTRA_LIBS = -lXext -lX11 -lcl -lc
-EXTRA_SPECIALS = 8inst_s 16inst_s 8size 16size size_s Alib.h
-
-AS = cc -Ae
-PERL = perl
-
-XOPTS = -DHPUX -I/usr/include/X11R5
-XLIBS = -L/usr/lib/X11R5 -L/opt/audio/lib
-
diff --git a/src/version.h.in b/src/version.h.in
new file mode 100644
index 0000000..244cccb
--- /dev/null
+++ b/src/version.h.in
@@ -0,0 +1 @@
+#define GSPLUS_VERSION_STRING "@gsplus_VERSION_MAJOR@.@gsplus_VERSION_MINOR@"
diff --git a/src/version.txt.in b/src/version.txt.in
new file mode 100644
index 0000000..1c4297e
--- /dev/null
+++ b/src/version.txt.in
@@ -0,0 +1 @@
+@gsplus_VERSION_MAJOR@.@gsplus_VERSION_MINOR@