Compare commits

..

61 Commits

Author SHA1 Message Date
Ryan Carsten Schmidt
d59a35d3a9
ci: remove macos-11; add macos-13; upgrade to checkout@v4 and upload-artifact@v4 (#69)
* ci: upgrade to checkout@v4 and upload-artifact@v4

* ci: remove macos-11; add macos-13

macos-11 will be removed by the end of June; replace it with macos-13.
macos-14 a.k.a. macos-latest is already covered by cmake-fat.yml.
2024-05-30 00:07:02 -04:00
ksherlock
9951892251
Create FUNDING.yml
eh
2024-04-05 09:49:09 -04:00
Kelvin Sherlock
79a8a93e03 update m68k cpu to match current upstream code, which includes a handful of bug fixes (mostly timing related). 2023-10-05 18:47:48 -04:00
Stefan
f619ed31b3
Fixed a few typos (#65) 2023-09-14 13:27:53 -04:00
Kelvin Sherlock
f460696b4f Add _RelString support, fix the case-sensitive flag in _CmpString 2023-09-02 14:50:02 -04:00
Kelvin Sherlock
6151ca1e87 use rl_attempted_completion_over to suppress standard filename completion logic. 2023-06-30 18:17:50 -04:00
Kelvin Sherlock
b9c7d9f95f submodule bump 2023-06-30 16:51:07 -04:00
Kelvin Sherlock
2dcb161f5e ResolveAliasFile - byte ptrs should only write 1 byte. 2022-11-23 13:28:53 -05:00
Ryan Schmidt
f08d67333d
Remove macOS 10.15 runner; add macOS 12 runner (#53)
The macOS 10.15 runner is deprecated and will be unsupported by December 1.
2022-11-21 21:14:20 -05:00
Ryan Schmidt
2e7e75a2a9
Return error from FSMakeFSSpec if file not found (#58)
Fixes #56
2022-11-21 21:13:29 -05:00
Ryan Schmidt
bdb1f4b2b9
Fix typos in comments (#57) 2022-11-19 23:52:37 -05:00
Ryan Schmidt
b8d17f4481
Don't overwrite user-specified CFLAGS and CXXFLAGS (#51)
* Check C and C++ compiler separately

It's possible (however unlikely) that the C++ compiler might be clang
but the C compiler might not be.

* Don't overwrite user-specified CFLAGS and CXXFLAGS
2022-11-19 22:32:44 -05:00
Ryan Schmidt
a76287876c
Add error message when loader can't load command (#55)
And change exit code from EX_CONFIG to EX_SOFTWARE.
2022-11-19 22:14:57 -05:00
Kelvin Sherlock
022d4cffe9 update github actions 2022-11-17 21:21:18 -05:00
Kelvin Sherlock
843ea2764c search for ragel and exit if not found. Also use found path when running ragel or lemon. 2022-11-17 21:07:45 -05:00
Ryan Schmidt
fc15ad1d81
Update version in CMakeLists.txt to 0.8.3 (#50)
Closes #45
2022-11-17 20:44:22 -05:00
Ryan Schmidt
7ac2a88974
Add newline after read() debug output (#44) 2022-11-15 19:01:21 -05:00
Ryan Schmidt
2703e00201
Use /bin/sh; quote shell variables (#46)
* On macOS, sh is /bin/sh not /usr/bin/sh

* Quote shell variables correctly
2022-11-15 19:00:16 -05:00
Kelvin Sherlock
5facdb095c version bump, allow MB/KB (vs M/K) for ram sizes 2022-10-11 21:11:36 -04:00
Kelvin Sherlock
194c36c89a add GetCurrentProcess / GetProcessInformation (SetVers)
GetProcessInformation is not currently implemented in a meaningful manner.
2022-10-10 21:07:58 -04:00
Kelvin Sherlock
3e2c02f796 .x is a binary extension used for xcoff object files (MrC, etc) 2022-10-10 21:07:13 -04:00
Kelvin Sherlock
48d869c6e8 more SANE tests. 2022-10-10 21:06:44 -04:00
ksherlock
8c911ab83d
Merge pull request #39 from potomak/patch-1
Add step to initialize and fetch submodules
2022-10-08 17:52:07 -04:00
Giovanni Cappellotto
b6b0abefbf
Add step to initialize and fetch submodules 2022-10-08 10:19:16 -04:00
ksherlock
67253a69e5
Update cmake-fat.yml 2022-09-23 18:11:20 -04:00
ksherlock
f3b3d221be
Merge pull request #37 from uliwitness/patch-1
Make build instructions no longer be on a single line.
2022-09-23 16:11:09 -04:00
Uli Kusterer
f4e3bd70a1
Make build instructions no longer be on a single line. 2022-09-23 19:34:06 +02:00
ksherlock
1925dc172b
Update .travis.yml 2021-05-31 00:33:52 -04:00
Kelvin Sherlock
4730a70874 include generated lemon code so lemon isn't needed. 2021-05-30 23:29:34 -04:00
Kelvin Sherlock
a70270be52 bump submodule 2021-05-30 23:00:53 -04:00
Kelvin Sherlock
f12b3789c4 typo 2021-05-30 22:42:13 -04:00
Kelvin Sherlock
6dfefb2343 bump submodule 2020-11-26 22:11:09 -05:00
ksherlock
35443c9aa8
Update cmake-fat.yml 2020-11-26 15:58:17 -05:00
ksherlock
fcdfe76817
Update cmake-fat.yml 2020-11-26 15:52:45 -05:00
ksherlock
a55b38104b
Update cmake-fat.yml 2020-11-26 15:51:18 -05:00
ksherlock
fb0d353716
Update cmake-fat.yml 2020-11-26 15:42:45 -05:00
ksherlock
7dc85091a3
Create cmake-fat.yml 2020-11-26 15:36:09 -05:00
Kelvin Sherlock
0cca883287 xp support for reading 80-bit extended numbers on platforms without a native 80-bit extended type.
previously this meant win32 and linux arm, now this includes Apple ARM as well.
2020-11-26 09:39:39 -05:00
ksherlock
58f2557df5
Update cmake.yml 2020-11-16 09:17:26 -05:00
ksherlock
031cdf0d08
Update cmake.yml 2020-11-16 09:11:13 -05:00
Kelvin Sherlock
c8310c0dbd fixup clang range warnings. 2020-11-05 18:53:52 -05:00
ksherlock
3480881001
Update cmake.yml 2020-11-05 18:50:36 -05:00
ksherlock
8f64923f9c
Update cmake.yml 2020-11-05 13:29:39 -05:00
ksherlock
7cb4c8cbc3
Create cmake.yml 2020-11-05 12:04:53 -05:00
Kelvin Sherlock
1a9cb0d766 Beef up the IUDateString/UIDateTime functions. Needed for a Date built-in replacement. 2020-07-13 23:43:24 -04:00
Kelvin Sherlock
02629c4eee 0-byte read request should not trigger eof error. 2019-08-17 10:33:12 -04:00
Kelvin Sherlock
fa1f4623c9 submodule update. 2018-07-24 11:23:32 -04:00
Kelvin Sherlock
b560c66dda fix case-insensitive includes. 2018-01-01 14:15:17 -05:00
Kelvin Sherlock
2eb90481bc remove old sane code (moved to libsane). 2018-01-01 14:13:30 -05:00
Kelvin Sherlock
8c38175492 bump version. 2017-12-14 10:50:50 -05:00
Kelvin Sherlock
08fef2cef5 update libsane 2017-12-14 10:47:45 -05:00
Kelvin Sherlock
fb6d52a93d sync cpu code with fellow. fixes some instruction times and 64-bit division. 2017-12-14 08:23:17 -05:00
Kelvin Sherlock
26bd3f53b7 submodule update. 2017-12-13 21:59:18 -05:00
Kelvin Sherlock
d11dab46e2 use libsane... 2017-12-13 21:58:43 -05:00
Kelvin Sherlock
c3d1121f36 case sensitive headers. 2017-10-02 21:16:12 -04:00
Kelvin Sherlock
776b385a41 update mpw open to be more consistent with actual implementation. Also support for non-HFS volumes. 2017-10-02 21:15:51 -04:00
Kelvin Sherlock
119d9aab57 APFS - when opening a resource fork as rdwr, create it as well
--
Under HFS, empty resource fork always exists. on APFS, it must be specifically created.
2017-10-02 16:31:33 -04:00
Kelvin Sherlock
60b49a1ff4 fix ptr bug. 2017-10-02 15:11:43 -04:00
Kelvin Sherlock
e21aac4022 clean up makefiles a bit. 2017-10-02 15:11:28 -04:00
Kelvin Sherlock
60c4977dfa fix build error. 2016-08-01 16:02:51 -04:00
Kelvin Sherlock
58f4ca4ac6 improve PBGetCatInfo 2016-07-31 13:26:41 -04:00
122 changed files with 17918 additions and 29287 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [ksherlock]

38
.github/workflows/cmake-fat.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: CMake fat
on: [push]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Brew
run: brew install ragel lemon
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: make mpw
- name: Archive
uses: actions/upload-artifact@v4
with:
name: mpw fat
path: ${{runner.workspace}}/build/bin/mpw

41
.github/workflows/cmake.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: CMake
on: [push]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12, macos-13]
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Brew
run: brew install ragel lemon
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: cmake --build . --config $BUILD_TYPE
- name: Archive
uses: actions/upload-artifact@v4
with:
name: mpw ${{ matrix.os }}
path: ${{runner.workspace}}/build/bin/mpw

1
.gitignore vendored
View File

@ -8,4 +8,3 @@ docs/
MrC/
testing/
build-msvc/

6
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "submodule/cxx"]
path = submodule/cxx
url = git://github.com/ksherlock/cxx
[submodule "libsane"]
path = libsane
url = https://github.com/ksherlock/libsane.git

View File

@ -1,4 +1,8 @@
os: osx
osx_image:
- xcode11
- xcode12
- xcode12.5
language: cpp
compiler: clang
before_script:

View File

@ -1,12 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(mpw)
set (PROJECT_TYPE "CXX")
set (PROJECT_NAME "mpw")
project(mpw VERSION 0.8.3 LANGUAGES CXX C)
# these are only effective as of CMake 3.1, apparently.
# Use c++14 for all C++ files, c99 for C files.
#
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_EXTENSIONS FALSE)
@ -14,74 +9,30 @@ set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED TRUE)
set(CMAKE_C_EXTENSIONS FALSE)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# Clang or AppleClang
set(CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}")
endif()
if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
# Clang or AppleClang
add_compile_options(-g -Wall)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-g -Wall -Wno-unknown-pragmas -Wno-multichar)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_compile_options(/wd4996 /wd4068)
include_directories(winclude)
set(HAVE_ENDIAN_H 1)
set(CMAKE_C_FLAGS "-Wall ${CMAKE_C_FLAGS}")
endif()
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
add_compile_options(-D _BSD_SOURCE)
ENDIF()
include_directories(${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_BINARY_DIR})
#
# create the config.h file.
#
INCLUDE (CheckIncludeFiles)
INCLUDE (CheckStructHasMember)
INCLUDE (CheckFunctionExists)
INCLUDE (CheckLibraryExists)
CHECK_INCLUDE_FILES(endian.h HAVE_ENDIAN_H)
CHECK_INCLUDE_FILES(sys/endian.h HAVE_SYS_ENDIAN_H)
CHECK_INCLUDE_FILES(machine/endian.h HAVE_MACHINE_ENDIAN_H)
CHECK_INCLUDE_FILES(bsd/string.h HAVE_BSD_STRING_H)
CHECK_STRUCT_HAS_MEMBER("struct dirent" d_namlen dirent.h HAVE_DIRENT_D_NAMLEN)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime sys/stat.h HAVE_STAT_ST_BIRTHTIME)
set(CMAKE_REQUIRED_INCLUDES string.h)
CHECK_FUNCTION_EXISTS(strlcat HAVE_STRLCAT)
CHECK_FUNCTION_EXISTS(strlcpy HAVE_STRLCPY)
set(CMAKE_REQUIRED_INCLUDES)
CHECK_LIBRARY_EXISTS(edit readline "" HAVE_LIBEDIT)
CHECK_LIBRARY_EXISTS(readline readline "" HAVE_LIBREADLINE)
CHECK_LIBRARY_EXISTS(history add_history "" HAVE_LIBHISTORY)
# feature config
SET(ENABLE_DEBUGGER 1 CACHE BOOL "Define whether debugger should be enabled.")
IF(ENABLE_DEBUGGER)
ENDIF()
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_BINARY_DIR}/config.h)
if (MSVC)
add_subdirectory(winclude)
find_program(RAGEL NAMES ragel)
if (NOT RAGEL)
message(FATAL_ERROR "ragel (version 6) is required.")
endif()
include_directories("${CMAKE_SOURCE_DIR}")
add_subdirectory(bin)
add_subdirectory(cpu)
add_subdirectory(toolbox)
add_subdirectory(mplite)
add_subdirectory(mpw)
add_subdirectory(macos)
add_subdirectory(cxx)
add_subdirectory(native)
add_subdirectory(libsane)

View File

@ -24,13 +24,18 @@ is in the public domain.
## Building
First initialize and fetch submodules:
git submodule init
git submodule update
Compiling requires cmake, ragel, lemon, and a recent version of clang++ with
c++11 support. It has only been built and tested with OS X 10.8+.
mkdir build
cd build
cmake ..
make
mkdir build
cd build
cmake ..
make
This will generate `bin/mpw` and `bin/disasm`.
@ -85,9 +90,9 @@ or create a shell script (in `/usr/local/bin`, etc)
`/usr/local/bin/AsmIIgs`:
#!/usr/bin/sh
#!/bin/sh
exec mpw AsmIIgs $@
exec mpw AsmIIgs "$@"
mpw uses the MPW `$Commands` variable to find the command, similar to `$PATH` on Unix. If the `$Commands` variable

View File

@ -84,9 +84,9 @@ or create a shell script (in /usr/local/bin, etc)
/usr/local/bin/AsmIIgs:
#!/usr/bin/sh
#!/bin/sh
exec mpw AsmIIgs $@
exec mpw AsmIIgs "$@"
mpw looks in the current directory and then in the $MPW:Tools: directory
for the command to run. The MPW $Commands variable is not yet supported.

View File

@ -1,47 +1,47 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# add_custom_command(
# OUTPUT lexer.cpp
# COMMAND re2c -b -i -o lexer.cpp "${CMAKE_CURRENT_SOURCE_DIR}/lexer.re.cpp"
# MAIN_DEPENDENCY lexer.re.cpp
# DEPENDS debugger.h parser.h
# )
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# Clang or AppleClang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations -Wno-unused-variable")
endif()
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
add_custom_command(
OUTPUT lexer.cpp
COMMAND ragel -p -G2 -o lexer.cpp "${CMAKE_CURRENT_SOURCE_DIR}/lexer.rl"
COMMAND "${RAGEL}" -p -G2 -o lexer.cpp "${CMAKE_CURRENT_SOURCE_DIR}/lexer.rl"
MAIN_DEPENDENCY lexer.rl
)
add_custom_command(
OUTPUT parser.cpp parser.h
COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/parser.lemon" "parser.lemon"
COMMAND lemon parser.lemon
COMMAND cp -f parser.h "${CMAKE_CURRENT_SOURCE_DIR}/"
COMMAND cp -f parser.out "${CMAKE_CURRENT_SOURCE_DIR}/"
COMMAND mv -f parser.c parser.cpp
MAIN_DEPENDENCY parser.lemon
DEPENDS debugger.h
)
find_program(LEMON NAMES lemon)
if (LEMON)
add_custom_command(
OUTPUT template_parser.cpp template_parser.h
COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/template_parser.lemon" "template_parser.lemon"
COMMAND lemon template_parser.lemon
COMMAND cp -f template_parser.h "${CMAKE_CURRENT_SOURCE_DIR}/"
COMMAND cp -f template_parser.out "${CMAKE_CURRENT_SOURCE_DIR}/"
COMMAND mv -f template_parser.c template_parser.cpp
MAIN_DEPENDENCY template_parser.lemon
DEPENDS debugger.h
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/parser.h
# COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/parser.lemon" "parser.lemon"
COMMAND ${LEMON} parser.lemon
COMMAND mv -f parser.c parser.cpp
MAIN_DEPENDENCY parser.lemon
DEPENDS debugger.h
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/template_parser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/template_parser.h
# COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/template_parser.lemon" "template_parser.lemon"
COMMAND ${LEMON} template_parser.lemon
COMMAND mv -f template_parser.c template_parser.cpp
MAIN_DEPENDENCY template_parser.lemon
DEPENDS debugger.h
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
endif()
add_custom_command(
OUTPUT loadtrap.cpp
COMMAND ragel -p -G2 -o loadtrap.cpp "${CMAKE_CURRENT_SOURCE_DIR}/loadtrap.rl"
COMMAND "${RAGEL}" -p -G2 -o loadtrap.cpp "${CMAKE_CURRENT_SOURCE_DIR}/loadtrap.rl"
MAIN_DEPENDENCY loadtrap.rl
DEPENDS debugger.h
)
@ -49,67 +49,31 @@ add_custom_command(
add_custom_command(
OUTPUT template_loader.cpp
COMMAND ragel -p -G2 -o template_loader.cpp "${CMAKE_CURRENT_SOURCE_DIR}/template_loader.rl"
COMMAND "${RAGEL}" -p -G2 -o template_loader.cpp "${CMAKE_CURRENT_SOURCE_DIR}/template_loader.rl"
MAIN_DEPENDENCY template_loader.rl
DEPENDS debugger.h template_parser.h
)
add_executable(mpw loader.cpp debugger.cpp debugger_internal.cpp
address_map.cpp lexer.cpp parser.cpp loadtrap.cpp
commands.cpp
template_loader.cpp template_parser.cpp intern.cpp template.cpp)
set_source_files_properties(
loadtrap.cpp lexer.cpp template_loader.cpp
PROPERTIES
COMPILE_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-unused-variable"
)
#
# -ledit includes history stuff. gnu -lreadline does not.
#
IF (ENABLE_DEBUGGER)
set(DEBUGGER_SRC
debugger.cpp debugger.cpp debugger_internal.cpp
address_map.cpp lexer.cpp parser.cpp loadtrap.cpp
commands.cpp
template_loader.cpp template_parser.cpp intern.cpp template.cpp
)
ENDIF()
add_executable(mpw main.cpp loadtrap.cpp ${DEBUGGER_SRC})
IF (ENABLE_DEBUGGER)
if(HAVE_LIBEDIT)
target_link_libraries(mpw edit)
elseif(HAVE_LIBREADLINE)
target_link_libraries(mpw readline)
if (HAVE_LIBHISTORY)
target_link_libraries(mpw history)
endif()
endif()
ENDIF()
if (MSVC)
target_link_libraries(mpw WINLIB_LIB)
endif()
target_link_libraries(mpw CPU_LIB)
target_link_libraries(mpw TOOLBOX_LIB)
target_link_libraries(mpw MPW_LIB)
target_link_libraries(mpw MPLITE_LIB)
target_link_libraries(mpw NATIVE_LIB)
target_link_libraries(mpw MACOS_LIB)
target_link_libraries(mpw CXX_LIB)
target_link_libraries(mpw -ledit)
target_link_libraries(mpw "-framework Carbon")
#add_executable(disasm disasm.cpp)
#target_link_libraries(disasm CPU_LIB)
#target_link_libraries(disasm MACOS_LIB)
add_executable(disasm disasm.cpp)
target_link_libraries(disasm CPU_LIB)
target_link_libraries(disasm MACOS_LIB)
target_link_libraries(disasm "-framework Carbon")
install(
PROGRAMS

View File

@ -13,7 +13,7 @@
#include "debugger.h"
#include "debugger_internal.h"
#include "main.h" // Flags
#include "loader.h" // Flags
namespace Debug {

View File

@ -43,9 +43,9 @@
#include <bitset>
#include <readline/readline.h>
#include <readline/history.h>
#include "main.h"
#include "loader.h"
#include "address_map.h"
#include "debugger.h"
@ -146,7 +146,7 @@ namespace {
printf(" %s\n\n", s.c_str());
// word-align
pc = (pc + 1) & ~0x01;
pc = pc + 1 & ~0x01;
// and possibly a zero-word after it.
if (Debug::ReadWord(pc) == 0x0000) pc += 2;
@ -1135,6 +1135,8 @@ namespace {
{
std::string s(text);
rl_attempted_completion_over = 1; // suppress filename completion if no results.
// returns iter to first element _not less_ than key
// ie, >= key.
auto iter = SymbolTable.lower_bound(s);
@ -1213,25 +1215,11 @@ namespace {
return buffer;
}
// this is here to prevent filename tab completion, for now.
// state is 0 for first call, non-zero for subsequent calls. It
// should return 1 match per invocation, NULL if no more matches.
char *mpw_completion_entry_function(const char *text, int state)
{
return NULL;
}
void readline_init()
{
rl_readline_name = (char *)"mpw";
rl_attempted_completion_function = mpw_attempted_completion_function;
#if RL_READLINE_VERSION == 0x0402
/* actually libedit */
rl_completion_entry_function = (Function *)mpw_completion_entry_function;
#else
/* gnu readline, I presume */
rl_completion_entry_function = mpw_completion_entry_function;
#endif
}
}
@ -1258,13 +1246,13 @@ void Shell()
// load the error code to error mnemonic
ErrorTableInvert.reserve(ErrorTable.size());
for (const auto kv : ErrorTable) {
for (const auto &kv : ErrorTable) {
ErrorTableInvert.emplace(std::make_pair(kv.second, kv.first));
}
// address to function name.
SymbolTableInvert.reserve(SymbolTable.size());
for (const auto kv : SymbolTable) {
for (const auto &kv : SymbolTable) {
SymbolTableInvert.emplace(std::make_pair(kv.second.first, kv.first));
}

View File

@ -25,8 +25,6 @@
*
*/
#include "config.h"
#include <cstdint>
#include <cctype>
#include <cstring>
@ -38,12 +36,9 @@
#include <getopt.h>
#include <libgen.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/stat.h>
#include <cxx/string_splitter.h>
#include <CoreServices/CoreServices.h>
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
@ -61,12 +56,13 @@
#include <macos/sysequ.h>
#include <macos/traps.h>
#include "main.h"
#ifdef ENABLE_DEBUGGER
#include "loader.h"
#include "debugger.h"
#endif
#include <cxx/string_splitter.h>
#define LOADER_LOAD
Settings Flags;
@ -118,7 +114,268 @@ void WriteLong(void *data, uint32_t offset, uint32_t value)
((uint8_t *)data)[offset++] = value;
}
#ifndef LOADER_LOAD
void reloc1(const uint8_t *r, uint32_t address, uint32_t offset)
{
// %00000000 00000000 -> break
// %0xxxxxxx -> 7-bit value
// %1xxxxxxx xxxxxxxx -> 15-bit value
// %00000000 1xxxxxxx x{8} x{8} x{8} -> 31 bit value
// ^ that's what the documentation says..
// that's how the 32-bit bootstrap works
// DumpCode ignores the high 2 bytes.
for(;;)
{
uint32_t x;
uint32_t value;
x = *r++;
if (x == 0x00)
{
x = *r++;
if (x == 0x00) break;
x = (x << 8) | *r++;
x = (x << 8) | *r++;
x = (x << 8) | *r++;
}
else if (x & 0x80)
{
x &= 0x7f;
x = (x << 8) | *r++;
}
x <<= 1; // * 2
address += x;
value = memoryReadLong(address);
memoryWriteLong(value + offset, address);
}
}
// relocate a far model segment.
void relocate(uint32_t address, uint32_t size, uint32_t a5)
{
// see MacOS RT Architecture, 10-23 .. 10-26
uint32_t offset;
offset = memoryReadLong(address + 0x14);
if (memoryReadLong(address + 0x18) != a5 && offset != 0)
{
memoryWriteLong(a5, address + 0x18); // current value of A5
reloc1(memoryPointer(address + offset), address, a5);
}
offset = memoryReadLong(address + 0x1c);
if (memoryReadLong(address + 0x20) != address && offset != 0)
{
memoryWriteLong(address, address + 0x20); // segment load address.
reloc1(memoryPointer(address + offset), address, address + 0x28);
}
}
uint32_t load(const char *file)
{
ResFileRefNum refNum;
FSRef ref;
uint32_t returnAddress = 0;
struct SegInfo {
public:
SegInfo()
{}
SegInfo(uint32_t a, uint32_t s, bool f) :
address(a), size(s), farModel(f)
{}
uint32_t address = 0;
uint32_t size = 0;
bool farModel = 0;
};
std::vector< SegInfo> segments;
uint32_t a5 = 0;
uint32_t jtStart = 0;
uint32_t jtEnd = 0;
// todo -- call RM::Native to open and load the Resource File.
assert(FSPathMakeRef( (const UInt8 *)file, &ref, NULL) == noErr);
// todo -- if it wasn't a resource file, this will fail
// should provide a nicer error message.
refNum = FSOpenResFile(&ref, fsRdPerm);
assert(refNum != -1 );
int l = Count1Resources('CODE');
segments.reserve(l);
assert(l > 0);
for (int i = 0; i < l; ++i)
{
ResAttributes attr;
ResID resID;
ResType resType;
Str255 name;
uint32_t size;
uint32_t address;
Handle h;
const uint8_t *data;
uint16_t error;
h = Get1IndResource('CODE', i + 1);
if (!h) continue;
HLock(h);
data = *(const uint8_t **)h;
attr = GetResAttrs(h);
GetResInfo(h, &resID, &resType, name);
size = GetHandleSize(h);
if (segments.size() <= resID) segments.resize(resID + 1);
// can't have duplicate resIDs, so no need to check that...
if (resID == 0)
{
// jump table/a5
uint32_t above = ReadLong(data, 0);
uint32_t below = ReadLong(data, 4);
uint32_t jtSize = ReadLong(data, 8);
uint32_t jtOffset = ReadLong(data, 12);
uint32_t a5size = above + below;
// TODO -- verify numbers are on word boundary?
error = MM::Native::NewPtr(a5size, true, address);
if (error)
{
fprintf(stderr, "Memory allocation error.\n");
return 0;
}
a5 = address + below;
std::memcpy(memoryPointer(a5 + jtOffset), data + 16 , jtSize);
segments[resID] = SegInfo(address, a5size, false);
jtStart = a5 + jtOffset;
jtEnd = jtStart + jtSize;
// 0x0934 - CurJTOffset (16-bit)
memoryWriteWord(jtOffset, MacOS::CurJTOffset);
// 0x0904 -- CurrentA5 (32-bit)
memoryWriteLong(a5, MacOS::CurrentA5);
cpuSetAReg(5, a5);
}
else
{
bool farModel = false;
if (data[0] == 0xff && data[1] == 0xff) farModel = true;
error = MM::Native::NewPtr(size, false, address);
if (error)
{
fprintf(stderr, "Memory allocation error.\n");
return 0;
}
std::memcpy(memoryPointer(address), data, size);
segments[resID] = SegInfo(address, size, farModel);
}
ReleaseResource(h);
}
// now link the segment 0 jump table...
assert(a5);
bool first = true;
bool farModel = false;
for (; jtStart < jtEnd; jtStart += 8)
{
uint16_t seg;
uint32_t offset;
if (farModel)
{
seg = memoryReadWord(jtStart + 0);
offset = memoryReadLong(jtStart + 4);
assert(memoryReadWord(jtStart + 2) == 0xA9F0);
}
else
{
uint16_t farModelCheck;
offset = memoryReadWord(jtStart);
farModelCheck = memoryReadWord(jtStart + 2);
seg = memoryReadWord(jtStart + 4);
if (farModelCheck == 0xffff)
{
farModel = true;
continue;
}
assert(memoryReadWord(jtStart + 2) == 0x3F3C);
assert(memoryReadWord(jtStart + 6) == 0xA9F0);
}
assert(seg < segments.size());
auto p = segments[seg];
//assert(p.first); // missing segment?!
//assert(offset < p.second);
assert(p.address); // missing segment?!
assert(offset < p.size);
// +$4/$28 for the jump table info header.
uint32_t address = p.address + offset + (p.farModel ? 0x00 : 0x04); // was 0x28
// JMP absolute long
memoryWriteWord(0x4EF9, jtStart + 2);
memoryWriteLong(address, jtStart + 4);
if (first)
{
//cpuSetPC(address);
returnAddress = address;
first = false;
}
}
// far-model relocation. This happens here, after a5 is loaded.
for (const auto &seg : segments)
{
if (seg.farModel)
{
relocate(seg.address, seg.size, a5);
}
}
// set pc to jump table entry 0.
return returnAddress;
}
#endif
void GlobalInit()
@ -154,10 +411,21 @@ void CreateStack()
uint32_t address;
//uint16_t error;
// stack is at top of memory because some apps assume stack overflow if elsewhere.
#if 0
Flags.stackSize = (Flags.stackSize + 3) & ~0x03;
error = MM::Native::NewPtr(Flags.stackSize, true, address);
if (error)
{
fprintf(stderr, "Unable to allocate stack (%08x bytes)\n", Flags.stackSize);
exit(EX_CONFIG);
}
#else
address = Flags.memorySize - Flags.stackSize;
#endif
Flags.stackRange.first = address;
Flags.stackRange.second = address + Flags.stackSize;
@ -315,7 +583,7 @@ void MidInstructionExceptionFunc()
}
#define MPW_VERSION "0.8.0"
#define MPW_VERSION "0.8.3"
void help()
{
printf("MPW " MPW_VERSION "\n");
@ -329,9 +597,6 @@ void help()
printf(" --memory-stats print memory usage information\n");
printf(" --ram=<number> set the ram size. Default=16M\n");
printf(" --stack=<number> set the stack size. Default=8K\n");
#ifdef ENABLE_DEBUGGER
printf(" --debugger Enable debug shell\n");
#endif
printf("\n");
}
@ -359,9 +624,9 @@ bool parse_number(const char *input, uint32_t *dest)
if (*end)
{
int old = value;
if (strcasecmp(end, "M") == 0)
if (strcasecmp(end, "M") == 0 || strcasecmp(end, "MB") == 0)
value *= 1024 * 1024;
else if (strcasecmp(end, "K") == 0)
else if (strcasecmp(end, "K") == 0 || strcasecmp(end, "KB") == 0)
value *= 1024;
else
{
@ -533,10 +798,8 @@ int main(int argc, char **argv)
{ "trace-tools", no_argument, NULL, kTraceToolBox },
{ "trace-mpw", no_argument, NULL, kTraceMPW },
#ifdef ENABLE_DEBUGGER
{ "debug", no_argument, NULL, kDebugger },
{ "debugger", no_argument, NULL, kDebugger },
#endif
{ "memory-stats", no_argument, NULL, kMemoryStats },
@ -692,15 +955,22 @@ int main(int argc, char **argv)
CreateStack();
{
auto rv = Loader::Native::LoadFile(command);
if (!rv) {
fprintf(stderr, "### Unable to load %s\n", command.c_str());
fprintf(stderr, "# %s (OS error %d)\n", ErrorName(rv.error()), rv.error());
exit(EX_CONFIG);
}
#ifdef LOADER_LOAD
uint16_t err = Loader::Native::LoadFile(command);
if (err) {
const char *cp = ErrorName(err);
fprintf(stderr, "Unable to load command %s: ", command.c_str());
if (cp) printf("%s\n", cp);
else printf("%hd\n", err);
exit(EX_SOFTWARE);
}
#else
uint32_t address = load(command.c_str());
if (!address) {
fprintf(stderr, "Unable to load command %s\n", command.c_str());
exit(EX_SOFTWARE);
}
#endif
GlobalInit();
@ -725,13 +995,12 @@ int main(int argc, char **argv)
// else do it manually below.
}
#ifdef ENABLE_DEBUGGER
if (Flags.debugger) Debug::Shell();
else MainLoop();
#else
MainLoop();
#ifndef LOADER_LOAD
cpuInitializeFromNewPC(address);
#endif
if (Flags.debugger) Debug::Shell();
else MainLoop();
@ -743,5 +1012,7 @@ int main(int argc, char **argv)
uint32_t rv = MPW::ExitStatus();
if (rv > 0xff) rv = 0xff;
exit(rv);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2016, Kelvin W Sherlock
* Copyright (c) 2013, Kelvin W Sherlock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -24,121 +24,258 @@
*
*/
%%{
machine load_traps;
alphtype unsigned char;
action reset {
negative = false;
value = 0;
key.clear();
scratch.clear();
}
action commit {
bool ok = true;
if (!scratch.empty()) {
auto iter = table.find(scratch);
if (iter == table.end()) {
fprintf(stderr, "Undefined reference: %s\n", scratch.c_str());
ok = false;
}
else value = iter->second;
}
if (negative) value = -value;
if (ok) table.emplace(std::move(key), value);
}
eol = [\r\n] ${ line++; };
ws = [ \t];
error := [^\r\n]* eol $reset ${ fnext main; };
comment = '#' [^\r\n]*;
word = [A-Za-z_][A-Za-z_0-9]*;
key = word ${ key.push_back(fc); };
base16 =
[0-9] ${value = (value << 4) + fc - '0'; }
| [A-Fa-f] ${value = (value << 4) + (fc | 0x20) - 'a' + 10; }
;
base10 = [0-9]+ ${ value = (value * 10) + fc - '0'; };
decnumber = ( '-' ${ negative = true; } )? base10+;
hexnumber = ('$' | '0x') base16+;
number = decnumber | hexnumber;
value = number | word ${ scratch.push_back(fc); };
line =
ws* ( key ws* '=' ws* value %commit %reset ws*)? comment? eol
;
main := line*
$err{
fprintf(stderr, "Unexpected character '%c' on line %d\n", fc, line);
fnext error;
};
}%%;
namespace {
%% write data;
}
#include <string>
#include <map>
#include <stdexcept>
#include <string>
#include <cstdio>
#include <cstdint>
#include <cxx/mapped_file.h>
#include <sys/types.h>
#include <limits.h>
namespace _loadtrap_rl {
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#define _GETDELIM_GROWBY 128 /* amount to grow line buffer by */
#define _GETDELIM_MINLEN 4 /* minimum line buffer size */
ssize_t getdelim(char ** lineptr, size_t * n, int delimiter, FILE * stream) {
char *buf, *pos;
int c;
ssize_t bytes;
if (lineptr == NULL || n == NULL) {
errno = EINVAL;
return -1;
}
if (stream == NULL) {
errno = EBADF;
return -1;
}
/* resize (or allocate) the line buffer if necessary */
buf = *lineptr;
if (buf == NULL || *n < _GETDELIM_MINLEN) {
buf = (char*)realloc(*lineptr, _GETDELIM_GROWBY);
if (buf == NULL) {
/* ENOMEM */
return -1;
}
*n = _GETDELIM_GROWBY;
*lineptr = buf;
}
/* read characters until delimiter is found, end of file is reached, or an
error occurs. */
bytes = 0;
pos = buf;
while ((c = getc(stream)) != EOF) {
if (bytes + 1 >= SSIZE_MAX) {
errno = EOVERFLOW;
return -1;
}
bytes++;
if (bytes >= *n - 1) {
buf = (char*)realloc(*lineptr, *n + _GETDELIM_GROWBY);
if (buf == NULL) {
/* ENOMEM */
return -1;
}
*n += _GETDELIM_GROWBY;
pos = buf + bytes - 1;
*lineptr = buf;
}
*pos++ = (char) c;
if (c == delimiter) {
break;
}
}
if (ferror(stream) || (feof(stream) && (bytes == 0))) {
/* EOF, or an error from getc(). */
return -1;
}
*pos = '\0';
return bytes;
}
#endif
ssize_t getline(char ** lineptr, size_t * n, FILE * stream) {
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
return getdelim(lineptr, n, '\n', stream);
#else
return ::getline(lineptr, n, stream);
#endif
}
}
namespace {
// private...
%%{
machine lexer;
action addx {
value = (value << 4) + digittoint(fc);
}
ws = [ \t];
value =
'0x' xdigit+ @addx
|
'$' xdigit+ @addx
|
'-'? @{ negative = true; }
digit+ @{value = value * 10 + (fc - '0'); }
|
[A-Za-z_] @{ stringValue.push_back(fc); }
[A-Za-z0-9_]+ @{ stringValue.push_back(fc); }
;
name =
[A-Za-z0-9_]+ @{
name.push_back(fc);
}
;
main :=
name
ws*
'='
ws*
value
;
write data;
}%%
bool ParseLine(const char *p, const char *pe, std::map<std::string, uint16_t> &map)
{
// trap = number
// or trap = [previously defined trap]
std::string name;
std::string stringValue;
uint32_t value;
bool negative = false;
value = 0;
const char *eof = pe;
int cs;
%%write init;
%%write exec;
if (cs < %%{ write first_final; }%% )
{
return false;
}
if (negative) value = (-value) & 0xffff;
// name lookup
if (!stringValue.empty())
{
auto iter = map.find(stringValue);
if (iter == map.end())
{
fprintf(stderr, "Undefined trap: %s\n", stringValue.c_str());
return false;
}
value = iter->second;
}
#if 0
// if loading globals, wouldn't need to do this...
if (value > 0xafff || value < 0xa000)
{
fprintf(stderr, "Invalid trap number: $%04x\n", value);
return false;
}
#endif
map.emplace(name, (uint16_t)value);
return true;
}
}
namespace Debug {
void LoadTrapFile(const std::string &path, std::map<std::string, uint16_t> &table) {
int cs;
const unsigned char *p;
const unsigned char *pe;
const unsigned char *eof;
int line = 1;
void LoadTrapFile(const std::string &path, std::map<std::string, uint16_t> &map)
{
FILE *fp;
int value = 0;
bool negative = false;
std::string key;
std::string scratch;
mapped_file mf;
try {
mf.open(path, mapped_file::readonly);
} catch (const std::exception &ex) {
//fprintf(stderr, "### %s: %s\n", path.c_str(), ex.what());
fp = fopen(path.c_str(), "r");
if (!fp)
{
fprintf(stderr, "Unable to open trap file %s\n", path.c_str());
return;
}
%% write init;
p = mf.cbegin();
pe = mf.cend();
eof = nullptr;
for (int i = 0; i < 2; ++i) {
%% write exec;
/*
* getline(3) is 2008 posix. it allocates (and resizes as appropriate)
* the buffer.
*
*/
char *lineBuffer = NULL;
size_t lineSize = 0;
p = (const unsigned char *)"\n";
pe = eof = p+1;
for(;;)
{
char *line;
ssize_t length;
length = _loadtrap_rl::getline(&lineBuffer, &lineSize, fp);
if (!length) continue; //?
if (length < 0) break; // eof or error.
line = lineBuffer;
// skip any leading space.
while (length && isspace(*line))
{
++line;
--length;
}
if (!length) continue;
// comments
if (*line == '#') continue;
// strip any trailing space.
// (will be \n terminated unless there was no \n)
while (length && isspace(line[length - 1]))
{
line[--length] = 0;
}
if (!length) continue;
if (!ParseLine(line, line + length, map))
{
fprintf(stderr, "Error in trap definition: %s\n", line);
}
}
fclose(fp);
}
}
#ifdef TEST
int main(int argc, char **argv)
@ -149,7 +286,7 @@ int main(int argc, char **argv)
std::map<std::string, uint16_t> map;
Debug::LoadTrapFile(f, map);
for(const auto &kv : map)
for(const auto kv : map)
{
printf("%s -> %04x\n", kv.first.c_str(), kv.second);
}
@ -158,4 +295,4 @@ int main(int argc, char **argv)
return 0;
}
#endif
#endif

1868
bin/parser.cpp Normal file

File diff suppressed because it is too large Load Diff

51
bin/parser.h Normal file
View File

@ -0,0 +1,51 @@
#define tkPIPEPIPE 1
#define tkAMPAMP 2
#define tkPIPE 3
#define tkCARET 4
#define tkAMP 5
#define tkEQEQ 6
#define tkBANGEQ 7
#define tkLT 8
#define tkLTEQ 9
#define tkGT 10
#define tkGTEQ 11
#define tkLTLT 12
#define tkGTGT 13
#define tkPLUS 14
#define tkMINUS 15
#define tkSTAR 16
#define tkSLASH 17
#define tkPERCENT 18
#define tkBANG 19
#define tkTILDE 20
#define tkEOL 21
#define tkPRINT 22
#define tkBREAK 23
#define tkBACKTRACE 24
#define tkCONTINUE 25
#define tkTBREAK 26
#define tkRBREAK 27
#define tkWBREAK 28
#define tkRWBREAK 29
#define tkNEXT 30
#define tkDUMP 31
#define tkCOLON 32
#define tkAT 33
#define tkLIST 34
#define tkSTACKCRAWL 35
#define tkSEMI 36
#define tkSEMIH 37
#define tkSEMII 38
#define tkSEMIL 39
#define tkSEMIDATE 40
#define tkSEMIERROR 41
#define tkSEMIT 42
#define tkIDENTIFIER 43
#define tkDREGISTER 44
#define tkEQ 45
#define tkAREGISTER 46
#define tkXREGISTER 47
#define tkHELP 48
#define tkLPAREN 49
#define tkRPAREN 50
#define tkINTEGER 51

View File

@ -1,7 +1,7 @@
#include "template.h"
#include "debugger.h"
#include "debugger_internal.h"
#include "main.h" // Flags.
#include "loader.h" // Flags.
#include <algorithm>

View File

@ -15,10 +15,6 @@
#include "template.h"
#include "intern.h"
#ifndef MAP_FILE
#define MAP_FILE 0
#endif
namespace {
int tox(char c)

1291
bin/template_parser.cpp Normal file

File diff suppressed because it is too large Load Diff

20
bin/template_parser.h Normal file
View File

@ -0,0 +1,20 @@
#define tkTYPEDEF 1
#define tkIDENTIFIER 2
#define tkSTRUCT 3
#define tkLBRACE 4
#define tkRBRACE 5
#define tkSEMI 6
#define tkTEMPLATE 7
#define tkLBRACKET 8
#define tkINTEGER 9
#define tkRBRACKET 10
#define tkVOLATILE 11
#define tkSIGNED 12
#define tkUNSIGNED 13
#define tkCHAR 14
#define tkSHORT 15
#define tkLONG 16
#define tkTYPECODE 17
#define tkVOID 18
#define tkSTAR 19
#define tkINT 20

View File

@ -1,23 +0,0 @@
#ifndef __mpw_config_h__
#define __mpw_config_h__
#cmakedefine HAVE_STAT_ST_BIRTHTIME
#cmakedefine HAVE_DIRENT_D_NAMLEN
#cmakedefine HAVE_STRLCAT
#cmakedefine HAVE_STRLCPY
#cmakedefine ENABLE_DEBUGGER
#cmakedefine HAVE_ENDIAN_H
#cmakedefine HAVE_MACHINE_ENDIAN_H
#cmakedefine HAVE_SYS_ENDIAN_H
#cmakedefine HAVE_BSD_STRING_H
#ifdef _WIN32
typedef long ssize_t;
extern "C" int asprintf(char **, const char *, ...);
#endif
#endif

View File

@ -1,6 +1,11 @@
if (MSVC)
else()
add_compile_options(-g -Wall -Wno-unused-function)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# Clang or AppleClang
set(CMAKE_CXX_FLAGS "-Wall -Wno-unused-function")
endif()
if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
# Clang or AppleClang
set(CMAKE_C_FLAGS "-Wall -Wno-unused-function")
endif()
set(CPU_SRC

View File

@ -1,8 +1,7 @@
/* @(#) $Id: CpuIntegration.c,v 1.10 2013-01-08 19:17:33 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* Initialization of 68000 core */
/* Integrates the 68k emulation with custom chips */
/* Integrates the 68k emulation with custom chips */
/* */
/* Author: Petter Schau */
/* */
@ -34,47 +33,47 @@
#include "interrupt.h"
jmp_buf cpu_integration_exception_buffer;
ULO cpu_integration_chip_interrupt_number;
uint32_t cpu_integration_chip_interrupt_number;
/* Cycles spent by chips (Blitter) as a result of an instruction */
static ULO cpu_integration_chip_cycles;
static ULO cpu_integration_chip_slowdown;
static uint32_t cpu_integration_chip_cycles;
static uint32_t cpu_integration_chip_slowdown;
/*===========================================================================*/
/* CPU properties */
/*===========================================================================*/
ULO cpu_integration_speed; // The speed as expressed in the fellow configuration settings
ULO cpu_integration_speed_multiplier; // The cycle multiplier used to adjust the cpu-speed, calculated from cpu_integration_speed
uint32_t cpu_integration_speed; // The speed as expressed in the fellow configuration settings
uint32_t cpu_integration_speed_multiplier; // The cycle multiplier used to adjust the cpu-speed, calculated from cpu_integration_speed
cpu_integration_models cpu_integration_model; // The cpu model as expressed in the fellow configuration settings
/*===========================================================================*/
/* CPU properties */
/*===========================================================================*/
void cpuIntegrationSetSpeed(ULO speed)
void cpuIntegrationSetSpeed(uint32_t speed)
{
cpu_integration_speed = speed;
}
ULO cpuIntegrationGetSpeed(void)
uint32_t cpuIntegrationGetSpeed(void)
{
return cpu_integration_speed;
}
static void cpuIntegrationSetSpeedMultiplier(ULO multiplier)
static void cpuIntegrationSetSpeedMultiplier(uint32_t multiplier)
{
cpu_integration_speed_multiplier = multiplier;
}
static ULO cpuIntegrationGetSpeedMultiplier(void)
static uint32_t cpuIntegrationGetSpeedMultiplier(void)
{
return cpu_integration_speed_multiplier;
}
void cpuIntegrationCalculateMultiplier(void)
{
ULO multiplier = 12;
uint32_t multiplier = 12;
switch (cpuGetModelMajor())
{
@ -121,39 +120,39 @@ cpu_integration_models cpuIntegrationGetModel(void)
return cpu_integration_model;
}
void cpuIntegrationSetChipCycles(ULO chip_cycles)
void cpuIntegrationSetChipCycles(uint32_t chip_cycles)
{
cpu_integration_chip_cycles = chip_cycles;
}
ULO cpuIntegrationGetChipCycles(void)
uint32_t cpuIntegrationGetChipCycles(void)
{
return cpu_integration_chip_cycles;
}
void cpuIntegrationSetChipSlowdown(ULO chip_slowdown)
void cpuIntegrationSetChipSlowdown(uint32_t chip_slowdown)
{
cpu_integration_chip_slowdown = chip_slowdown;
}
ULO cpuIntegrationGetChipSlowdown(void)
uint32_t cpuIntegrationGetChipSlowdown(void)
{
return cpu_integration_chip_slowdown;
}
void cpuIntegrationSetChipInterruptNumber(ULO chip_interrupt_number)
void cpuIntegrationSetChipInterruptNumber(uint32_t chip_interrupt_number)
{
cpu_integration_chip_interrupt_number = chip_interrupt_number;
}
ULO cpuIntegrationGetChipInterruptNumber(void)
uint32_t cpuIntegrationGetChipInterruptNumber(void)
{
return cpu_integration_chip_interrupt_number;
}
// A wrapper for cpuSetIrqLevel that restarts the
// scheduling of cpu events if the cpu was stoppped
void cpuIntegrationSetIrqLevel(ULO new_interrupt_level, ULO chip_interrupt_number)
void cpuIntegrationSetIrqLevel(uint32_t new_interrupt_level, uint32_t chip_interrupt_number)
{
if (cpuSetIrqLevel(new_interrupt_level))
{
@ -241,7 +240,7 @@ void cpuIntegrationInstructionLogging(void)
fprintf(CPUINSTRUCTIONLOG, "SSP:%.6X USP:%.6X SP:%.4X %s %s\t%s\t%s\n", cpuGetSspDirect(), cpuGetUspDirect(), cpuGetSR(), saddress, sdata, sinstruction, soperands);
}
void cpuIntegrationExceptionLogging(STR *description, ULO original_pc, UWO opcode)
void cpuIntegrationExceptionLogging(char *description, uint32_t original_pc, uint16_t opcode)
{
if (cpu_disable_instruction_log) return;
cpuInstructionLogOpen();
@ -250,7 +249,7 @@ void cpuIntegrationExceptionLogging(STR *description, ULO original_pc, UWO opcod
fprintf(CPUINSTRUCTIONLOG, "%s for opcode %.4X at PC %.8X from PC %.8X\n", description, opcode, original_pc, cpuGetPC());
}
void cpuIntegrationInterruptLogging(ULO level, ULO vector_address)
void cpuIntegrationInterruptLogging(uint32_t level, uint32_t vector_address)
{
if (cpu_disable_instruction_log) return;
cpuInstructionLogOpen();
@ -263,8 +262,7 @@ void cpuIntegrationInterruptLogging(ULO level, ULO vector_address)
void cpuIntegrationExecuteInstructionEventHandler68000Fast(void)
{
ULO cycles;
cycles = cpuExecuteInstruction();
uint32_t cycles = cpuExecuteInstruction();
if (cpuGetStop())
{
@ -279,8 +277,8 @@ void cpuIntegrationExecuteInstructionEventHandler68000Fast(void)
void cpuIntegrationExecuteInstructionEventHandler68000General(void)
{
ULO cycles = 0;
ULO time_used = 0;
uint32_t cycles = 0;
uint32_t time_used = 0;
do
{
@ -303,7 +301,7 @@ void cpuIntegrationExecuteInstructionEventHandler68000General(void)
void cpuIntegrationExecuteInstructionEventHandler68020(void)
{
ULO time_used = 0;
uint32_t time_used = 0;
do
{
cpuExecuteInstruction();

View File

@ -1,5 +1,4 @@
#ifndef CpuIntegration_H
#define CpuIntegration_H
#pragma once
#ifdef __cplusplus
extern "C" {
@ -16,25 +15,23 @@ typedef enum {
extern void cpuIntegrationCalculateMultiplier(void);
extern void cpuIntegrationSetUpInterruptEventHandler(void);
extern void cpuIntegrationExecuteInstructionEventHandler68000Fast(void);
extern void cpuIntegrationExecuteInstructionEventHandler68000General(void);
extern void cpuIntegrationExecuteInstructionEventHandler68020(void);
extern void cpuIntegrationCheckPendingInterrupts(void);
extern ULO cpuIntegrationDisOpcode(ULO disasm_pc, STR *saddress, STR *sdata, STR *sinstruction, STR *soperands);
extern uint32_t cpuIntegrationDisOpcode(uint32_t disasm_pc, char *saddress, char *sdata, char *sinstruction, char *soperands);
extern BOOLE cpuIntegrationSetModel(cpu_integration_models model);
extern cpu_integration_models cpuIntegrationGetModel(void);
extern ULO cpuIntegrationGetModelMajor(void);
extern ULO cpuIntegrationGetPC(void);
extern uint32_t cpuIntegrationGetModelMajor(void);
extern ULO cpuIntegrationGetInstructionTime(void);
extern void cpuIntegrationSetSpeed(ULO speed);
extern ULO cpuIntegrationGetSpeed(void);
extern void cpuIntegrationSetChipCycles(ULO chip_cycles);
extern ULO cpuIntegrationGetChipCycles(void);
extern void cpuIntegrationSetChipSlowdown(ULO chip_slowdown);
extern ULO cpuIntegrationGetChipSlowdown(void);
void cpuIntegrationSetIrqLevel(uint32_t new_interrupt_level, uint32_t chip_interrupt_number);
extern uint32_t cpuIntegrationGetInstructionTime(void);
extern void cpuIntegrationSetSpeed(uint32_t speed);
extern uint32_t cpuIntegrationGetSpeed(void);
extern void cpuIntegrationSetChipCycles(uint32_t chip_cycles);
extern uint32_t cpuIntegrationGetChipCycles(void);
extern void cpuIntegrationSetChipSlowdown(uint32_t chip_slowdown);
extern uint32_t cpuIntegrationGetChipSlowdown(void);
extern jmp_buf cpu_integration_exception_buffer;
@ -50,5 +47,3 @@ extern void cpuIntegrationShutdown(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule.c,v 1.7 2012-08-12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* Initialization of 68000 core */
@ -29,10 +28,8 @@
void cpuClearEverything(void)
{
ULO i,j;
for (j = 0; j < 2; j++)
for (i = 0; i < 8; i++)
for (uint32_t j = 0; j < 2; j++)
for (uint32_t i = 0; i < 8; i++)
cpuSetReg(j, i, 0);
cpuSetUspDirect(0);
@ -47,7 +44,6 @@ void cpuClearEverything(void)
cpuSetSfc(0);
cpuSetDfc(0);
cpuSetIrqLevel(0);
cpuSetRaiseInterrupt(FALSE);
cpuSetStop(FALSE);
cpuSetInstructionTime(0);
cpuSetOriginalPC(0);

View File

@ -1,87 +1,88 @@
#ifndef CpuModule_H
#define CpuModule_H
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// This header file defines the internal interfaces of the CPU module.
// MPW additions.
typedef void (*cpuLineExceptionFunc)(uint16_t);
extern void cpuSetALineExceptionFunc(cpuLineExceptionFunc func);
extern void cpuSetFLineExceptionFunc(cpuLineExceptionFunc func);
// This header file defines the internal interfaces of the CPU module.
//#define CPU_INSTRUCTION_LOGGING
// Function to check if there are any external interrupt sources wanting to issue interrupts
typedef BOOLE (*cpuCheckPendingInterruptsFunc)(void);
extern void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func);
extern void cpuCheckPendingInterrupts(void);
extern void cpuSetUpInterrupt(ULO new_interrupt_level);
extern void cpuInitializeFromNewPC(ULO new_pc);
typedef void (*memoryLoggingFunc)(uint32_t address, int size, int readWrite, uint32_t value);
extern void memorySetLoggingFunc(memoryLoggingFunc func);
#ifdef _DEBUG
#define CPU_INSTRUCTION_LOGGING
#endif
// Function to check if there are any external interrupt sources wanting to issue interrupts
typedef void (*cpuCheckPendingInterruptsFunc)(void);
extern void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func);
extern void cpuCheckPendingInterrupts(void);
extern void cpuSetUpInterrupt(uint32_t new_interrupt_level);
extern void cpuInitializeFromNewPC(uint32_t new_pc);
// Logging interface
#ifdef CPU_INSTRUCTION_LOGGING
typedef void (*cpuInstructionLoggingFunc)(void);
extern void cpuSetInstructionLoggingFunc(cpuInstructionLoggingFunc func);
typedef void (*cpuExceptionLoggingFunc)(STR *description, ULO original_pc, UWO opcode);
typedef void (*cpuExceptionLoggingFunc)(char *description, uint32_t original_pc, uint16_t opcode);
extern void cpuSetExceptionLoggingFunc(cpuExceptionLoggingFunc func);
typedef void (*cpuInterruptLoggingFunc)(ULO level, ULO vector_address);
typedef void (*cpuInterruptLoggingFunc)(uint32_t level, uint32_t vector_address);
extern void cpuSetInterruptLoggingFunc(cpuInterruptLoggingFunc func);
#endif
// CPU register and control properties
extern void cpuSetPC(ULO pc);
extern ULO cpuGetPC(void);
extern void cpuSetPC(uint32_t pc);
extern uint32_t cpuGetPC(void);
extern void cpuSetReg(ULO da, ULO i, ULO value);
extern ULO cpuGetReg(ULO da, ULO i);
extern void cpuSetReg(uint32_t da, uint32_t i, uint32_t value);
extern uint32_t cpuGetReg(uint32_t da, uint32_t i);
extern void cpuSetDReg(ULO i, ULO value);
extern ULO cpuGetDReg(ULO i);
extern void cpuSetDReg(uint32_t i, uint32_t value);
extern uint32_t cpuGetDReg(uint32_t i);
extern void cpuSetAReg(ULO i, ULO value);
extern ULO cpuGetAReg(ULO i);
extern void cpuSetAReg(uint32_t i, uint32_t value);
extern uint32_t cpuGetAReg(uint32_t i);
extern void cpuSetSR(ULO sr);
extern ULO cpuGetSR(void);
extern void cpuSetSR(uint32_t sr);
extern uint32_t cpuGetSR(void);
extern void cpuSetUspDirect(ULO usp);
extern ULO cpuGetUspDirect(void);
extern ULO cpuGetUspAutoMap(void);
extern void cpuSetUspDirect(uint32_t usp);
extern uint32_t cpuGetUspDirect(void);
extern uint32_t cpuGetUspAutoMap(void);
extern void cpuSetMspDirect(ULO msp);
extern ULO cpuGetMspDirect(void);
extern void cpuSetMspDirect(uint32_t msp);
extern uint32_t cpuGetMspDirect(void);
extern void cpuSetSspDirect(ULO ssp);
extern ULO cpuGetSspDirect(void);
extern ULO cpuGetSspAutoMap(void);
extern void cpuSetSspDirect(uint32_t ssp);
extern uint32_t cpuGetSspDirect(void);
extern uint32_t cpuGetSspAutoMap(void);
extern ULO cpuGetVbr(void);
extern uint32_t cpuGetVbr(void);
extern void cpuSetStop(BOOLE stop);
extern BOOLE cpuGetStop(void);
extern void cpuSetInitialPC(ULO pc);
extern ULO cpuGetInitialPC(void);
extern void cpuSetInitialPC(uint32_t pc);
extern uint32_t cpuGetInitialPC(void);
extern void cpuSetInitialSP(ULO sp);
extern ULO cpuGetInitialSP(void);
extern void cpuSetInitialSP(uint32_t sp);
extern uint32_t cpuGetInitialSP(void);
extern ULO cpuGetInstructionTime(void);
extern uint32_t cpuGetInstructionTime(void);
extern BOOLE cpuSetIrqLevel(ULO irq_level);
extern ULO cpuGetIrqLevel(void);
extern BOOLE cpuSetIrqLevel(uint32_t irq_level);
extern uint32_t cpuGetIrqLevel(void);
extern ULO cpuExecuteInstruction(void);
extern ULO cpuDisOpcode(ULO disasm_pc, STR *saddress, STR *sdata, STR *sinstruction, STR *soperands);
extern uint32_t cpuExecuteInstruction(void);
extern uint32_t cpuDisOpcode(uint32_t disasm_pc, char *saddress, char *sdata, char *sinstruction, char *soperands);
extern void cpuSaveState(FILE *F);
extern void cpuLoadState(FILE *F);
@ -96,12 +97,10 @@ typedef void (*cpuResetExceptionFunc)(void);
extern void cpuSetResetExceptionFunc(cpuResetExceptionFunc func);
// Configuration settings
extern void cpuSetModel(ULO major, ULO minor);
extern ULO cpuGetModelMajor(void);
extern ULO cpuGetModelMinor(void);
extern void cpuSetModel(uint32_t major, uint32_t minor);
extern uint32_t cpuGetModelMajor(void);
extern uint32_t cpuGetModelMinor(void);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,105 +1,102 @@
#ifndef CPUMODULE_DISASSEMBLER_H
#define CPUMODULE_DISASSEMBLER_H
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
extern ULO cpuDisOpcode(ULO disasm_pc, STR *saddress, STR *sdata, STR *sinstruction, STR *soperands);
extern uint32_t cpuDisOpcode(uint32_t disasm_pc, char *saddress, char *sdata, char *sinstruction, char *soperands);
extern ULO cpuDisIllegal(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAbcd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAdd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAdda(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAddi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAddq(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAddx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAnd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAndi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAsx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBcc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBt(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisChk(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisClr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmp(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmpa(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmpi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmpm(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDBcc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDivs(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDivu(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisEor(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisEori(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisExg(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisExt(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisJmp(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisJsr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLea(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLink(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLsx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMove(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveToCcr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveToSr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveFromSr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveUsp(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovea(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovem(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovep(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveq(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMuls(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMulu(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNbcd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNeg(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNegx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNop(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNot(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisOr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisOri(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPea(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisReset(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRox(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRoxx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRte(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRtr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRts(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSbcd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisScc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisStop(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSub(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSuba(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSubi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSubq(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSubx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSwap(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTas(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTrap(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTrapv(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTst(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisUnlk(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBkpt(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBf(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCas(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisChkl(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisChk2(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDivl(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisExtb(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLinkl(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveFromCcr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovec(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoves(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMull(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPack(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPflush030(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPflush040(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPtest040(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRtd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTrapcc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisUnpk(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCallm(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRtm(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern uint32_t cpuDisIllegal(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAbcd(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAdd(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAdda(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAddi(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAddq(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAddx(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAnd(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAndi(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisAsx(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisBcc(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisBt(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisChk(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisClr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisCmp(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisCmpa(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisCmpi(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisCmpm(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisDBcc(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisDivs(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisDivu(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisEor(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisEori(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisExg(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisExt(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisJmp(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisJsr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisLea(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisLink(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisLsx(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMove(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoveToCcr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoveToSr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoveFromSr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoveUsp(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMovea(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMovem(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMovep(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoveq(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMuls(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMulu(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisNbcd(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisNeg(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisNegx(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisNop(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisNot(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisOr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisOri(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisPea(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisReset(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRox(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRoxx(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRte(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRtr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRts(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSbcd(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisScc(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisStop(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSub(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSuba(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSubi(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSubq(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSubx(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisSwap(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisTas(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisTrap(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisTrapv(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisTst(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisUnlk(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisBkpt(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisBf(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisCas(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisChkl(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisChk2(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisDivl(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisExtb(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisLinkl(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoveFromCcr(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMovec(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMoves(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisMull(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisPack(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisPflush030(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisPflush040(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisPtest040(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRtd(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisTrapcc(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisUnpk(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisCallm(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
extern uint32_t cpuDisRtm(uint32_t prc, uint32_t opc, char *sdata, char *sinstruction, char *soperands);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,7 +1,6 @@
#ifndef CPUMODULE_DISASSEMBLERFUNC_H
#define CPUMODULE_DISASSEMBLERFUNC_H
#pragma once
static UBY cpu_dis_func_tab[65536] =
static uint8_t cpu_dis_func_tab[65536] =
{
60,60,60,60,60,60,60,60,0,0,0,0,0,0,0,0,
60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
@ -259,7 +258,7 @@ static UBY cpu_dis_func_tab[65536] =
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -267,31 +266,31 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -299,31 +298,31 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -331,23 +330,23 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -355,7 +354,7 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -363,23 +362,23 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -387,7 +386,7 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -395,23 +394,23 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -419,7 +418,7 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -427,23 +426,23 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -451,7 +450,7 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -459,23 +458,23 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -483,7 +482,7 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -491,23 +490,23 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,0,0,0,0,0,0,0,0,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
39,39,39,39,39,39,39,39,39,39,39,39,39,0,0,0,
@ -4100,4 +4099,3 @@ static UBY cpu_dis_func_tab[65536] =
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
#endif

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_EffectiveAddress.c,v 1.3 2012-07-15 22:20:35 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* CPU 68k effective address calculation functions */
@ -30,22 +29,22 @@
#include "CpuModule_Internal.h"
/* Calculates EA for (Ax). */
ULO cpuEA02(ULO regno)
uint32_t cpuEA02(uint32_t regno)
{
return cpuGetAReg(regno);
}
/* Calculates EA for (Ax)+ */
ULO cpuEA03(ULO regno, ULO size)
uint32_t cpuEA03(uint32_t regno, uint32_t size)
{
ULO tmp = cpuGetAReg(regno);
uint32_t tmp = cpuGetAReg(regno);
if (regno == 7 && size == 1) size++;
cpuSetAReg(regno, tmp + size);
return tmp;
}
/* Calculates EA for -(Ax) */
ULO cpuEA04(ULO regno, ULO size)
uint32_t cpuEA04(uint32_t regno, uint32_t size)
{
if (regno == 7 && size == 1) size++;
cpuSetAReg(regno, cpuGetAReg(regno) - size);
@ -53,20 +52,20 @@ ULO cpuEA04(ULO regno, ULO size)
}
/* Calculates EA for disp16(Ax) */
ULO cpuEA05(ULO regno)
uint32_t cpuEA05(uint32_t regno)
{
return cpuGetAReg(regno) + cpuGetNextWordSignExt();
}
/* Calculates EA for disp8(Ax,Ri.size) with 68020 extended modes. */
static ULO cpuEA06Ext(UWO ext, ULO base_reg_value, ULO index_value)
static uint32_t cpuEA06Ext(uint16_t ext, uint32_t base_reg_value, uint32_t index_value)
{
ULO base_displacement;
ULO outer_displacement;
uint32_t base_displacement;
uint32_t outer_displacement;
BOOLE index_register_suppressed = (ext & 0x0040);
BOOLE base_register_suppressed = (ext & 0x0080);
ULO base_displacement_size = (ext >> 4) & 3;
ULO memory_indirect_action = (ext & 7);
uint32_t base_displacement_size = (ext >> 4) & 3;
uint32_t memory_indirect_action = (ext & 7);
if (memory_indirect_action == 4
|| (memory_indirect_action > 4 && index_register_suppressed))
@ -126,14 +125,14 @@ static ULO cpuEA06Ext(UWO ext, ULO base_reg_value, ULO index_value)
}
/* Calculates EA for disp8(Ax,Ri.size), calls cpuEA06Ext() for 68020 extended modes. */
ULO cpuEA06(ULO regno)
uint32_t cpuEA06(uint32_t regno)
{
ULO reg_value = cpuGetAReg(regno);
UWO ext = cpuGetNextWord();
ULO index_value = cpuGetReg(ext >> 15, (ext >> 12) & 7);
uint32_t reg_value = cpuGetAReg(regno);
uint16_t ext = cpuGetNextWord();
uint32_t index_value = cpuGetReg(ext >> 15, (ext >> 12) & 7);
if (!(ext & 0x0800))
{
index_value = cpuSignExtWordToLong((UWO)index_value);
index_value = cpuSignExtWordToLong((uint16_t)index_value);
}
if (cpuGetModelMajor() >= 2)
{
@ -143,17 +142,17 @@ ULO cpuEA06(ULO regno)
return cpuEA06Ext(ext, reg_value, index_value);
}
}
return reg_value + index_value + cpuSignExtByteToLong((UBY)ext);
return reg_value + index_value + cpuSignExtByteToLong((uint8_t)ext);
}
/* Calculates EA for xxxx.W */
ULO cpuEA70(void)
uint32_t cpuEA70()
{
return cpuGetNextWordSignExt();
}
/* Calculates EA for xxxxxxxx.L */
ULO cpuEA71(void)
uint32_t cpuEA71()
{
return cpuGetNextLong();
}
@ -162,9 +161,9 @@ ULO cpuEA71(void)
/// Calculates EA for disp16(PC)
/// </summary>
/// <returns>Address</returns>
ULO cpuEA72(void)
uint32_t cpuEA72()
{
ULO pc_tmp = cpuGetPC();
uint32_t pc_tmp = cpuGetPC();
return pc_tmp + cpuGetNextWordSignExt();
}
@ -172,14 +171,14 @@ ULO cpuEA72(void)
/// Calculates EA for disp8(PC,Ri.size). Calls cpuEA06Ext() to calculate extended 68020 modes.
/// </summary>
/// <returns>Address</returns>
ULO cpuEA73(void)
uint32_t cpuEA73()
{
ULO reg_value = cpuGetPC();
UWO ext = cpuGetNextWord();
ULO index_value = cpuGetReg(ext >> 15, (ext >> 12) & 0x7);
uint32_t reg_value = cpuGetPC();
uint16_t ext = cpuGetNextWord();
uint32_t index_value = cpuGetReg(ext >> 15, (ext >> 12) & 0x7);
if (!(ext & 0x0800))
{
index_value = cpuSignExtWordToLong((UWO)index_value);
index_value = cpuSignExtWordToLong((uint16_t)index_value);
}
if (cpuGetModelMajor() >= 2)
{
@ -189,5 +188,5 @@ ULO cpuEA73(void)
return cpuEA06Ext(ext, reg_value, index_value);
}
}
return reg_value + index_value + cpuSignExtByteToLong((UBY)ext);
return reg_value + index_value + cpuSignExtByteToLong((uint8_t)ext);
}

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_Exceptions.c,v 1.5 2012-08-12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* CPU 68k exception handling functions */
@ -29,6 +28,22 @@
#include "CpuModule.h"
#include "CpuModule_Internal.h"
// MPW
static cpuLineExceptionFunc cpu_a_line_exception_func = NULL;
static cpuLineExceptionFunc cpu_f_line_exception_func = NULL;
void cpuSetALineExceptionFunc(cpuLineExceptionFunc func)
{
cpu_a_line_exception_func = func;
}
void cpuSetFLineExceptionFunc(cpuLineExceptionFunc func)
{
cpu_f_line_exception_func = func;
}
/* Function for exiting from mid-instruction exceptions */
static cpuMidInstructionExceptionFunc cpu_mid_instruction_exception_func;
@ -55,12 +70,12 @@ void cpuSetResetExceptionFunc(cpuResetExceptionFunc func)
cpu_reset_exception_func = func;
}
static STR *cpuGetExceptionName(ULO vector_offset)
static char *cpuGetExceptionName(uint32_t vector_offset)
{
char *name;
if (vector_offset == 0x8)
name = "Exception: 2 - Access fault";
name = "Exception: 2 - Bus error";
else if (vector_offset == 0xc)
name = "Exception: 3 - Address error";
else if (vector_offset == 0x10)
@ -106,9 +121,9 @@ void cpuExceptionFail(BOOLE executejmp)
}
}
void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp)
void cpuThrowException(uint32_t vector_offset, uint32_t pc, BOOLE executejmp)
{
ULO vector_address;
uint32_t vector_address;
BOOLE is_address_error_on_sub_020 = (cpuGetModelMajor() < 2 && vector_offset == 0xc);
BOOLE stack_is_even = !(cpuGetAReg(7) & 1);
BOOLE vbr_is_even = !(cpuGetVbr() & 1);
@ -133,7 +148,7 @@ void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp)
return;
}
cpuStackFrameGenerate((UWO) vector_offset, pc);
cpuStackFrameGenerate((uint16_t) vector_offset, pc);
// read a memory position
vector_address = memoryReadLong(cpuGetVbr() + vector_offset);
@ -152,7 +167,40 @@ void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp)
cpuSetStop(FALSE);
cpuInitializeFromNewPC(vector_address);
cpuSetInstructionTime(40);
uint32_t exceptionCycles = 0;
switch (vector_offset)
{
case 0x08: exceptionCycles = 50; break; // Bus
case 0x0c: exceptionCycles = 50; break; // Address
case 0x10: exceptionCycles = 34; break; // Illegal
case 0x14: exceptionCycles = 42; break; // Division by zero
case 0x18: exceptionCycles = 28; break; // Chk
case 0x1c: exceptionCycles = 34; break; // Trapcc/trapv
case 0x20: exceptionCycles = 34; break; // Privilege
case 0x24: exceptionCycles = 34; break; // Trace
case 0x28: exceptionCycles = 34; break; // Line A
case 0x2c: exceptionCycles = 34; break; // Line F
case 0x80:
case 0x84:
case 0x88:
case 0x8c:
case 0x90:
case 0x94:
case 0x98:
case 0x9c:
case 0xa0:
case 0xa4:
case 0xa8:
case 0xac:
case 0xb0:
case 0xb4:
case 0xb8:
case 0xbc: exceptionCycles = 34; break; // TRAP
default: exceptionCycles = 4; break; // Should not come here
}
cpuSetInstructionTime(exceptionCycles);
}
// If the exception happened mid-instruction...
@ -164,6 +212,7 @@ void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp)
void cpuThrowPrivilegeViolationException(void)
{
cpuSetInstructionAborted(true);
// The saved pc points to the instruction causing the violation
// (And the kickstart excpects pc in the stack frame to be the opcode PC.)
cpuThrowException(0x20, cpuGetOriginalPC(), FALSE);
@ -171,18 +220,48 @@ void cpuThrowPrivilegeViolationException(void)
void cpuThrowIllegalInstructionException(BOOLE executejmp)
{
cpuSetInstructionAborted(true);
// The saved pc points to the illegal instruction
cpuThrowException(0x10, cpuGetOriginalPC(), executejmp);
}
void cpuThrowIllegalInstructionExceptionFromBreakpoint(void)
{
cpuSetInstructionAborted(true);
// The saved pc points to the illegal instruction
cpuThrowException(0x10, cpuGetPC(), FALSE);
}
void cpuThrowALineException(void)
{
// MPW
if (cpu_a_line_exception_func)
{
uint16_t opcode = memoryReadWord(cpuGetPC() - 2);
cpu_a_line_exception_func(opcode);
cpuInitializeFromNewPC(cpuGetPC());
cpuSetInstructionTime(512);
return;
}
cpuSetInstructionAborted(true);
// The saved pc points to the a-line instruction
cpuThrowException(0x28, cpuGetOriginalPC(), FALSE);
}
void cpuThrowFLineException(void)
{
// MPW
if (cpu_f_line_exception_func)
{
uint16_t opcode = memoryReadWord(cpuGetPC() - 2);
cpu_f_line_exception_func(opcode);
cpuInitializeFromNewPC(cpuGetPC());
cpuSetInstructionTime(512);
return;
}
cpuSetInstructionAborted(true);
// The saved pc points to the f-line instruction
cpuThrowException(0x2c, cpuGetOriginalPC(), FALSE);
}
@ -193,13 +272,13 @@ void cpuThrowTrapVException(void)
cpuThrowException(0x1c, cpuGetPC(), FALSE);
}
void cpuThrowDivisionByZeroException()
void cpuThrowDivisionByZeroException(void)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x14, cpuGetPC(), FALSE);
}
void cpuThrowTrapException(ULO vector_no)
void cpuThrowTrapException(uint32_t vector_no)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x80 + vector_no*4, cpuGetPC(), FALSE);
@ -219,6 +298,7 @@ void cpuThrowTraceException(void)
void cpuThrowAddressErrorException(void)
{
cpuSetInstructionAborted(true);
cpuThrowException(0xc, cpuGetPC() - 2, TRUE);
}

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_Flags.c,v 1.3 2011-07-18 17:22:55 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 flag and condition code handling */
@ -27,23 +26,23 @@
/// Sets the Z flag for bit operations
void cpuSetZFlagBitOpsB(UBY res)
void cpuSetZFlagBitOpsB(uint8_t res)
{
ULO flags = cpu_sr & 0xfffb;
uint32_t flags = cpu_sr & 0xfffb;
if (res == 0) flags |= 4;
cpu_sr = flags;
}
/// Sets the Z flag for bit operations
void cpuSetZFlagBitOpsL(ULO res)
void cpuSetZFlagBitOpsL(uint32_t res)
{
ULO flags = cpu_sr & 0xfffb;
uint32_t flags = cpu_sr & 0xfffb;
if (res == 0) flags |= 4;
cpu_sr = flags;
}
// rm,dm,sm
ULO cpu_xnvc_flag_add_table[2][2][2] = { 0,0x11,0x11,0x13,0xa,8,8,0x19};
uint32_t cpu_xnvc_flag_add_table[2][2][2] = { 0,0x11,0x11,0x13,0xa,8,8,0x19};
/// <summary>
/// Calculate XNVC flags of an add operation.
@ -51,13 +50,13 @@ ULO cpu_xnvc_flag_add_table[2][2][2] = { 0,0x11,0x11,0x13,0xa,8,8,0x19};
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagXNVCAdd(BOOLE rm, BOOLE dm, BOOLE sm)
static uint32_t cpuMakeFlagXNVCAdd(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_xnvc_flag_add_table[rm][dm][sm];
}
// rm,dm,sm
ULO cpu_nvc_flag_add_table[2][2][2] = { 0,1,1,3,0xa,8,8,9};
uint32_t cpu_nvc_flag_add_table[2][2][2] = { 0,1,1,3,0xa,8,8,9};
/// <summary>
/// Calculate NVC flags of an add operation for instructions not setting X.
@ -65,13 +64,13 @@ ULO cpu_nvc_flag_add_table[2][2][2] = { 0,1,1,3,0xa,8,8,9};
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagNVCAdd(BOOLE rm, BOOLE dm, BOOLE sm)
static uint32_t cpuMakeFlagNVCAdd(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_nvc_flag_add_table[rm][dm][sm];
}
// rm,dm,sm
ULO cpu_xnvc_flag_sub_table[2][2][2] = { 0,0x11,2,0,0x19,0x1b,8,0x19};
uint32_t cpu_xnvc_flag_sub_table[2][2][2] = { 0,0x11,2,0,0x19,0x1b,8,0x19};
/// <summary>
/// Calculate XNVC flags of a sub operation.
@ -79,13 +78,13 @@ ULO cpu_xnvc_flag_sub_table[2][2][2] = { 0,0x11,2,0,0x19,0x1b,8,0x19};
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagXNVCSub(BOOLE rm, BOOLE dm, BOOLE sm)
static uint32_t cpuMakeFlagXNVCSub(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_xnvc_flag_sub_table[rm][dm][sm];
}
// rm,dm,sm
ULO cpu_nvc_flag_sub_table[2][2][2] = { 0,1,2,0,9,0xb,8,9};
uint32_t cpu_nvc_flag_sub_table[2][2][2] = { 0,1,2,0,9,0xb,8,9};
/// <summary>
/// Calculate NVC flags of a sub operation for instructions not setting X.
@ -93,7 +92,7 @@ ULO cpu_nvc_flag_sub_table[2][2][2] = { 0,1,2,0,9,0xb,8,9};
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagNVCSub(BOOLE rm, BOOLE dm, BOOLE sm)
static uint32_t cpuMakeFlagNVCSub(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_nvc_flag_sub_table[rm][dm][sm];
}
@ -125,14 +124,6 @@ void cpuSetFlagV(BOOLE f)
cpu_sr = (cpu_sr & 0xfffd) | ((f) ? 2 : 0);
}
/// <summary>
/// Clear the V flag.
/// </summary>
static void cpuClearFlagV(void)
{
cpu_sr = cpu_sr & 0xfffd;
}
/// <summary>
/// Get the V flag.
/// </summary>
@ -159,22 +150,6 @@ void cpuSetFlagZ(BOOLE f)
cpu_sr = (cpu_sr & 0xfffb) | ((f) ? 4 : 0);
}
/// <summary>
/// Clear the Z flag.
/// </summary>
static void cpuClearFlagZ(void)
{
cpu_sr = cpu_sr & 0xfffb;
}
/// <summary>
/// Get the Z flag.
/// </summary>
static BOOLE cpuGetFlagZ(void)
{
return cpu_sr & 0x4;
}
/// <summary>
/// Get the X flag.
/// </summary>
@ -199,13 +174,13 @@ void cpuClearFlagsVC(void)
cpu_sr = cpu_sr & 0xfffc;
}
UWO cpuGetZFlagB(UBY res) {return (UWO)((res) ? 0 : 4);}
UWO cpuGetZFlagW(UWO res) {return (UWO)((res) ? 0 : 4);}
UWO cpuGetZFlagL(ULO res) {return (UWO)((res) ? 0 : 4);}
uint16_t cpuGetZFlagB(uint8_t res) {return (uint16_t)((res) ? 0 : 4);}
uint16_t cpuGetZFlagW(uint16_t res) {return (uint16_t)((res) ? 0 : 4);}
uint16_t cpuGetZFlagL(uint32_t res) {return (uint16_t)((res) ? 0 : 4);}
UWO cpuGetNFlagB(UBY res) {return (UWO)((res & 0x80) >> 4);}
UWO cpuGetNFlagW(UWO res) {return (UWO)((res & 0x8000) >> 12);}
UWO cpuGetNFlagL(ULO res) {return (UWO)((res & 0x80000000) >> 28);}
uint16_t cpuGetNFlagB(uint8_t res) {return (uint16_t)((res & 0x80) >> 4);}
uint16_t cpuGetNFlagW(uint16_t res) {return (uint16_t)((res & 0x8000) >> 12);}
uint16_t cpuGetNFlagL(uint32_t res) {return (uint16_t)((res & 0x80000000) >> 28);}
/// <summary>
/// Set the flags NZVC.
@ -216,7 +191,7 @@ UWO cpuGetNFlagL(ULO res) {return (UWO)((res & 0x80000000) >> 28);}
/// <param name="c">The C flag.</param>
void cpuSetFlagsNZVC(BOOLE z, BOOLE n, BOOLE v, BOOLE c)
{
ULO flags = cpu_sr & 0xfff0;
uint32_t flags = cpu_sr & 0xfff0;
if (n) flags |= 8;
else if (z) flags |= 4;
if (v) flags |= 2;
@ -231,7 +206,7 @@ void cpuSetFlagsNZVC(BOOLE z, BOOLE n, BOOLE v, BOOLE c)
/// <param name="c">The C flag.</param>
void cpuSetFlagsVC(BOOLE v, BOOLE c)
{
ULO flags = cpu_sr & 0xfffc;
uint32_t flags = cpu_sr & 0xfffc;
if (v) flags |= 2;
if (c) flags |= 1;
cpu_sr = flags;
@ -246,7 +221,7 @@ void cpuSetFlagsVC(BOOLE v, BOOLE c)
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsAdd(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & 0xffe0;
uint32_t flags = cpu_sr & 0xffe0;
if (z) flags |= 4;
flags |= cpuMakeFlagXNVCAdd(rm, dm, sm);
cpu_sr = flags;
@ -261,7 +236,7 @@ void cpuSetFlagsAdd(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsSub(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & 0xffe0;
uint32_t flags = cpu_sr & 0xffe0;
if (z) flags |= 4;
flags |= cpuMakeFlagXNVCSub(rm, dm, sm);
cpu_sr = flags;
@ -276,7 +251,7 @@ void cpuSetFlagsSub(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsAddX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
uint32_t flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
flags |= cpuMakeFlagXNVCAdd(rm, dm, sm);
cpu_sr = flags;
}
@ -290,7 +265,7 @@ void cpuSetFlagsAddX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsSubX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
uint32_t flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
flags |= cpuMakeFlagXNVCSub(rm, dm, sm);
cpu_sr = flags;
}
@ -303,7 +278,7 @@ void cpuSetFlagsSubX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
/// <param name="dm">The MSB of the destination source.</param>
void cpuSetFlagsNeg(BOOLE z, BOOLE rm, BOOLE dm)
{
ULO flags = cpu_sr & 0xffe0;
uint32_t flags = cpu_sr & 0xffe0;
if (z) flags |= 4;
else
{
@ -325,7 +300,7 @@ void cpuSetFlagsNeg(BOOLE z, BOOLE rm, BOOLE dm)
/// <param name="dm">The MSB of the destination source.</param>
void cpuSetFlagsNegx(BOOLE z, BOOLE rm, BOOLE dm)
{
ULO flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
uint32_t flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
if (dm || rm)
{
flags |= 0x11; // XC
@ -347,7 +322,7 @@ void cpuSetFlagsNegx(BOOLE z, BOOLE rm, BOOLE dm)
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsCmp(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & 0xfff0;
uint32_t flags = cpu_sr & 0xfff0;
if (z) flags |= 4;
flags |= cpuMakeFlagNVCSub(rm, dm, sm);
cpu_sr = flags;
@ -360,7 +335,7 @@ void cpuSetFlagsCmp(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
/// <param name="rm">The MSB of the result.</param>
void cpuSetFlagsShiftZero(BOOLE z, BOOLE rm)
{
ULO flags = cpu_sr & 0xfff0; // Always clearing the VC flag
uint32_t flags = cpu_sr & 0xfff0; // Always clearing the VC flag
if (rm) flags |= 8;
else if (z) flags |= 4;
cpu_sr = flags;
@ -375,7 +350,7 @@ void cpuSetFlagsShiftZero(BOOLE z, BOOLE rm)
/// <param name="c">The overflow of the result.</param>
void cpuSetFlagsShift(BOOLE z, BOOLE rm, BOOLE c, BOOLE v)
{
ULO flags = cpu_sr & 0xffe0;
uint32_t flags = cpu_sr & 0xffe0;
if (rm) flags |= 8;
else if (z) flags |= 4;
if (v) flags |= 2;
@ -391,7 +366,7 @@ void cpuSetFlagsShift(BOOLE z, BOOLE rm, BOOLE c, BOOLE v)
/// <param name="c">The carry of the result.</param>
void cpuSetFlagsRotate(BOOLE z, BOOLE rm, BOOLE c)
{
ULO flags = cpu_sr & 0xfff0; // Always clearing the V flag
uint32_t flags = cpu_sr & 0xfff0; // Always clearing the V flag
if (rm) flags |= 8;
else if (z) flags |= 4;
@ -406,7 +381,7 @@ void cpuSetFlagsRotate(BOOLE z, BOOLE rm, BOOLE c)
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="c">The extend bit and carry of the result.</param>
void cpuSetFlagsRotateX(UWO z, UWO rm, UWO x)
void cpuSetFlagsRotateX(uint16_t z, uint16_t rm, uint16_t x)
{
cpu_sr = (cpu_sr & 0xffe0) | z | rm | x;
}
@ -414,9 +389,9 @@ void cpuSetFlagsRotateX(UWO z, UWO rm, UWO x)
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00NewB(UBY res)
void cpuSetFlagsNZ00NewB(uint8_t res)
{
ULO flag = cpu_sr & 0xfff0;
uint32_t flag = cpu_sr & 0xfff0;
if (res & 0x80) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
@ -425,9 +400,9 @@ void cpuSetFlagsNZ00NewB(UBY res)
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00NewW(UWO res)
void cpuSetFlagsNZ00NewW(uint16_t res)
{
ULO flag = cpu_sr & 0xfff0;
uint32_t flag = cpu_sr & 0xfff0;
if (res & 0x8000) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
@ -436,9 +411,9 @@ void cpuSetFlagsNZ00NewW(UWO res)
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00NewL(ULO res)
void cpuSetFlagsNZ00NewL(uint32_t res)
{
ULO flag = cpu_sr & 0xfff0;
uint32_t flag = cpu_sr & 0xfff0;
if (res & 0x80000000) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
@ -447,9 +422,9 @@ void cpuSetFlagsNZ00NewL(ULO res)
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00New64(LLO res)
void cpuSetFlagsNZ00New64(int64_t res)
{
ULO flag = cpu_sr & 0xfff0;
uint32_t flag = cpu_sr & 0xfff0;
if (res < 0) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
@ -459,7 +434,7 @@ void cpuSetFlagsNZ00New64(LLO res)
/// Set the 4 flags absolute.
/// </summary>
/// <param name="f">flags</param>
void cpuSetFlagsAbs(UWO f)
void cpuSetFlagsAbs(uint16_t f)
{
cpu_sr = (cpu_sr & 0xfff0) | f;
}
@ -530,29 +505,29 @@ BOOLE cpuCalculateConditionCode11(void)
BOOLE cpuCalculateConditionCode12(void)
{
ULO tmp = cpu_sr & 0xa;
uint32_t tmp = cpu_sr & 0xa;
return (tmp == 0xa) || (tmp == 0); // GE - (N && V) || (!N && !V)
}
BOOLE cpuCalculateConditionCode13(void)
{
ULO tmp = cpu_sr & 0xa;
uint32_t tmp = cpu_sr & 0xa;
return (tmp == 0x8) || (tmp == 0x2); // LT - (N && !V) || (!N && V)
}
BOOLE cpuCalculateConditionCode14(void)
{
ULO tmp = cpu_sr & 0xa;
uint32_t tmp = cpu_sr & 0xa;
return (!(cpu_sr & 0x4)) && ((tmp == 0xa) || (tmp == 0)); // GT - (N && V && !Z) || (!N && !V && !Z)
}
BOOLE cpuCalculateConditionCode15(void)
{
ULO tmp = cpu_sr & 0xa;
uint32_t tmp = cpu_sr & 0xa;
return (cpu_sr & 0x4) || (tmp == 0x8) || (tmp == 2);// LE - Z || (N && !V) || (!N && V)
}
BOOLE cpuCalculateConditionCode(ULO cc)
BOOLE cpuCalculateConditionCode(uint32_t cc)
{
switch (cc & 0xf)
{

File diff suppressed because it is too large Load Diff

View File

@ -1,115 +1,112 @@
#ifndef CpuModule_Internal_H
#define CpuModule_Internal_H
#ifdef __cplusplus
extern "C" {
#endif
#pragma once
// This header file defines the internal interfaces of the CPU module.
extern void cpuMakeOpcodeTableForModel(void);
extern void cpuCreateMulTimeTables(void);
// StackFrameGen
extern void cpuStackFrameGenerate(UWO vector_no, ULO pc);
extern void cpuStackFrameGenerate(uint16_t vector_no, uint32_t pc);
extern void cpuStackFrameInit(void);
// Registers
extern ULO cpu_sr; // Not static because the flags calculation uses it extensively
extern uint32_t cpu_sr; // Not static because the flags calculation uses it extensively
extern BOOLE cpuGetFlagSupervisor(void);
extern BOOLE cpuGetFlagMaster(void);
extern void cpuSetUspDirect(ULO usp);
extern ULO cpuGetUspDirect(void);
extern ULO cpuGetUspAutoMap(void);
extern void cpuSetSspDirect(ULO ssp);
extern ULO cpuGetSspDirect(void);
extern ULO cpuGetSspAutoMap(void);
extern void cpuSetMspDirect(ULO msp);
extern ULO cpuGetMspDirect(void);
extern ULO cpuGetMspAutoMap(void);
extern void cpuSetMspAutoMap(ULO new_msp);
extern ULO cpuGetIspAutoMap(void);
extern void cpuSetIspAutoMap(ULO new_isp);
extern void cpuSetDReg(ULO i, ULO value);
extern ULO cpuGetDReg(ULO i);
extern void cpuSetAReg(ULO i, ULO value);
extern ULO cpuGetAReg(ULO i);
extern void cpuSetReg(ULO da, ULO i, ULO value);
extern ULO cpuGetReg(ULO da, ULO i);
extern void cpuSetPC(ULO address);
extern ULO cpuGetPC(void);
extern void cpuSetUspDirect(uint32_t usp);
extern uint32_t cpuGetUspDirect(void);
extern uint32_t cpuGetUspAutoMap(void);
extern void cpuSetSspDirect(uint32_t ssp);
extern uint32_t cpuGetSspDirect(void);
extern uint32_t cpuGetSspAutoMap(void);
extern void cpuSetMspDirect(uint32_t msp);
extern uint32_t cpuGetMspDirect(void);
extern uint32_t cpuGetMspAutoMap(void);
extern void cpuSetMspAutoMap(uint32_t new_msp);
extern uint32_t cpuGetIspAutoMap(void);
extern void cpuSetIspAutoMap(uint32_t new_isp);
extern void cpuSetDReg(uint32_t i, uint32_t value);
extern uint32_t cpuGetDReg(uint32_t i);
extern void cpuSetAReg(uint32_t i, uint32_t value);
extern uint32_t cpuGetAReg(uint32_t i);
extern void cpuSetReg(uint32_t da, uint32_t i, uint32_t value);
extern uint32_t cpuGetReg(uint32_t da, uint32_t i);
extern void cpuSetPC(uint32_t address);
extern uint32_t cpuGetPC(void);
extern void cpuSetStop(BOOLE stop);
extern BOOLE cpuGetStop(void);
extern void cpuSetVbr(ULO vbr);
extern ULO cpuGetVbr(void);
extern void cpuSetSfc(ULO sfc);
extern ULO cpuGetSfc(void);
extern void cpuSetDfc(ULO dfc);
extern ULO cpuGetDfc(void);
extern void cpuSetCacr(ULO cacr);
extern ULO cpuGetCacr(void);
extern void cpuSetCaar(ULO caar);
extern ULO cpuGetCaar(void);
extern void cpuSetSR(ULO sr);
extern ULO cpuGetSR(void);
extern void cpuSetInstructionTime(ULO cycles);
extern ULO cpuGetInstructionTime(void);
extern void cpuSetOriginalPC(ULO pc);
extern ULO cpuGetOriginalPC(void);
extern void cpuSetVbr(uint32_t vbr);
extern uint32_t cpuGetVbr(void);
extern void cpuSetSfc(uint32_t sfc);
extern uint32_t cpuGetSfc(void);
extern void cpuSetDfc(uint32_t dfc);
extern uint32_t cpuGetDfc(void);
extern void cpuSetCacr(uint32_t cacr);
extern uint32_t cpuGetCacr(void);
extern void cpuSetCaar(uint32_t caar);
extern uint32_t cpuGetCaar(void);
extern void cpuSetSR(uint32_t sr);
extern uint32_t cpuGetSR(void);
extern void cpuSetInstructionTime(uint32_t cycles);
extern uint32_t cpuGetInstructionTime(void);
extern void cpuSetOriginalPC(uint32_t pc);
extern uint32_t cpuGetOriginalPC(void);
extern void cpuSetInstructionAborted(bool aborted);
extern bool cpuGetInstructionAborted(void);
#ifdef CPU_INSTRUCTION_LOGGING
extern void cpuSetCurrentOpcode(UWO opcode);
extern UWO cpuGetCurrentOpcode(void);
extern void cpuSetCurrentOpcode(uint16_t opcode);
extern uint16_t cpuGetCurrentOpcode(void);
#endif
extern void cpuProfileWrite(void);
extern void cpuSetModelMask(UBY model_mask);
extern UBY cpuGetModelMask(void);
extern void cpuSetDRegWord(ULO regno, UWO val);
extern void cpuSetDRegByte(ULO regno, UBY val);
extern UWO cpuGetRegWord(ULO i, ULO regno);
extern UWO cpuGetDRegWord(ULO regno);
extern UBY cpuGetDRegByte(ULO regno);
extern ULO cpuGetDRegWordSignExtLong(ULO regno);
extern UWO cpuGetDRegByteSignExtWord(ULO regno);
extern ULO cpuGetDRegByteSignExtLong(ULO regno);
extern UWO cpuGetARegWord(ULO regno);
extern UBY cpuGetARegByte(ULO regno);
extern void cpuSetModelMask(uint8_t model_mask);
extern uint8_t cpuGetModelMask(void);
extern void cpuSetDRegWord(uint32_t regno, uint16_t val);
extern void cpuSetDRegByte(uint32_t regno, uint8_t val);
extern uint16_t cpuGetRegWord(uint32_t i, uint32_t regno);
extern uint16_t cpuGetDRegWord(uint32_t regno);
extern uint8_t cpuGetDRegByte(uint32_t regno);
extern uint32_t cpuGetDRegWordSignExtLong(uint32_t regno);
extern uint16_t cpuGetDRegByteSignExtWord(uint32_t regno);
extern uint32_t cpuGetDRegByteSignExtLong(uint32_t regno);
extern uint16_t cpuGetARegWord(uint32_t regno);
extern uint8_t cpuGetARegByte(uint32_t regno);
extern UWO cpuGetNextWord(void);
extern ULO cpuGetNextWordSignExt(void);
extern ULO cpuGetNextLong(void);
extern uint16_t cpuGetNextWord(void);
extern uint32_t cpuGetNextWordSignExt(void);
extern uint32_t cpuGetNextLong(void);
extern void cpuSkipNextWord(void);
extern void cpuSkipNextLong(void);
extern void cpuClearPrefetch(void);
extern void cpuValidateReadPointer(void);
extern void cpuInitializeFromNewPC(ULO new_pc);
extern void cpuInitializeFromNewPC(uint32_t new_pc);
// Effective address
extern ULO cpuEA02(ULO regno);
extern ULO cpuEA03(ULO regno, ULO size);
extern ULO cpuEA04(ULO regno, ULO size);
extern ULO cpuEA05(ULO regno);
extern ULO cpuEA06(ULO regno);
extern ULO cpuEA70(void);
extern ULO cpuEA71(void);
extern ULO cpuEA72(void);
extern ULO cpuEA73(void);
extern uint32_t cpuEA02(uint32_t regno);
extern uint32_t cpuEA03(uint32_t regno, uint32_t size);
extern uint32_t cpuEA04(uint32_t regno, uint32_t size);
extern uint32_t cpuEA05(uint32_t regno);
extern uint32_t cpuEA06(uint32_t regno);
extern uint32_t cpuEA70(void);
extern uint32_t cpuEA71(void);
extern uint32_t cpuEA72(void);
extern uint32_t cpuEA73(void);
// Flags
extern void cpuSetFlagsAdd(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsSub(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsCmp(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetZFlagBitOpsB(UBY res);
extern void cpuSetZFlagBitOpsL(ULO res);
extern void cpuSetZFlagBitOpsB(uint8_t res);
extern void cpuSetZFlagBitOpsL(uint32_t res);
extern void cpuSetFlagsNZ00NewB(UBY res);
extern void cpuSetFlagsNZ00NewW(UWO res);
extern void cpuSetFlagsNZ00NewL(ULO res);
extern void cpuSetFlagsNZ00New64(LLO res);
extern void cpuSetFlagsNZ00NewB(uint8_t res);
extern void cpuSetFlagsNZ00NewW(uint16_t res);
extern void cpuSetFlagsNZ00NewL(uint32_t res);
extern void cpuSetFlagsNZ00New64(int64_t res);
extern void cpuSetFlagZ(BOOLE f);
extern void cpuSetFlagN(BOOLE f);
@ -126,16 +123,16 @@ extern void cpuSetFlagsVC(BOOLE v, BOOLE c);
extern void cpuSetFlagsShiftZero(BOOLE z, BOOLE rm);
extern void cpuSetFlagsShift(BOOLE z, BOOLE rm, BOOLE c, BOOLE v);
extern void cpuSetFlagsRotate(BOOLE z, BOOLE rm, BOOLE c);
extern void cpuSetFlagsRotateX(UWO z, UWO rm, UWO x);
extern void cpuSetFlagsRotateX(uint16_t z, uint16_t rm, uint16_t x);
extern void cpuSetFlagsAddX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsSubX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsAbs(UWO f);
extern UWO cpuGetZFlagB(UBY res);
extern UWO cpuGetZFlagW(UWO res);
extern UWO cpuGetZFlagL(ULO res);
extern UWO cpuGetNFlagB(UBY res);
extern UWO cpuGetNFlagW(UWO res);
extern UWO cpuGetNFlagL(ULO res);
extern void cpuSetFlagsAbs(uint16_t f);
extern uint16_t cpuGetZFlagB(uint8_t res);
extern uint16_t cpuGetZFlagW(uint16_t res);
extern uint16_t cpuGetZFlagL(uint32_t res);
extern uint16_t cpuGetNFlagB(uint8_t res);
extern uint16_t cpuGetNFlagW(uint16_t res);
extern uint16_t cpuGetNFlagL(uint32_t res);
extern void cpuClearFlagsVC(void);
extern BOOLE cpuCalculateConditionCode0(void);
@ -154,53 +151,47 @@ extern BOOLE cpuCalculateConditionCode12(void);
extern BOOLE cpuCalculateConditionCode13(void);
extern BOOLE cpuCalculateConditionCode14(void);
extern BOOLE cpuCalculateConditionCode15(void);
extern BOOLE cpuCalculateConditionCode(ULO cc);
extern BOOLE cpuCalculateConditionCode(uint32_t cc);
// Logging
#ifdef CPU_INSTRUCTION_LOGGING
extern void cpuCallInstructionLoggingFunc(void);
extern void cpuCallExceptionLoggingFunc(STR *description, ULO original_pc, UWO opcode);
extern void cpuCallInterruptLoggingFunc(ULO level, ULO vector_address);
extern void cpuCallExceptionLoggingFunc(char *description, uint32_t original_pc, uint16_t opcode);
extern void cpuCallInterruptLoggingFunc(uint32_t level, uint32_t vector_address);
#endif
// Interrupt
extern ULO cpuActivateSSP(void);
extern uint32_t cpuActivateSSP(void);
extern void cpuSetRaiseInterrupt(BOOLE raise_irq);
extern BOOLE cpuGetRaiseInterrupt(void);
extern void cpuSetRaiseInterruptLevel(ULO raise_irq_level);
extern ULO cpuGetRaiseInterruptLevel(void);
extern void cpuSetRaiseInterruptLevel(uint32_t raise_irq_level);
extern uint32_t cpuGetRaiseInterruptLevel(void);
// Exceptions
extern void cpuThrowPrivilegeViolationException(void);
extern void cpuThrowIllegalInstructionException(BOOLE executejmp);
extern void cpuThrowIllegalInstructionExceptionFromBreakpoint(void);
extern void cpuThrowFLineException(void);
extern void cpuThrowALineException(void);
extern void cpuThrowTrapVException(void);
extern void cpuThrowTrapException(ULO vector_no);
extern void cpuThrowDivisionByZeroException();
extern void cpuThrowTrapException(uint32_t vector_no);
extern void cpuThrowDivisionByZeroException(void);
extern void cpuThrowChkException(void);
extern void cpuThrowTraceException(void);
extern void cpuThrowResetException(void);
extern void cpuCallResetExceptionFunc(void);
extern void cpuFrame1(UWO vector_offset, ULO pc);
extern void cpuFrame1(uint16_t vector_offset, uint32_t pc);
// Private help functions
static ULO cpuSignExtByteToLong(UBY v) {return (ULO)(LON)(BYT) v;}
static UWO cpuSignExtByteToWord(UBY v) {return (UWO)(WOR)(BYT) v;}
static ULO cpuSignExtWordToLong(UWO v) {return (ULO)(LON)(WOR) v;}
static ULO cpuJoinWordToLong(UWO upper, UWO lower) {return (((ULO)upper) << 16) | ((ULO)lower);}
static ULO cpuJoinByteToLong(UBY upper, UBY midh, UBY midl, UBY lower) {return (((ULO)upper) << 24) | (((ULO)midh) << 16) | (((ULO)midl) << 8) | ((ULO)lower);}
static UWO cpuJoinByteToWord(UBY upper, UBY lower) {return (((UWO)upper) << 8) | ((UWO)lower);}
static BOOLE cpuMsbB(UBY v) {return v>>7;}
static BOOLE cpuMsbW(UWO v) {return v>>15;}
static BOOLE cpuMsbL(ULO v) {return v>>31;}
static BOOLE cpuIsZeroB(UBY v) {return v == 0;}
static BOOLE cpuIsZeroW(UWO v) {return v == 0;}
static BOOLE cpuIsZeroL(ULO v) {return v == 0;}
#ifdef __cplusplus
}
#endif
#endif
static uint32_t cpuSignExtByteToLong(uint8_t v) {return (uint32_t)(int32_t)(int8_t) v;}
static uint16_t cpuSignExtByteToWord(uint8_t v) {return (uint16_t)(int16_t)(int8_t) v;}
static uint32_t cpuSignExtWordToLong(uint16_t v) {return (uint32_t)(int32_t)(int16_t) v;}
static uint32_t cpuJoinWordToLong(uint16_t upper, uint16_t lower) {return (((uint32_t)upper) << 16) | ((uint32_t)lower);}
static uint32_t cpuJoinByteToLong(uint8_t upper, uint8_t midh, uint8_t midl, uint8_t lower) {return (((uint32_t)upper) << 24) | (((uint32_t)midh) << 16) | (((uint32_t)midl) << 8) | ((uint32_t)lower);}
static uint16_t cpuJoinByteToWord(uint8_t upper, uint8_t lower) {return (((uint16_t)upper) << 8) | ((uint16_t)lower);}
static BOOLE cpuMsbB(uint8_t v) {return v>>7;}
static BOOLE cpuMsbW(uint16_t v) {return v>>15;}
static BOOLE cpuMsbL(uint32_t v) {return v>>31;}
static BOOLE cpuIsZeroB(uint8_t v) {return v == 0;}
static BOOLE cpuIsZeroW(uint16_t v) {return v == 0;}
static BOOLE cpuIsZeroL(uint32_t v) {return v == 0;}

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_InternalState.c,v 1.9 2012-08-12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 internal state */
@ -27,57 +26,58 @@
#include "CpuModule_Internal.h"
/* M68k registers */
static ULO cpu_regs[2][8]; /* 0 - data, 1 - address */
static ULO cpu_pc;
static ULO cpu_usp;
static ULO cpu_ssp;
static ULO cpu_msp;
static ULO cpu_sfc;
static ULO cpu_dfc;
ULO cpu_sr; // Not static because flags calculation use it extensively
static ULO cpu_vbr;
static UWO cpu_prefetch_word;
static ULO cpu_cacr;
static ULO cpu_caar;
static uint32_t cpu_regs[2][8]; /* 0 - data, 1 - address */
static uint32_t cpu_pc;
static uint32_t cpu_usp;
static uint32_t cpu_ssp;
static uint32_t cpu_msp;
static uint32_t cpu_sfc;
static uint32_t cpu_dfc;
uint32_t cpu_sr; // Not static because flags calculation use it extensively
static uint32_t cpu_vbr;
static uint16_t cpu_prefetch_word;
static uint32_t cpu_cacr;
static uint32_t cpu_caar;
/* Irq management */
static BOOLE cpu_raise_irq;
static ULO cpu_raise_irq_level;
static uint32_t cpu_raise_irq_level;
/* Reset values */
static ULO cpu_initial_pc;
static ULO cpu_initial_sp;
static uint32_t cpu_initial_pc;
static uint32_t cpu_initial_sp;
/* Flag set if CPU is stopped */
static BOOLE cpu_stop;
/* The current CPU model */
static ULO cpu_model_major = -1;
static ULO cpu_model_minor;
static UBY cpu_model_mask;
static uint32_t cpu_model_major = -1;
static uint32_t cpu_model_minor;
static uint8_t cpu_model_mask;
/* For exception handling */
#ifdef CPU_INSTRUCTION_LOGGING
static UWO cpu_current_opcode;
static uint16_t cpu_current_opcode;
#endif
static ULO cpu_original_pc;
static uint32_t cpu_original_pc;
static bool cpu_instruction_aborted;
/* Number of cycles taken by the last intstruction */
static ULO cpu_instruction_time;
static uint32_t cpu_instruction_time;
/* Getters and setters */
void cpuSetDReg(ULO i, ULO value) {cpu_regs[0][i] = value;}
ULO cpuGetDReg(ULO i) {return cpu_regs[0][i];}
void cpuSetDReg(uint32_t i, uint32_t value) {cpu_regs[0][i] = value;}
uint32_t cpuGetDReg(uint32_t i) {return cpu_regs[0][i];}
void cpuSetAReg(ULO i, ULO value) {cpu_regs[1][i] = value;}
ULO cpuGetAReg(ULO i) {return cpu_regs[1][i];}
void cpuSetAReg(uint32_t i, uint32_t value) {cpu_regs[1][i] = value;}
uint32_t cpuGetAReg(uint32_t i) {return cpu_regs[1][i];}
void cpuSetReg(ULO da, ULO i, ULO value) {cpu_regs[da][i] = value;}
ULO cpuGetReg(ULO da, ULO i) {return cpu_regs[da][i];}
void cpuSetReg(uint32_t da, uint32_t i, uint32_t value) {cpu_regs[da][i] = value;}
uint32_t cpuGetReg(uint32_t da, uint32_t i) {return cpu_regs[da][i];}
/// <summary>
/// Get the supervisor bit from sr.
@ -95,21 +95,21 @@ BOOLE cpuGetFlagMaster(void)
return cpu_sr & 0x1000;
}
void cpuSetUspDirect(ULO usp) {cpu_usp = usp;}
ULO cpuGetUspDirect(void) {return cpu_usp;}
ULO cpuGetUspAutoMap(void) {return (cpuGetFlagSupervisor()) ? cpuGetUspDirect() : cpuGetAReg(7);}
void cpuSetUspDirect(uint32_t usp) {cpu_usp = usp;}
uint32_t cpuGetUspDirect() {return cpu_usp;}
uint32_t cpuGetUspAutoMap() {return (cpuGetFlagSupervisor()) ? cpuGetUspDirect() : cpuGetAReg(7);}
void cpuSetSspDirect(ULO ssp) {cpu_ssp = ssp;}
ULO cpuGetSspDirect(void) {return cpu_ssp;}
ULO cpuGetSspAutoMap(void) {return (cpuGetFlagSupervisor()) ? cpuGetAReg(7) : cpuGetSspDirect();}
void cpuSetSspDirect(uint32_t ssp) {cpu_ssp = ssp;}
uint32_t cpuGetSspDirect() {return cpu_ssp;}
uint32_t cpuGetSspAutoMap() {return (cpuGetFlagSupervisor()) ? cpuGetAReg(7) : cpuGetSspDirect();}
void cpuSetMspDirect(ULO msp) {cpu_msp = msp;}
ULO cpuGetMspDirect(void) {return cpu_msp;}
void cpuSetMspDirect(uint32_t msp) {cpu_msp = msp;}
uint32_t cpuGetMspDirect() {return cpu_msp;}
/// <summary>
/// Returns the master stack pointer.
/// </summary>
ULO cpuGetMspAutoMap(void)
uint32_t cpuGetMspAutoMap(void)
{
if (cpuGetFlagSupervisor() && cpuGetFlagMaster())
{
@ -121,7 +121,7 @@ ULO cpuGetMspAutoMap(void)
/// <summary>
/// Sets the master stack pointer.
/// </summary>
void cpuSetMspAutoMap(ULO new_msp)
void cpuSetMspAutoMap(uint32_t new_msp)
{
if (cpuGetFlagSupervisor() && cpuGetFlagMaster())
{
@ -136,7 +136,7 @@ void cpuSetMspAutoMap(ULO new_msp)
/// <summary>
/// Returns the interrupt stack pointer. ssp is used as isp.
/// </summary>
ULO cpuGetIspAutoMap(void)
uint32_t cpuGetIspAutoMap(void)
{
if (cpuGetFlagSupervisor() && !cpuGetFlagMaster())
{
@ -148,7 +148,7 @@ ULO cpuGetIspAutoMap(void)
/// <summary>
/// Sets the interrupt stack pointer. ssp is used as isp.
/// </summary>
void cpuSetIspAutoMap(ULO new_isp)
void cpuSetIspAutoMap(uint32_t new_isp)
{
if (cpuGetFlagSupervisor() && !cpuGetFlagMaster())
{
@ -160,61 +160,64 @@ void cpuSetIspAutoMap(ULO new_isp)
}
}
void cpuSetPC(ULO address) {cpu_pc = address;}
ULO cpuGetPC(void) {return cpu_pc;}
void cpuSetPC(uint32_t address) {cpu_pc = address;}
uint32_t cpuGetPC() {return cpu_pc;}
void cpuSetStop(BOOLE stop) {cpu_stop = stop;}
BOOLE cpuGetStop(void) {return cpu_stop;}
BOOLE cpuGetStop() {return cpu_stop;}
void cpuSetVbr(ULO vbr) {cpu_vbr = vbr;}
ULO cpuGetVbr(void) {return cpu_vbr;}
void cpuSetVbr(uint32_t vbr) {cpu_vbr = vbr;}
uint32_t cpuGetVbr() {return cpu_vbr;}
void cpuSetSfc(ULO sfc) {cpu_sfc = sfc;}
ULO cpuGetSfc(void) {return cpu_sfc;}
void cpuSetSfc(uint32_t sfc) {cpu_sfc = sfc;}
uint32_t cpuGetSfc() {return cpu_sfc;}
void cpuSetDfc(ULO dfc) {cpu_dfc = dfc;}
ULO cpuGetDfc(void) {return cpu_dfc;}
void cpuSetDfc(uint32_t dfc) {cpu_dfc = dfc;}
uint32_t cpuGetDfc() {return cpu_dfc;}
void cpuSetCacr(ULO cacr) {cpu_cacr = cacr;}
ULO cpuGetCacr(void) {return cpu_cacr;}
void cpuSetCacr(uint32_t cacr) {cpu_cacr = cacr;}
uint32_t cpuGetCacr() {return cpu_cacr;}
void cpuSetCaar(ULO caar) {cpu_caar = caar;}
ULO cpuGetCaar(void) {return cpu_caar;}
void cpuSetCaar(uint32_t caar) {cpu_caar = caar;}
uint32_t cpuGetCaar() {return cpu_caar;}
void cpuSetSR(ULO sr) {cpu_sr = sr;}
ULO cpuGetSR(void) {return cpu_sr;}
void cpuSetSR(uint32_t sr) {cpu_sr = sr;}
uint32_t cpuGetSR() {return cpu_sr;}
void cpuSetInstructionTime(ULO cycles) {cpu_instruction_time = cycles;}
ULO cpuGetInstructionTime(void) {return cpu_instruction_time;}
void cpuSetInstructionTime(uint32_t cycles) {cpu_instruction_time = cycles;}
uint32_t cpuGetInstructionTime() {return cpu_instruction_time;}
void cpuSetOriginalPC(ULO pc) {cpu_original_pc = pc;}
ULO cpuGetOriginalPC(void) {return cpu_original_pc;}
void cpuSetOriginalPC(uint32_t pc) {cpu_original_pc = pc;}
uint32_t cpuGetOriginalPC() {return cpu_original_pc;}
void cpuSetInstructionAborted(bool aborted) {cpu_instruction_aborted = aborted;}
bool cpuGetInstructionAborted() {return cpu_instruction_aborted;}
#ifdef CPU_INSTRUCTION_LOGGING
void cpuSetCurrentOpcode(UWO opcode) {cpu_current_opcode = opcode;}
UWO cpuGetCurrentOpcode(void) {return cpu_current_opcode;}
void cpuSetCurrentOpcode(uint16_t opcode) {cpu_current_opcode = opcode;}
uint16_t cpuGetCurrentOpcode() {return cpu_current_opcode;}
#endif
void cpuSetRaiseInterrupt(BOOLE raise_irq) {cpu_raise_irq = raise_irq;}
BOOLE cpuGetRaiseInterrupt(void) {return cpu_raise_irq;}
void cpuSetRaiseInterruptLevel(ULO raise_irq_level) {cpu_raise_irq_level = raise_irq_level;}
ULO cpuGetRaiseInterruptLevel(void) {return cpu_raise_irq_level;}
BOOLE cpuGetRaiseInterrupt() {return cpu_raise_irq;}
void cpuSetRaiseInterruptLevel(uint32_t raise_irq_level) {cpu_raise_irq_level = raise_irq_level;}
uint32_t cpuGetRaiseInterruptLevel() {return cpu_raise_irq_level;}
ULO cpuGetIrqLevel(void) {return (cpu_sr & 0x0700) >> 8;}
uint32_t cpuGetIrqLevel() {return (cpu_sr & 0x0700) >> 8;}
void cpuSetInitialPC(ULO pc) {cpu_initial_pc = pc;}
ULO cpuGetInitialPC(void) {return cpu_initial_pc;}
void cpuSetInitialPC(uint32_t pc) {cpu_initial_pc = pc;}
uint32_t cpuGetInitialPC() {return cpu_initial_pc;}
void cpuSetInitialSP(ULO sp) {cpu_initial_sp = sp;}
ULO cpuGetInitialSP(void) {return cpu_initial_sp;}
void cpuSetInitialSP(uint32_t sp) {cpu_initial_sp = sp;}
uint32_t cpuGetInitialSP() {return cpu_initial_sp;}
void cpuSetModelMask(UBY model_mask) {cpu_model_mask = model_mask;}
UBY cpuGetModelMask(void) {return cpu_model_mask;}
void cpuSetModelMask(uint8_t model_mask) {cpu_model_mask = model_mask;}
uint8_t cpuGetModelMask() {return cpu_model_mask;}
ULO cpuGetModelMajor(void) {return cpu_model_major;}
ULO cpuGetModelMinor(void) {return cpu_model_minor;}
uint32_t cpuGetModelMajor() {return cpu_model_major;}
uint32_t cpuGetModelMinor() {return cpu_model_minor;}
static void cpuCalculateModelMask(void)
{
@ -235,7 +238,7 @@ static void cpuCalculateModelMask(void)
}
}
void cpuSetModel(ULO major, ULO minor)
void cpuSetModel(uint32_t major, uint32_t minor)
{
BOOLE makeOpcodeTable = (cpu_model_major != major);
cpu_model_major = major;
@ -245,57 +248,59 @@ void cpuSetModel(ULO major, ULO minor)
if (makeOpcodeTable) cpuMakeOpcodeTableForModel();
}
#if defined(__BIG_ENDIAN__)
void cpuSetDRegWord(ULO regno, UWO val) {*((WOR*)&cpu_regs[0][regno]+1) = val;}
void cpuSetDRegByte(ULO regno, UBY val) {*((UBY*)&cpu_regs[0][regno]+3) = val;}
#if 0
void cpuSetDRegWord(uint32_t regno, uint16_t val) {*((int16_t*)&cpu_regs[0][regno]) = val;}
void cpuSetDRegByte(uint32_t regno, uint8_t val) {*((uint8_t*)&cpu_regs[0][regno]) = val;}
#else
void cpuSetDRegWord(ULO regno, UWO val) {*((WOR*)&cpu_regs[0][regno]) = val;}
void cpuSetDRegByte(ULO regno, UBY val) {*((UBY*)&cpu_regs[0][regno]) = val;}
// MPW -- above assumes little endian.
void cpuSetDRegWord(uint32_t regno, uint16_t val) {cpu_regs[0][regno] &= 0xffff0000; cpu_regs[0][regno] |= val;}
void cpuSetDRegByte(uint32_t regno, uint8_t val) {cpu_regs[0][regno] &= 0xffffff00; cpu_regs[0][regno] |= val;}
#endif
UWO cpuGetRegWord(ULO i, ULO regno) {return (UWO)cpu_regs[i][regno];}
UWO cpuGetDRegWord(ULO regno) {return (UWO)cpu_regs[0][regno];}
UBY cpuGetDRegByte(ULO regno) {return (UBY)cpu_regs[0][regno];}
uint16_t cpuGetRegWord(uint32_t i, uint32_t regno) {return (uint16_t)cpu_regs[i][regno];}
uint16_t cpuGetDRegWord(uint32_t regno) {return (uint16_t)cpu_regs[0][regno];}
uint8_t cpuGetDRegByte(uint32_t regno) {return (uint8_t)cpu_regs[0][regno];}
UWO cpuGetARegWord(ULO regno) {return (UWO)cpu_regs[1][regno];}
UBY cpuGetARegByte(ULO regno) {return (UBY)cpu_regs[1][regno];}
ULO cpuGetDRegWordSignExtLong(ULO regno) {return cpuSignExtWordToLong(cpuGetDRegWord(regno));}
UWO cpuGetDRegByteSignExtWord(ULO regno) {return cpuSignExtByteToWord(cpuGetDRegByte(regno));}
ULO cpuGetDRegByteSignExtLong(ULO regno) {return cpuSignExtByteToLong(cpuGetDRegByte(regno));}
uint32_t cpuGetDRegWordSignExtLong(uint32_t regno) {return cpuSignExtWordToLong(cpuGetDRegWord(regno));}
uint16_t cpuGetDRegByteSignExtWord(uint32_t regno) {return cpuSignExtByteToWord(cpuGetDRegByte(regno));}
uint32_t cpuGetDRegByteSignExtLong(uint32_t regno) {return cpuSignExtByteToLong(cpuGetDRegByte(regno));}
typedef UWO (*cpuGetWordFunc)(void);
typedef ULO (*cpuGetLongFunc)(void);
uint16_t cpuGetARegWord(uint32_t regno) {return (uint16_t)cpu_regs[1][regno];}
uint8_t cpuGetARegByte(uint32_t regno) {return (uint8_t)cpu_regs[1][regno];}
static UWO cpuGetNextWordInternal(void)
typedef uint16_t (*cpuGetWordFunc)(void);
typedef uint32_t (*cpuGetLongFunc)(void);
static uint16_t cpuGetNextWordInternal(void)
{
UWO data = memoryReadWord(cpuGetPC() + 2);
uint16_t data = memoryReadWord(cpuGetPC() + 2);
return data;
}
static ULO cpuGetNextLongInternal(void)
static uint32_t cpuGetNextLongInternal(void)
{
ULO data = memoryReadLong(cpuGetPC() + 2);
uint32_t data = memoryReadLong(cpuGetPC() + 2);
return data;
}
UWO cpuGetNextWord(void)
uint16_t cpuGetNextWord(void)
{
UWO tmp = cpu_prefetch_word;
uint16_t tmp = cpu_prefetch_word;
cpu_prefetch_word = cpuGetNextWordInternal();
cpuSetPC(cpuGetPC() + 2);
return tmp;
}
ULO cpuGetNextWordSignExt(void)
uint32_t cpuGetNextWordSignExt(void)
{
return cpuSignExtWordToLong(cpuGetNextWord());
}
ULO cpuGetNextLong(void)
uint32_t cpuGetNextLong(void)
{
ULO tmp = cpu_prefetch_word << 16;
ULO data = cpuGetNextLongInternal();
cpu_prefetch_word = (UWO) data;
uint32_t tmp = cpu_prefetch_word << 16;
uint32_t data = cpuGetNextLongInternal();
cpu_prefetch_word = (uint16_t) data;
cpuSetPC(cpuGetPC() + 4);
return tmp | (data >> 16);
}
@ -322,7 +327,7 @@ void cpuSkipNextLong(void)
cpuInitializePrefetch();
}
void cpuInitializeFromNewPC(ULO new_pc)
void cpuInitializeFromNewPC(uint32_t new_pc)
{
cpuSetPC(new_pc);
cpuInitializePrefetch();
@ -330,13 +335,11 @@ void cpuInitializeFromNewPC(ULO new_pc)
void cpuSaveState(FILE *F)
{
ULO i, j;
fwrite(&cpu_model_major, sizeof(cpu_model_major), 1, F);
fwrite(&cpu_model_minor, sizeof(cpu_model_minor), 1, F);
for (i = 0; i < 2; i++)
for (uint32_t i = 0; i < 2; i++)
{
for (j = 0; j < 7; j++)
for (uint32_t j = 0; j < 7; j++)
{
fwrite(&cpu_regs[i][j], sizeof(cpu_regs[i][j]), 1, F);
}
@ -358,13 +361,11 @@ void cpuSaveState(FILE *F)
void cpuLoadState(FILE *F)
{
ULO i, j;
fread(&cpu_model_major, sizeof(cpu_model_major), 1, F);
fread(&cpu_model_minor, sizeof(cpu_model_minor), 1, F);
for (i = 0; i < 2; i++)
for (uint32_t i = 0; i < 2; i++)
{
for (j = 0; j < 7; j++)
for (uint32_t j = 0; j < 7; j++)
{
fread(&cpu_regs[i][j], sizeof(cpu_regs[i][j]), 1, F);
}

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_Interrupts.c,v 1.5 2012-08-12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 interrupt handling */
@ -32,7 +31,7 @@ cpuCheckPendingInterruptsFunc cpu_check_pending_interrupts_func;
void cpuCheckPendingInterrupts(void)
{
if (cpuGetRaiseInterrupt()) return;
if (cpu_check_pending_interrupts_func) cpu_check_pending_interrupts_func();
cpu_check_pending_interrupts_func();
}
void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func)
@ -40,9 +39,9 @@ void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func)
cpu_check_pending_interrupts_func = func;
}
ULO cpuActivateSSP(void)
uint32_t cpuActivateSSP(void)
{
ULO currentSP = cpuGetAReg(7);
uint32_t currentSP = cpuGetAReg(7);
// check supervisor bit number (bit 13) within the system byte of the status register
if (!cpuGetFlagSupervisor())
@ -66,7 +65,7 @@ ULO cpuActivateSSP(void)
// Retrns TRUE if the CPU is in the stopped state,
// this allows our scheduling queue to start
// scheduling CPU events again.
BOOLE cpuSetIrqLevel(ULO new_interrupt_level)
BOOLE cpuSetIrqLevel(uint32_t new_interrupt_level)
{
cpuSetRaiseInterrupt(TRUE);
cpuSetRaiseInterruptLevel(new_interrupt_level);
@ -83,10 +82,10 @@ BOOLE cpuSetIrqLevel(ULO new_interrupt_level)
Transfers control to an interrupt routine
============================================================*/
void cpuSetUpInterrupt(ULO new_interrupt_level)
void cpuSetUpInterrupt(uint32_t new_interrupt_level)
{
UWO vector_offset = (UWO) (0x60 + new_interrupt_level*4);
ULO vector_address = memoryReadLong(cpuGetVbr() + vector_offset);
uint16_t vector_offset = (uint16_t) (0x60 + new_interrupt_level*4);
uint32_t vector_address = memoryReadLong(cpuGetVbr() + vector_offset);
cpuActivateSSP(); // Switch to using ssp or msp. Loads a7 and preserves usp if we came from user-mode.
@ -94,7 +93,7 @@ void cpuSetUpInterrupt(ULO new_interrupt_level)
cpuSetSR(cpuGetSR() & 0x38ff); // Clear interrupt level
cpuSetSR(cpuGetSR() | 0x2000); // Set supervisor mode
cpuSetSR(cpuGetSR() | (UWO)(new_interrupt_level << 8)); // Set interrupt level
cpuSetSR(cpuGetSR() | (uint16_t)(new_interrupt_level << 8)); // Set interrupt level
#ifdef CPU_INSTRUCTION_LOGGING
cpuCallInterruptLoggingFunc(new_interrupt_level, vector_address);
@ -104,7 +103,7 @@ void cpuSetUpInterrupt(ULO new_interrupt_level)
{
if (cpuGetFlagMaster())
{ // If the cpu was in master mode, preserve msp, and switch to using ssp (isp) in a7.
ULO oldA7 = cpuGetAReg(7);
uint32_t oldA7 = cpuGetAReg(7);
cpuSetMspDirect(oldA7);
cpuSetAReg(7, cpuGetSspDirect());
cpuFrame1(vector_offset, cpuGetPC()); // Make the throwaway frame on ssp/isp

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_Logging.c,v 1.3 2012-08-12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* CPU 68k logging functions */
@ -49,7 +48,7 @@ void cpuSetExceptionLoggingFunc(cpuExceptionLoggingFunc func)
cpu_exception_logging_func = func;
}
void cpuCallExceptionLoggingFunc(STR *description, ULO original_pc, UWO opcode)
void cpuCallExceptionLoggingFunc(char *description, uint32_t original_pc, uint16_t opcode)
{
if (cpu_exception_logging_func != NULL)
cpu_exception_logging_func(description, original_pc, opcode);
@ -60,7 +59,7 @@ void cpuSetInterruptLoggingFunc(cpuInterruptLoggingFunc func)
cpu_interrupt_logging_func = func;
}
void cpuCallInterruptLoggingFunc(ULO level, ULO vector_address)
void cpuCallInterruptLoggingFunc(uint32_t level, uint32_t vector_address)
{
if (cpu_interrupt_logging_func != NULL)
cpu_interrupt_logging_func(level, vector_address);

View File

@ -1 +1 @@
#include "fmem.h"
#include "fmem.h"

View File

@ -1,7 +1,5 @@
#ifndef CPUMODULE_PROFILE_H
#define CPUMODULE_PROFILE_H
#pragma once
void cpuProfileWrite(void)
{
}
#endif

View File

@ -1,4 +1,3 @@
/* @(#) $Id: CpuModule_StackFrameGen.c,v 1.3 2011-07-18 17:22:55 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 stack frame generation */
@ -27,10 +26,10 @@
#include "CpuModule_Internal.h"
/* Exception stack frame jmptables */
typedef void(*cpuStackFrameGenFunc)(UWO, ULO);
typedef void(*cpuStackFrameGenFunc)(uint16_t, uint32_t);
static cpuStackFrameGenFunc cpu_stack_frame_gen_func[64];
static void cpuSetStackFrameGenFunc(ULO vector_no, cpuStackFrameGenFunc func)
static void cpuSetStackFrameGenFunc(uint32_t vector_no, cpuStackFrameGenFunc func)
{
cpu_stack_frame_gen_func[vector_no] = func;
}
@ -41,7 +40,7 @@ static void cpuSetStackFrameGenFunc(ULO vector_no, cpuStackFrameGenFunc func)
000: All, except bus and address error
========================================================================*/
static void cpuFrameGroup1(UWO vector_offset, ULO pcPtr)
static void cpuFrameGroup1(uint16_t vector_offset, uint32_t pcPtr)
{
// save PC
cpuSetAReg(7, cpuGetAReg(7) - 4);
@ -49,7 +48,7 @@ static void cpuFrameGroup1(UWO vector_offset, ULO pcPtr)
// save SR
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
memoryWriteWord((uint16_t)cpuGetSR(), cpuGetAReg(7));
}
/*========================================================================
@ -61,7 +60,7 @@ static void cpuFrameGroup1(UWO vector_offset, ULO pcPtr)
memory_fault_read is TRUE if the access was a read
========================================================================*/
static void cpuFrameGroup2(UWO vector_offset, ULO pcPtr)
static void cpuFrameGroup2(uint16_t vector_offset, uint32_t pcPtr)
{
// save PC
cpuSetAReg(7, cpuGetAReg(7) - 4);
@ -69,7 +68,7 @@ static void cpuFrameGroup2(UWO vector_offset, ULO pcPtr)
// save SR
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
memoryWriteWord((uint16_t)cpuGetSR(), cpuGetAReg(7));
// fault address, skip ireg
cpuSetAReg(7, cpuGetAReg(7) - 6);
@ -79,7 +78,7 @@ static void cpuFrameGroup2(UWO vector_offset, ULO pcPtr)
memoryWriteLong(memory_fault_read << 4, cpuGetAReg(7));
}
static void cpuFrame4Words(UWO frame_code, UWO vector_offset, ULO pc)
static void cpuFrame4Words(uint16_t frame_code, uint16_t vector_offset, uint32_t pc)
{
// save vector_offset word
cpuSetAReg(7, cpuGetAReg(7) - 2);
@ -91,7 +90,7 @@ static void cpuFrame4Words(UWO frame_code, UWO vector_offset, ULO pc)
// save SR
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
memoryWriteWord((uint16_t)cpuGetSR(), cpuGetAReg(7));
}
@ -111,7 +110,7 @@ static void cpuFrame4Words(UWO frame_code, UWO vector_offset, ULO pc)
030: Same as for 020
========================================================================*/
static void cpuFrame0(UWO vector_offset, ULO pc)
static void cpuFrame0(uint16_t vector_offset, uint32_t pc)
{
cpuFrame4Words(0x0000, vector_offset, pc);
}
@ -131,7 +130,7 @@ static void cpuFrame0(UWO vector_offset, ULO pc)
040: Same as for 020
========================================================================*/
void cpuFrame1(UWO vector_offset, ULO pc)
void cpuFrame1(uint16_t vector_offset, uint32_t pc)
{
cpuFrame4Words(0x1000, vector_offset, pc);
}
@ -147,7 +146,7 @@ void cpuFrame1(UWO vector_offset, ULO pc)
060: Same as for 040
========================================================================*/
static void cpuFrame2(UWO vector_offset, ULO pc)
static void cpuFrame2(uint16_t vector_offset, uint32_t pc)
{
// save inst address
cpuSetAReg(7, cpuGetAReg(7) - 4);
@ -162,7 +161,7 @@ static void cpuFrame2(UWO vector_offset, ULO pc)
========================================================================*/
static void cpuFrame8(UWO vector_offset, ULO pc)
static void cpuFrame8(uint16_t vector_offset, uint32_t pc)
{
cpuSetAReg(7, cpuGetAReg(7) - 50);
cpuFrame4Words(0x8000, vector_offset, pc);
@ -178,14 +177,14 @@ static void cpuFrame8(UWO vector_offset, ULO pc)
Fellow will always generate this frame for bus/address errors
========================================================================*/
static void cpuFrameA(UWO vector_offset, ULO pc)
static void cpuFrameA(uint16_t vector_offset, uint32_t pc)
{
// save vector_offset offset
cpuSetAReg(7, cpuGetAReg(7) - 24);
cpuFrame4Words(0xa000, vector_offset, pc);
}
void cpuStackFrameGenerate(UWO vector_offset, ULO pc)
void cpuStackFrameGenerate(uint16_t vector_offset, uint32_t pc)
{
cpu_stack_frame_gen_func[vector_offset>>2](vector_offset, pc);
}
@ -196,8 +195,7 @@ void cpuStackFrameGenerate(UWO vector_offset, ULO pc)
static void cpuStackFrameInitSetDefaultFunc(cpuStackFrameGenFunc default_func)
{
ULO i;
for (i = 0; i < 64; i++)
for (uint32_t i = 0; i < 64; i++)
cpuSetStackFrameGenFunc(i, default_func);
}

View File

@ -1,14 +1,10 @@
#ifndef DEFS_H
#define DEFS_H
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Maximum values for memory, don't change */
@ -17,27 +13,19 @@ extern "C" {
#define BOGOMEM 0x1c0000
#define KICKMEM 0x080000
/* Fellow types to ensure correct sizes */
typedef uint8_t UBY;
typedef uint16_t UWO;
typedef uint32_t ULO;
typedef uint64_t ULL;
typedef int8_t BYT;
typedef int16_t WOR;
typedef int32_t LON;
typedef int64_t LLO;
typedef int BOOLE;
#define FALSE 0
#define TRUE 1
typedef char STR;
/*
#ifndef X64
#define PTR_TO_INT(i) ((ULO)i)
#define PTR_TO_INT(i) ((uint32_t)i)
#define PTR_TO_INT_MASK_TYPE(i) ((uint32_t)i)
#endif
#ifdef X64
#define PTR_TO_INT(i) ((ULL)i)
#define PTR_TO_INT(i) ((uint64_t)i)
#define PTR_TO_INT_MASK_TYPE(i) ((uint64_t)i)
#endif
*/
@ -49,17 +37,17 @@ typedef char STR;
/* The decode routines have this type */
/*------------------------------------*/
typedef void (*decoderoutinetype)(ULO,ULO);
typedef void (*decoderoutinetype)(uint32_t, uint32_t);
extern UBY configromname[];
extern uint8_t configromname[];
typedef union {
ULO *lptr;
UWO *wptr;
UBY *bptr;
ULO lval;
UWO wval[2];
UBY bval[4];
uint32_t *lptr;
uint16_t *wptr;
uint8_t *bptr;
uint32_t lval;
uint16_t wval[2];
uint8_t bval[4];
} ptunion;
typedef void (*planar2chunkyroutine)(void);
@ -69,13 +57,3 @@ typedef void (*sound_before_emu_routine)(void);
typedef void (*sound_after_emu_routine)(void);
typedef void (*buseventfunc)(void);
#define FELLOWVERSION "WinFellow alpha v0.5.0 build 0 (CVS)"
#define FELLOWLONGVERSION "WinFellow Amiga Emulator alpha v0.5.0 - CVS"
#define FELLOWNUMERICVERSION "0.5.0.0"
#ifdef __cplusplus
}
#endif
#endif

1692
cpu/fmem.c

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +1,50 @@
#ifndef FMEM_H
#define FMEM_H
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// new functions
// MPW
extern void memorySetMemory(uint8_t *memory, uint32_t size);
extern void memorySetGlobalLog(uint32_t globalLog);
extern uint8_t *memoryPointer(uint32_t address);
/* Access for chipset emulation that already have validated addresses */
#define chipmemReadByte(address) (memory_chip[address])
#define chipmemReadWord(address) ((((uint16_t) memory_chip[address]) << 8) | ((uint16_t) memory_chip[address + 1]))
#define chipmemWriteWord(data, address) \
memory_chip[address] = (uint8_t) (data >> 8); \
memory_chip[address + 1] = (uint8_t) data
/* Memory access functions */
extern UBY memoryReadByte(ULO address);
extern UWO memoryReadWord(ULO address);
extern ULO memoryReadLong(ULO address);
extern uint64_t memoryReadLongLong(ULO address);
extern void memoryWriteByte(UBY data, ULO address);
extern void memoryWriteWord(UWO data, ULO address);
extern void memoryWriteLong(ULO data, ULO address);
extern void memoryWriteLongLong(uint64_t data, ULO address);
extern uint8_t memoryReadByte(uint32_t address);
extern uint16_t memoryReadWord(uint32_t address);
extern uint32_t memoryReadLong(uint32_t address);
extern uint64_t memoryReadLongLong(uint32_t address);
extern void memoryWriteByte(uint8_t data, uint32_t address);
extern void memoryWriteWord(uint16_t data, uint32_t address);
extern void memoryWriteLong(uint32_t data, uint32_t address);
extern void memoryWriteLongLong(uint64_t data, uint32_t address);
extern UWO memoryChipReadWord(ULO address);
extern void memoryChipWriteWord(UWO data, ULO address);
extern uint16_t memoryChipReadWord(uint32_t address);
extern void memoryChipWriteWord(uint16_t data, uint32_t address);
#define memoryReadByteFromPointer(address) (address[0])
#define memoryReadWordFromPointer(address) ((address[0] << 8) | address[1])
#define memoryReadLongFromPointer(address) ((address[0] << 24) | (address[1] << 16) | (address[2] << 8) | address[3])
extern void memoryWriteLongToPointer(uint32_t data, uint8_t *address);
/* IO Bank functions */
typedef UWO (*memoryIoReadFunc)(ULO address);
typedef void (*memoryIoWriteFunc)(UWO data, ULO address);
typedef uint16_t (*memoryIoReadFunc)(uint32_t address);
typedef void (*memoryIoWriteFunc)(uint16_t data, uint32_t address);
extern void memorySetIoReadStub(ULO index, memoryIoReadFunc ioreadfunction);
extern void memorySetIoWriteStub(ULO index, memoryIoWriteFunc iowritefunction);
extern void memorySetIoReadStub(uint32_t index, memoryIoReadFunc ioreadfunction);
extern void memorySetIoWriteStub(uint32_t index, memoryIoWriteFunc iowritefunction);
/* For the copper */
extern memoryIoWriteFunc memory_iobank_write[257];
@ -43,23 +52,24 @@ extern memoryIoWriteFunc memory_iobank_write[257];
/* Expansion card functions */
typedef void (*memoryEmemCardInitFunc)(void);
typedef void (*memoryEmemCardMapFunc)(ULO);
typedef void (*memoryEmemCardMapFunc)(uint32_t);
extern void memoryEmemClear(void);
extern void memoryEmemCardAdd(memoryEmemCardInitFunc cardinit,
memoryEmemCardMapFunc cardmap);
extern void memoryEmemSet(ULO index, ULO data);
extern void memoryEmemMirror(ULO emem_offset, UBY *src, ULO size);
extern void memoryEmemSet(uint32_t index, uint32_t data);
extern void memoryEmemMirror(uint32_t emem_offset, uint8_t *src, uint32_t size);
/* Device memory functions. fhfile is using these. */
extern void memoryDmemSetByte(UBY data);
extern void memoryDmemSetWord(UWO data);
extern void memoryDmemSetLong(ULO data);
extern void memoryDmemSetLongNoCounter(ULO data, ULO offset);
extern void memoryDmemSetString(STR *data);
extern void memoryDmemSetCounter(ULO val);
extern ULO memoryDmemGetCounter(void);
extern void memoryDmemSetByte(uint8_t data);
extern void memoryDmemSetWord(uint16_t data);
extern void memoryDmemSetLong(uint32_t data);
extern void memoryDmemSetLongNoCounter(uint32_t data, uint32_t offset);
extern void memoryDmemSetString(const char *data);
extern void memoryDmemSetCounter(uint32_t val);
extern uint32_t memoryDmemGetCounter(void);
extern uint32_t memoryDmemGetCounterWithoutOffset(void);
extern void memoryDmemClear(void);
/* Module management functions */
@ -76,12 +86,12 @@ extern void memoryShutdown(void);
/* Memory bank functions */
typedef UBY (*memoryReadByteFunc)(ULO address);
typedef UWO (*memoryReadWordFunc)(ULO address);
typedef ULO (*memoryReadLongFunc)(ULO address);
typedef void (*memoryWriteByteFunc)(UBY data, ULO address);
typedef void (*memoryWriteWordFunc)(UWO data, ULO address);
typedef void (*memoryWriteLongFunc)(ULO data, ULO address);
typedef uint8_t (*memoryReadByteFunc)(uint32_t address);
typedef uint16_t (*memoryReadWordFunc)(uint32_t address);
typedef uint32_t (*memoryReadLongFunc)(uint32_t address);
typedef void (*memoryWriteByteFunc)(uint8_t data, uint32_t address);
typedef void (*memoryWriteWordFunc)(uint16_t data, uint32_t address);
typedef void (*memoryWriteLongFunc)(uint32_t data, uint32_t address);
extern memoryReadByteFunc memory_bank_readbyte[65536];
extern memoryReadWordFunc memory_bank_readword[65536];
@ -90,8 +100,8 @@ extern memoryWriteByteFunc memory_bank_writebyte[65536];
extern memoryWriteWordFunc memory_bank_writeword[65536];
extern memoryWriteLongFunc memory_bank_writelong[65536];
extern UBY *memory_bank_pointer[65536];
extern UBY *memory_bank_datapointer[65536];
extern uint8_t *memory_bank_pointer[65536];
extern uint8_t *memory_bank_datapointer[65536];
extern void memoryBankSet(memoryReadByteFunc rb,
memoryReadWordFunc rw,
@ -99,39 +109,43 @@ extern void memoryBankSet(memoryReadByteFunc rb,
memoryWriteByteFunc wb,
memoryWriteWordFunc ww,
memoryWriteLongFunc wl,
UBY *basep,
ULO bank,
ULO basebank,
uint8_t *basep,
uint32_t bank,
uint32_t basebank,
BOOLE pointer_can_write);
extern UBY *memoryAddressToPtr(ULO address);
extern void memoryChipMap(BOOLE overlay);
extern uint8_t *memoryAddressToPtr(uint32_t address);
extern void memoryChipMap(bool overlay);
/* Memory configuration properties */
extern BOOLE memorySetChipSize(ULO chipsize);
extern ULO memoryGetChipSize(void);
extern BOOLE memorySetFastSize(ULO fastsize);
extern ULO memoryGetFastSize(void);
extern void memorySetFastAllocatedSize(ULO fastallocatedsize);
extern ULO memoryGetFastAllocatedSize(void);
extern BOOLE memorySetSlowSize(ULO bogosize);
extern ULO memoryGetSlowSize(void);
extern BOOLE memorySetUseAutoconfig(BOOLE useautoconfig);
extern BOOLE memoryGetUseAutoconfig(void);
extern BOOLE memorySetChipSize(uint32_t chipsize);
extern uint32_t memoryGetChipSize(void);
extern BOOLE memorySetFastSize(uint32_t fastsize);
extern uint32_t memoryGetFastSize(void);
extern void memorySetFastAllocatedSize(uint32_t fastallocatedsize);
extern uint32_t memoryGetFastAllocatedSize(void);
extern BOOLE memorySetSlowSize(uint32_t bogosize);
extern uint32_t memoryGetSlowSize(void);
extern bool memorySetUseAutoconfig(bool useautoconfig);
extern bool memoryGetUseAutoconfig(void);
extern BOOLE memorySetAddress32Bit(BOOLE address32bit);
extern BOOLE memoryGetAddress32Bit(void);
extern BOOLE memorySetKickImage(STR *kickimage);
extern STR *memoryGetKickImage(void);
extern void memorySetKey(STR *key);
extern STR *memoryGetKey(void);
extern BOOLE memorySetKickImage(char *kickimage);
extern BOOLE memorySetKickImageExtended(char *kickimageext);
extern char *memoryGetKickImage(void);
extern void memorySetKey(char *key);
extern char *memoryGetKey(void);
extern BOOLE memoryGetKickImageOK(void);
/* Derived from memory configuration */
extern ULO memoryGetKickImageBaseBank(void);
extern ULO memoryGetKickImageVersion(void);
extern ULO memoryInitialPC(void);
extern ULO memoryInitialSP(void);
extern uint32_t memoryGetKickImageBaseBank(void);
extern uint32_t memoryGetKickImageVersion(void);
extern uint32_t memoryInitialPC(void);
extern uint32_t memoryInitialSP(void);
/* Kickstart decryption */
extern int memoryKickLoadAF2(char *filename, FILE *F, uint8_t *memory_kick, const bool);
/* Kickstart load error handling */
@ -148,21 +162,19 @@ extern ULO memoryInitialSP(void);
/* Global variables */
extern UBY memory_chip[];
extern UBY *memory_fast;
extern UBY memory_slow[];
extern UBY memory_kick[];
extern ULO memory_chipsize;
extern UBY memory_emem[];
extern uint8_t memory_chip[];
extern uint8_t *memory_fast;
extern uint8_t memory_slow[];
extern uint8_t memory_kick[];
extern uint32_t memory_chipsize;
extern uint8_t memory_emem[];
extern ULO intenar,intena,intreq;
extern ULO potgor;
extern uint32_t potgor;
extern ULO memory_fault_address;
extern uint32_t memory_fault_address;
extern BOOLE memory_fault_read;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -8,14 +8,14 @@
/*============================================================================*/
BOOLE memory_fault_read = FALSE; /* TRUE - read / FALSE - write */
ULO memory_fault_address = 0;
uint32_t memory_fault_address = 0;
/*==============================================================================
Raises exception 3 when a word or long is accessing an odd address
and the CPU is < 020
==============================================================================*/
static void memoryOddRead(ULO address)
static void memoryOddRead(uint32_t address)
{
if (address & 1)
{
@ -28,7 +28,7 @@ static void memoryOddRead(ULO address)
}
}
static void memoryOddWrite(ULO address)
static void memoryOddWrite(uint32_t address)
{
if (address & 1)
{
@ -75,7 +75,7 @@ uint8_t *memoryPointer(uint32_t address)
// memory read of 0xffffffff not handled correctly
// since the unsigned compare overflows.
UBY memoryReadByte(ULO address)
uint8_t memoryReadByte(uint32_t address)
{
if (MemoryLoggingFunc)
@ -88,7 +88,7 @@ UBY memoryReadByte(ULO address)
return 0;
}
UWO memoryReadWord(ULO address)
uint16_t memoryReadWord(uint32_t address)
{
if (MemoryLoggingFunc)
@ -103,7 +103,7 @@ UWO memoryReadWord(ULO address)
return 0;
}
ULO memoryReadLong(ULO address)
uint32_t memoryReadLong(uint32_t address)
{
if (MemoryLoggingFunc)
@ -121,7 +121,7 @@ ULO memoryReadLong(ULO address)
}
uint64_t memoryReadLongLong(ULO address)
uint64_t memoryReadLongLong(uint32_t address)
{
uint64_t tmp;
@ -132,7 +132,7 @@ uint64_t memoryReadLongLong(ULO address)
return tmp;
}
void memoryWriteByte(UBY data, ULO address)
void memoryWriteByte(uint8_t data, uint32_t address)
{
if (MemoryLoggingFunc)
@ -144,7 +144,7 @@ void memoryWriteByte(UBY data, ULO address)
}
}
void memoryWriteWord(UWO data, ULO address)
void memoryWriteWord(uint16_t data, uint32_t address)
{
if (MemoryLoggingFunc)
@ -159,7 +159,7 @@ void memoryWriteWord(UWO data, ULO address)
}
}
void memoryWriteLong(ULO data, ULO address)
void memoryWriteLong(uint32_t data, uint32_t address)
{
if (MemoryLoggingFunc)
@ -178,7 +178,7 @@ void memoryWriteLong(ULO data, ULO address)
}
void memoryWriteLongLong(uint64_t data, ULO address)
void memoryWriteLongLong(uint64_t data, uint32_t address)
{
if (address & 0x01) memoryOddWrite(address);

View File

@ -1,4 +0,0 @@
set(CXX_SRC mapped_file.cpp)
add_library(CXX_LIB ${CXX_SRC})

View File

@ -1,377 +0,0 @@
#include "mapped_file.h"
#include <memory>
#include <functional>
#include <system_error>
#include "unique_resource.h"
namespace {
class defer {
public:
typedef std::function<void()> FX;
defer() = default;
defer(FX fx) : _fx(fx) {}
defer(const defer &) = delete;
defer(defer &&) = default;
defer & operator=(const defer &) = delete;
defer & operator=(defer &&) = default;
void cancel() { _fx = nullptr; }
~defer() { if (_fx) _fx(); }
private:
FX _fx;
};
void throw_error(int error) {
throw std::system_error(error, std::system_category());
}
void throw_error(int error, const std::string &what) {
throw std::system_error(error, std::system_category(), what);
}
}
#ifdef _WIN32
#include <windows.h>
namespace {
void throw_error() {
throw_error(GetLastError());
}
void throw_error(const std::string &what) {
throw_error(GetLastError(), what);
}
}
void mapped_file_base::close() {
if (is_open()) {
UnmapViewOfFile(_data);
CloseHandle(_map_handle);
CloseHandle(_file_handle);
reset();
}
}
void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset) {
HANDLE fh;
HANDLE mh;
// length of 0 in CreateFileMapping / MapViewOfFile
// means map the entire file.
if (is_open()) {
throw std::runtime_error("mapped_file_base::open - file already open");
}
fh = CreateFile(p.c_str(),
flags == readonly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
flags == readonly ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (fh == INVALID_HANDLE_VALUE) {
throw_error();
}
auto fh_close = make_unique_resource(fh, CloseHandle);
if (length == -1) {
LARGE_INTEGER file_size;
GetFileSizeEx(fh, &file_size);
length = (size_t)file_size.QuadPart;
}
if (length == 0) return;
DWORD protect = 0;
DWORD access = 0;
switch (flags) {
case readonly:
protect = PAGE_READONLY;
access = FILE_MAP_READ;
break;
case readwrite:
protect = PAGE_READWRITE;
access = FILE_MAP_WRITE;
break;
case priv:
protect = PAGE_WRITECOPY;
access = FILE_MAP_WRITE;
break;
}
mh = CreateFileMapping(fh, nullptr, protect, 0, 0, 0);
if (mh == INVALID_HANDLE_VALUE) {
throw_error();
}
auto mh_close = make_unique_resource(mh, CloseHandle);
_data = MapViewOfFileEx(mh,
access,
(DWORD)(offset >> 32),
(DWORD)offset,
length,
nullptr);
if (!_data) {
throw_error();
}
_file_handle = fh_close.release();
_map_handle = mh_close.release();
_size = length;
_flags = flags;
}
void mapped_file_base::create(const path_type& p, size_t length) {
const size_t offset = 0;
HANDLE fh;
HANDLE mh;
LARGE_INTEGER file_size;
const DWORD protect = PAGE_READWRITE;
const DWORD access = FILE_MAP_WRITE;
if (is_open()) {
throw std::runtime_error("mapped_file_base::create - file already open");
}
fh = CreateFile(p.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (fh == INVALID_HANDLE_VALUE) {
throw_error();
}
auto fh_close = make_unique_resource(fh, CloseHandle);
file_size.QuadPart = length;
if (!SetFilePointerEx(fh, file_size, nullptr, FILE_BEGIN)) throw_error();
if (!SetEndOfFile(fh)) throw_error();
mh = CreateFileMapping(fh, nullptr, protect, 0, 0, 0);
if (mh == INVALID_HANDLE_VALUE) {
throw_error();
}
auto mh_close = make_unique_resource(mh, CloseHandle);
_data = MapViewOfFileEx(mh,
access,
(DWORD)(offset >> 32),
(DWORD)offset,
length,
nullptr);
if (!_data) {
throw_error();
}
_file_handle = fh_close.release();
_map_handle = mh_close.release();
_size = length;
_flags = readwrite;
}
#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <cerrno>
namespace {
void throw_error() {
throw_error(errno);
}
void throw_error(const std::string &what) {
throw_error(errno, what);
}
}
void mapped_file_base::close() {
if (is_open()) {
::munmap(_data, _size);
::close(_fd);
reset();
}
}
void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset) {
int fd;
int oflags = 0;
if (is_open()) {
throw std::runtime_error("mapped_file_base::open - file already open");
}
switch (flags) {
case readonly:
oflags = O_RDONLY;
break;
default:
oflags = O_RDWR;
break;
}
fd = ::open(p.c_str(), oflags);
if (fd < 0) {
throw_error(errno);
}
//defer([fd](){::close(fd); });
auto close_fd = make_unique_resource(fd, ::close);
if (length == -1) {
struct stat st;
if (::fstat(fd, &st) < 0) {
throw_error(errno);
}
length = st.st_size;
}
if (length == 0) return;
_data = ::mmap(0, length,
flags == readonly ? PROT_READ : PROT_READ | PROT_WRITE,
flags == priv ? MAP_PRIVATE : MAP_SHARED,
fd, offset);
if (_data == MAP_FAILED) {
_data = nullptr;
throw_error(errno);
}
_fd = close_fd.release();
_size = length;
_flags = flags;
}
void mapped_file_base::create(const path_type& p, size_t length) {
int fd;
const size_t offset = 0;
if (is_open()) {
throw std::runtime_error("mapped_file_base::create - file already open");
}
fd = ::open(p.c_str(), O_RDWR | O_CREAT | O_TRUNC);
if (fd < 0) {
throw_error(errno);
}
//defer([fd](){::close(fd); });
auto close_fd = make_unique_resource(fd, ::close);
if (::ftruncate(fd, length) < 0) {
throw_error(errno);
}
_data = ::mmap(0, length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd, offset);
if (_data == MAP_FAILED) {
_data = nullptr;
throw_error(errno);
}
_fd = close_fd.release();
_size = length;
_flags = readwrite;
}
#endif
void mapped_file_base::reset() {
_data = nullptr;
_size = 0;
_flags = readonly;
#ifdef _WIN32
_file_handle = nullptr;
_map_handle = nullptr;
#else
_fd = -1;
#endif
}
void mapped_file_base::swap(mapped_file_base &rhs)
{
if (std::addressof(rhs) != this) {
std::swap(_data, rhs._data);
std::swap(_size, rhs._size);
std::swap(_flags, rhs._flags);
#ifdef _WIN32
std::swap(_file_handle, rhs._file_handle);
std::swap(_map_handle, rhs._map_handle);
#else
std::swap(_fd, rhs._fd);
#endif
}
}
mapped_file::mapped_file(mapped_file &&rhs) : mapped_file() {
swap(rhs);
//rhs.reset();
}
mapped_file& mapped_file::operator=(mapped_file &&rhs) {
if (std::addressof(rhs) == this) return *this;
swap(rhs);
rhs.close();
//rhs.reset();
return *this;
}

View File

@ -1,146 +0,0 @@
#ifndef __mapped_file_h__
#define __mapped_file_h__
#ifdef HAVE_TSFS
#include <filesystem>
#else
#include <string>
#endif
#include <cstddef>
class mapped_file_base {
public:
#ifdef HAVE_TSFS
typedef std::filesystem::path path_type ;
#else
typedef std::string path_type ;
#endif
enum mapmode { readonly, readwrite, priv };
void close();
bool is_open() const {
return _data != nullptr;
}
size_t size() const {
return _size;
}
operator bool() const { return is_open(); }
bool operator !() const { return !is_open(); }
~mapped_file_base() { close(); }
protected:
void swap(mapped_file_base &rhs);
void open(const path_type& p, mapmode flags, size_t length, size_t offset);
void create(const path_type &p, size_t new_size); // always creates readwrite.
void reset();
size_t _size = 0;
void *_data = nullptr;
mapmode _flags = readonly;
#ifdef _WIN32
void *_file_handle = nullptr;
void *_map_handle = nullptr;
#else
int _fd = -1;
#endif
};
class mapped_file : public mapped_file_base {
typedef mapped_file_base base;
public:
typedef unsigned char value_type;
typedef value_type *iterator;
typedef const value_type *const_iterator;
typedef value_type &reference ;
typedef const value_type &const_reference;
mapped_file() = default;
mapped_file(const path_type& p, mapmode flags = readonly, size_t length = -1, size_t offset = 0) {
open(p, flags, length, offset);
}
mapped_file(mapped_file &&);
mapped_file(const mapped_file &) = delete;
mapped_file &operator=(mapped_file &&);
mapped_file &operator=(const mapped_file &) = delete;
void open(const path_type& p, mapmode flags, size_t length = -1, size_t offset = 0) {
base::open(p, flags, length, offset);
}
const value_type *data() const {
return (const value_type *)_data;
}
value_type *data() {
return (value_type *)_data;
//return _flags == readonly ? (value_type *)nullptr : (value_type *)_data;
}
const_iterator cbegin() const {
return data();
}
const_iterator cend() const {
return data() + size();
}
const_iterator begin() const {
return cbegin();
}
const_iterator end() const {
return cend();
}
iterator begin() {
return (iterator)_data;
//return _flags == readonly ? (iterator)nullptr : (iterator)_data;
}
iterator end() {
return (iterator)_data + size();
//return _flags == readonly ? (iterator)nullptr : (iterator)_data + size();
}
mapmode flags() const {
return _flags;
}
void swap(mapped_file &rhs) {
base::swap(rhs);
}
};
namespace std {
template<class T>
void swap(mapped_file &a, mapped_file &b) {
a.swap(b);
}
}
#endif

View File

@ -1,95 +0,0 @@
#ifndef __unique_resource_h__
#define __unique_resource_h__
#include <utility>
template <class T, class D>
class unique_resource {
public:
typedef T element_type;
typedef D deleter_type;
unique_resource() = default;
unique_resource(const unique_resource &) = delete;
unique_resource(unique_resource &&rhs) {
swap(rhs);
}
unique_resource(T t, D d): _pair(t,d), _active(true)
{}
~unique_resource() {
reset();
}
unique_resource &operator=(const unique_resource &) = delete;
unique_resource &operator=(unique_resource &&rhs) {
if (this != std::addressof(rhs)) {
reset();
swap(rhs);
}
return *this;
}
void swap(unique_resource & rhs) {
if (this != std::addressof(rhs)) {
std::swap(_active, rhs._active);
std::swap(_pair, rhs._pair);
}
}
void reset(T t) {
reset();
_active = true;
_pair.first = t;
}
void reset(T t, D d) {
reset();
_active = true;
_pair = std::make_pair(t, d);
}
void reset() {
if (_active) {
(*_pair.second)(_pair.first);
_active = false;
}
}
T release() {
_active = false;
return _pair.first;;
}
T get() {
return _pair.first;
}
operator bool() const {
return _active;
}
D& get_deleter() {
return _pair.second;
}
const D& get_deleter() const {
return _pair.second;
}
private:
std::pair<T, D> _pair;
bool _active = false;
};
#define MAKE_UNIQUE_RESOURCE(T, D) \
unique_resource<decltype(T), decltype(D) *>(T, D)
template<class T, class D>
unique_resource<T, D> make_unique_resource(T t, D d) {
return unique_resource<T, D>(t, d);
}
#endif

View File

@ -1,119 +0,0 @@
#ifndef __mpw_endian_h__
#define __mpw_endian_h__
#include "config.h"
#include <stdint.h>
#if defined(HAVE_ENDIAN_H)
#include <endian.h>
#elif defined(HAVE_SYS_ENDIAN_H)
#include <sys/endian.h>
#elif defined(HAVE_MACHINE_ENDIAN_H)
#include <machine/endian.h>
#else
/* aix doesn't have an endian, but gcc #defines _BIG_ENDIAN=1 and __BIG_ENDIAN__=1 */
#error missing endian.h
#endif
#ifdef __APPLE__
#define bswap16 __builtin_bswap16
#define bswap32 __builtin_bswap32
#define bswap64 __builtin_bswap64
#if BYTE_ORDER == LITTLE_ENDIAN
#define htobe16(x) bswap16((x))
#define htobe32(x) bswap32((x))
#define htobe64(x) bswap64((x))
#define htole16(x) ((uint16_t)(x))
#define htole32(x) ((uint32_t)(x))
#define htole64(x) ((uint64_t)(x))
#define be16toh(x) bswap16((x))
#define be32toh(x) bswap32((x))
#define be64toh(x) bswap64((x))
#define le16toh(x) ((uint16_t)(x))
#define le32toh(x) ((uint32_t)(x))
#define le64toh(x) ((uint64_t)(x))
#else /* BYTE_ORDER != LITTLE_ENDIAN */
#define htobe16(x) ((uint16_t)(x))
#define htobe32(x) ((uint32_t)(x))
#define htobe64(x) ((uint64_t)(x))
#define htole16(x) bswap16((x))
#define htole32(x) bswap32((x))
#define htole64(x) bswap64((x))
#define be16toh(x) ((uint16_t)(x))
#define be32toh(x) ((uint32_t)(x))
#define be64toh(x) ((uint64_t)(x))
#define le16toh(x) bswap16((x))
#define le32toh(x) bswap32((x))
#define le64toh(x) bswap64((x))
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#endif
#ifdef _WIN32
#include <stdlib.h>
#define bswap16 _byteswap_ushort
#define bswap32 _byteswap_ulong
#define bswap64 _byteswap_uint64
#if BYTE_ORDER == LITTLE_ENDIAN
#define htobe16(x) bswap16((x))
#define htobe32(x) bswap32((x))
#define htobe64(x) bswap64((x))
#define htole16(x) ((uint16_t)(x))
#define htole32(x) ((uint32_t)(x))
#define htole64(x) ((uint64_t)(x))
#define be16toh(x) bswap16((x))
#define be32toh(x) bswap32((x))
#define be64toh(x) bswap64((x))
#define le16toh(x) ((uint16_t)(x))
#define le32toh(x) ((uint32_t)(x))
#define le64toh(x) ((uint64_t)(x))
#else /* BYTE_ORDER != LITTLE_ENDIAN */
#define htobe16(x) ((uint16_t)(x))
#define htobe32(x) ((uint32_t)(x))
#define htobe64(x) ((uint64_t)(x))
#define htole16(x) bswap16((x))
#define htole32(x) bswap32((x))
#define htole64(x) bswap64((x))
#define be16toh(x) ((uint16_t)(x))
#define be32toh(x) ((uint32_t)(x))
#define be64toh(x) ((uint64_t)(x))
#define le16toh(x) bswap16((x))
#define le32toh(x) bswap32((x))
#define le64toh(x) bswap64((x))
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#endif
#ifdef __cplusplus
// https://github.com/HowardHinnant/hash_append/blob/master/endian.h
enum class endian
{
native = LITTLE_ENDIAN,
little = LITTLE_ENDIAN,
big = BIG_ENDIAN
};
static_assert(endian::native == endian::little ||
endian::native == endian::big,
"endian::native shall be one of endian::little or endian::big");
static_assert(endian::big != endian::little,
"endian::big and endian::little shall have different values");
#endif
#endif

1
libsane Submodule

@ -0,0 +1 @@
Subproject commit 8a47aacd7d8a19566701ae60dd03ff3c6e6b3634

View File

@ -1,6 +1,3 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(MACOS_SRC traps.c sysequ.c errors.cpp)
add_library(MACOS_LIB ${MACOS_SRC})
add_library(MACOS_LIB ${MACOS_SRC})

View File

@ -537,7 +537,7 @@ const char *ErrorName(int16_t error)
case -339: return "Error occurred during _NewPtr";
case -338: return "Selector out of bounds";
case -337: return "Slot out of bounds or does not exist";
case -336: return "The physical block size of an sBlock was zero";
case -336: return "The physical block size of an sBlock was zero";
case -335: return "The sPointer is nil; no list is specified";
case -334: return "The CPU field of the code to be executed by sExec was wrong";
case -333: return "The revision code to be executed by sExec was wrong";
@ -891,11 +891,6 @@ namespace MacOS {
case dupFNErr: return EEXIST;
case fBsyErr: return EBUSY;
case dskFulErr: return ENOSPC;
case paramErr: return EINVAL;
case posErr: return EINVAL;
case memFullErr: return ENOMEM;
case mFulErr: return ENOMEM;
case tmfoErr: return ENFILE;
default: return -1;
}
@ -917,27 +912,6 @@ namespace MacOS {
return macos_error_from_errno(errno);
}
macos_error macos_error_from_errno(const std::error_code &ec) {
if (!ec) return noErr;
// generic_category is a posix errno.
// system_category is the native error (eg posix errno or windows error)
// but will default_error_condition() to a generic_category, if possible.
if (ec.category() == std::generic_category())
return macos_error_from_errno(ec.value());
if (ec.category() == macos_system_category()) return (macos_error)ec.value();
std::error_condition econd = ec.default_error_condition();
if (econd.category() == std::generic_category())
return macos_error_from_errno(econd.value());
return ioErr;
}
macos_error macos_error_from_errno(int error)
{
switch(error)
@ -946,25 +920,20 @@ namespace MacOS {
case EBADF: return rfNumErr;
case EIO: return ioErr;
case EACCES: return permErr;
case EPERM: return permErr;
case ENOENT: return fnfErr;
case ENOTDIR: return dirNFErr;
case EISDIR: return notAFileErr;
case ENOTSUP: return extFSErr;
case EROFS: return wPrErr;
case EINVAL: return paramErr;
case EEXIST: return dupFNErr;
case EBUSY: return fBsyErr;
case ENOTEMPTY: return fBsyErr;
#ifdef EDQUOT
case EDQUOT: return dskFulErr;
#endif
case ENOSPC: return dskFulErr;
case ENOMEM: return mFulErr;
case ENFILE: return tmfoErr;
case ENOTEMPTY: return fBsyErr;
default:

View File

@ -107,7 +107,7 @@ enum macos_error {
envVersTooBig = -5502, /*Version bigger than call can handle*/
fontDecError = -64, /*error during font declaration*/
fontNotDeclared = -65, /*font not declared*/
fontSubErr = -66, /*font substitution occured*/
fontSubErr = -66, /*font substitution occurred*/
fontNotOutlineErr = -32615, /*bitmap font passed to routine that does outlines only*/
firstDskErr = -84, /*I/O System Errors*/
lastDskErr = -64, /*I/O System Errors*/
@ -196,7 +196,7 @@ enum macos_error {
rgnTooBigErr = -500,
updPixMemErr = -125, /*insufficient memory to update a pixmap*/
pictInfoVersionErr = -11000, /* wrong version of the PictInfo structure */
pictInfoIDErr = -11001, /* the internal consistancy check for the PictInfoID is wrong */
pictInfoIDErr = -11001, /* the internal consistency check for the PictInfoID is wrong */
pictInfoVerbErr = -11002, /* the passed verb was invalid */
cantLoadPickMethodErr = -11003, /* unable to load the custom pick proc */
colorsRequestedErr = -11004, /* the number of colors requested was illegal */
@ -249,7 +249,7 @@ enum macos_error {
smEmptySlot = -300, /*No card in slot*/
smCRCFail = -301, /*CRC check failed for declaration data*/
smFormatErr = -302, /*FHeader Format is not Apple's*/
smRevisionErr = -303, /*Wrong revison level*/
smRevisionErr = -303, /*Wrong revision level*/
smNoDir = -304, /*Directory offset is Nil */
smDisabledSlot = -305, /*This slot is disabled (-305 use to be smLWTstBad)*/
smNosInfoArray = -306, /*No sInfoArray. Memory Mgr error.*/
@ -258,14 +258,14 @@ enum macos_error {
smResrvErr = -307, /*Fatal reserved error. Resreved field <> 0.*/
smUnExBusErr = -308, /*Unexpected BusError*/
smBLFieldBad = -309, /*ByteLanes field was bad.*/
smFHBlockRdErr = -310, /*Error occured during _sGetFHeader.*/
smFHBlkDispErr = -311, /*Error occured during _sDisposePtr (Dispose of FHeader block).*/
smFHBlockRdErr = -310, /*Error occurred during _sGetFHeader.*/
smFHBlkDispErr = -311, /*Error occurred during _sDisposePtr (Dispose of FHeader block).*/
smDisposePErr = -312, /*_DisposePointer error*/
smNoBoardSRsrc = -313, /*No Board sResource.*/
smGetPRErr = -314, /*Error occured during _sGetPRAMRec (See SIMStatus).*/
smGetPRErr = -314, /*Error occurred during _sGetPRAMRec (See SIMStatus).*/
smNoBoardId = -315, /*No Board Id.*/
smInitStatVErr = -316, /*The InitStatusV field was negative after primary or secondary init.*/
smInitTblVErr = -317, /*An error occured while trying to initialize the Slot Resource Table.*/
smInitTblVErr = -317, /*An error occurred while trying to initialize the Slot Resource Table.*/
smNoJmpTbl = -318, /*SDM jump table could not be created.*/
smBadBoardId = -319, /*BoardId was wrong; re-init the PRAM record.*/
smBusErrTO = -320, /*BusError time out.*/
@ -285,20 +285,20 @@ but a special error is needed to patch secondary inits.*/
smCPUErr = -334, /*Code revision is wrong*/
smsPointerNil = -335, /*LPointer is nil From sOffsetData. If this error occurs; check sInfo rec for more information.*/
smNilsBlockErr = -336, /*Nil sBlock error (Dont allocate and try to use a nil sBlock)*/
smNilsBlockErr = -336, /*Nil sBlock error (Don't allocate and try to use a nil sBlock)*/
smSlotOOBErr = -337, /*Slot out of bounds error*/
smSelOOBErr = -338, /*Selector out of bounds error*/
smNewPErr = -339, /*_NewPtr error*/
smBlkMoveErr = -340, /*_BlockMove error*/
smCkStatusErr = -341, /*Status of slot = fail.*/
smGetDrvrNamErr = -342, /*Error occured during _sGetDrvrName.*/
smDisDrvrNamErr = -343, /*Error occured during _sDisDrvrName.*/
smGetDrvrNamErr = -342, /*Error occurred during _sGetDrvrName.*/
smDisDrvrNamErr = -343, /*Error occurred during _sDisDrvrName.*/
smNoMoresRsrcs = -344, /*No more sResources*/
smsGetDrvrErr = -345, /*Error occurred during _sGetDriver.*/
smBadsPtrErr = -346, /*Bad pointer was passed to sCalcsPointer*/
smByteLanesErr = -347, /*NumByteLanes was determined to be zero.*/
smOffsetErr = -348, /*Offset was too big (temporary error*/
smNoGoodOpens = -349, /*No opens were successfull in the loop.*/
smNoGoodOpens = -349, /*No opens were successful in the loop.*/
smSRTOvrFlErr = -350, /*SRT over flow.*/
smRecNotFnd = -351, /*Record not found in the SRT.*/
editionMgrInitErr = -450, /*edition manager not inited by this app*/
@ -333,7 +333,7 @@ but a special error is needed to patch secondary inits.*/
interruptsMaskedErr = -624, /*don't call with interrupts masked*/
cannotDeferErr = -625, /*unable to defer additional functions*/
ddpSktErr = -91, /*error in soket number*/
ddpSktErr = -91, /*error in socket number*/
ddpLenErr = -92, /*data length too big*/
noBridgeErr = -93, /*no network bridge for non-local send*/
lapProtErr = -94, /*error in attaching/detaching protocol*/
@ -453,7 +453,7 @@ but a special error is needed to patch secondary inits.*/
noDefaultUserErr = -922, /* user hasn't typed in owners name in Network Setup Control Pannel */
notLoggedInErr = -923, /* The default userRefNum does not yet exist */
noUserRefErr = -924, /* unable to create a new userRefNum */
networkErr = -925, /* An error has occured in the network, not too likely */
networkErr = -925, /* An error has occurred in the network, not too likely */
noInformErr = -926, /* PPCStart failed because destination did not have inform pending */
authFailErr = -927, /* unable to authenticate user at destination */
noUserRecErr = -928, /* Invalid user reference number */
@ -565,8 +565,6 @@ namespace MacOS {
macos_error macos_error_from_errno();
macos_error macos_error_from_errno(int error);
macos_error macos_error_from_errno(const std::error_code &ec);
// c++11 error stuff
const std::error_category& macos_system_category();

View File

@ -60,7 +60,7 @@ enum {
SMGlobals = 0x0CC4, /* (long) pointer to Sound Manager Globals*/
TheGDevice = 0x0CC8, /*[GLOBAL VAR] (long) the current graphics device*/
CQDGlobals = 0x0CCC, /* (long) quickDraw global extensions*/
ADBBase = 0x0CF8, /*[GLOBAL VAR] (long) pointer to Front Desk Buss Variables*/
ADBBase = 0x0CF8, /*[GLOBAL VAR] (long) pointer to Front Desk Bus Variables*/
WarmStart = 0x0CFC, /*[GLOBAL VAR] (long) flag to indicate it is a warm start*/
TimeDBRA = 0x0D00, /*[GLOBAL VAR] (word) number of iterations of DBRA per millisecond*/
TimeSCCDB = 0x0D02, /*[GLOBAL VAR] (word) number of iter's of SCC access & DBRA.*/

View File

@ -3,45 +3,29 @@
#include "errors.h"
#include <utility>
#include <type_traits>
namespace MacOS {
template<class T>
class tool_return;
template<class T>
struct tool_return_type { typedef tool_return<T> type; };
template<class T>
struct tool_return_type<tool_return<T>> { typedef tool_return<T> type; };
template<>
struct tool_return_type<macos_error> { typedef tool_return<void> type; };
namespace internal {
class tool_return_base
{
protected:
macos_error _error = noErr;
macos_error _error;
constexpr tool_return_base() = default;
tool_return_base() : _error(static_cast<macos_error>(0))
{}
constexpr tool_return_base(macos_error error) : _error(error)
tool_return_base(macos_error error) : _error(error)
{}
public:
constexpr macos_error error() const { return _error; }
macos_error error() const
{
return _error;
}
constexpr explicit operator bool() const { return !_error; }
template<class... Args>
void throw_macos_error(Args&&... args) const
@ -51,62 +35,13 @@ namespace MacOS {
}
};
class void_tool_return : public tool_return_base {
public:
typedef void value_type;
void_tool_return() = default;
void_tool_return(macos_error error) : tool_return_base(error)
{}
void_tool_return &operator=(macos_error error)
{
_error = error;
return *this;
}
template<class F, typename RT = typename std::result_of<F(void_tool_return)>::type>
void then(F &&f, typename std::enable_if<std::is_void<RT>::value>::type* = 0) {
f(std::move(*this));
}
template<class F, typename RT = typename std::result_of<F(void_tool_return)>::type>
RT then(F &&f, typename std::enable_if<!std::is_void<RT>::value>::type* = 0) {
return f(std::move(*this));
}
template<class F, typename RT = typename std::result_of<F()>::type>
typename tool_return_type<RT>::type
map(F &&f, typename std::enable_if<std::is_void<RT>::value>::type* = 0) {
if (_error) return _error;
f();
//return tool_return<void>();
return noErr;
}
template<class F, typename RT = typename std::result_of<F()>::type>
typename tool_return_type<RT>::type
map(F &&f, typename std::enable_if<!std::is_void<RT>::value>::type* = 0) {
if (_error) return _error;
return f();
}
};
} // namespace
template<class T>
class tool_return : public internal::tool_return_base
{
private:
T _value = T();
T _value;
tool_return() = delete;
@ -117,34 +52,20 @@ namespace MacOS {
public:
typedef T value_type;
tool_return(const T &value) : _value(value)
tool_return(T value) : _value(value)
{}
tool_return(T &&value) : _value(std::forward<T>(value))
{}
tool_return(macos_error error) : tool_return_base(error)
{}
tool_return &operator=(const T &value)
tool_return &operator=(T value)
{
_value = value;
_error = 0;
return *this;
}
tool_return &operator=(T &&value)
{
_value = std::forward<T>(value);
_error = 0;
return *this;
}
tool_return &operator=(macos_error error)
{
_value = T();
@ -165,29 +86,18 @@ namespace MacOS {
}
T value() const &
T value() const
{
return _value;
}
T value() && {
return std::move(_value);
}
template<class U>
T value_or(U&& u) const &
T value_or(U&& u) const
{
if (_error) return std::forward<U>(u);
if (_error) return u;
return _value;
}
template<class U>
T &&value_or(U&& u) &&
{
if (_error) return std::forward<U>(u);
return std::move(_value);
}
template<class... Args>
T value_or_throw(Args&&... args) const
{
@ -196,51 +106,32 @@ namespace MacOS {
return _value;
}
template<class F, typename RT = typename std::result_of<F(tool_return)>::type>
void then(F &&f, typename std::enable_if<std::is_void<RT>::value>::type* = 0) {
f(std::move(*this));
}
template<class F, typename RT = typename std::result_of<F(tool_return)>::type>
RT then(F &&f, typename std::enable_if<!std::is_void<RT>::value>::type* = 0) {
return f(std::move(*this));
}
template<class F, typename RT = typename std::result_of<F(value_type)>::type>
typename tool_return_type<RT>::type
map(F &&f, typename std::enable_if<std::is_void<RT>::value>::type* = 0) {
if (_error) return _error;
f(std::move(_value));
//return tool_return<void>();
return noErr;
}
template<class F, typename RT = typename std::result_of<F(value_type)>::type>
typename tool_return_type<RT>::type
map(F &&f, typename std::enable_if<!std::is_void<RT>::value>::type* = 0) {
if (_error) return _error;
return f(std::move(_value));
}
template<class TT=T>
TT value_or_error(typename std::enable_if<std::is_integral<TT>::value>::type * = 0) const {
return _error ? _error : _value;
}
};
template<>
class tool_return<void> : public internal::void_tool_return {
public: using void_tool_return::void_tool_return;
class tool_return<void> : public internal::tool_return_base
{
public:
tool_return()
{}
tool_return(macos_error error) : tool_return_base(error)
{}
tool_return &operator=(macos_error error)
{
_error = error;
return *this;
}
};
template<>
class tool_return<macos_error> : public internal::void_tool_return {
public: using void_tool_return::void_tool_return;
};
} // namespace
#endif

View File

@ -1047,7 +1047,7 @@ enum {
};
enum {
_ALMDispatch = 0xAAA4 /* Apple Location Manger*/
_ALMDispatch = 0xAAA4 /* Apple Location Manager*/
};
enum {

View File

@ -1,5 +1,3 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(MPLITE_SRC mplite.c)
add_library(MPLITE_LIB ${MPLITE_SRC})

View File

@ -73,7 +73,7 @@
* include stdint.h. The hope is that one or the other can be
* used with no real difference.
*
* 5) In the current verison, if your platform can't represent
* 5) In the current version, if your platform can't represent
* int32_t, int16_t and int8_t, it just dumps out with a compiler
* error.
*

View File

@ -1,45 +1,22 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
set(MPW_SRC mpw.cpp mpw_io.cpp mpw_close.cpp mpw_access.cpp mpw_ioctl.cpp mpw_errno.cpp
environment.cpp)
# add_custom_command(
# OUTPUT environ.cpp
# COMMAND ragel -p -G2 -o environ.cpp "${CMAKE_CURRENT_SOURCE_DIR}/environ.rl"
# MAIN_DEPENDENCY environ.rl
# )
add_custom_command(
OUTPUT environment.cpp
COMMAND ragel -p -G2 -o environment.cpp "${CMAKE_CURRENT_SOURCE_DIR}/environment.rl"
COMMAND "${RAGEL}" -p -G2 -o environment.cpp "${CMAKE_CURRENT_SOURCE_DIR}/environment.rl"
MAIN_DEPENDENCY environment.rl
)
# add_custom_command(
# OUTPUT epv.cpp
# COMMAND ragel -p -G2 -o epv.cpp "${CMAKE_CURRENT_SOURCE_DIR}/epv.rl"
# MAIN_DEPENDENCY epv.rl
# )
# add_custom_command(
# OUTPUT ep.cpp
# COMMAND ragel -p -G2 -o ep.cpp "${CMAKE_CURRENT_SOURCE_DIR}/ep.rl"
# MAIN_DEPENDENCY ep.rl
# )
if(NOT MSVC)
set_source_files_properties(
environment.cpp # environ.cpp ep.cpp epv.cpp
PROPERTIES
COMPILE_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-unused-variable"
)
endif()
add_library(MPW_LIB ${MPW_SRC})
target_link_libraries(MPW_LIB MACOS_LIB NATIVE_LIB)
add_library(MPW_LIB ${MPW_SRC})

View File

@ -27,20 +27,16 @@
#include <string>
#include <unordered_map>
#include <cstdio>
#include <cstring>
#include <vector>
#include <sys/types.h>
#include <limits.h>
#include "config.h"
#ifndef _WIN32
extern char **environ;
#endif
namespace _env_rl {
#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#define _GETDELIM_GROWBY 128 /* amount to grow line buffer by */
#define _GETDELIM_MINLEN 4 /* minimum line buffer size */
@ -109,7 +105,7 @@ namespace _env_rl {
ssize_t getline(char ** lineptr, size_t * n, FILE * stream) {
#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
return getdelim(lineptr, n, '\n', stream);
#else
return ::getline(lineptr, n, stream);

View File

@ -33,7 +33,6 @@
#include <cstring>
#include <deque>
#include <unordered_map>
#include <algorithm>
#include <cstdint>
#include <cstdio>
@ -41,7 +40,9 @@
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/stat.h>
#include <pwd.h>
#include <cpu/defs.h>
#include <cpu/fmem.h>
@ -53,17 +54,8 @@
#include <macos/sysequ.h>
#include <native/file.h>
#include <libgen.h>
#include <filesystem>
namespace fs = std::experimental::filesystem;
#ifndef _WIN32
extern char **environ;
#endif
namespace MPW {
@ -82,7 +74,108 @@ namespace MPW
bool Trace = false;
const std::string RootDir();
static bool isdir(const std::string &path)
{
struct stat st;
if (stat(path.c_str(), &st) < 0) return false;
return S_ISDIR(st.st_mode);
}
std::string RootDirPathForFile(const std::string &file)
{
std::string dir(RootDir());
if (dir.length() && dir.back() != '/') dir.push_back('/');
dir.append(file);
return dir;
}
const std::string RootDir()
{
static bool initialized = false;
static std::string path;
static const std::string paths[] = {
"/usr/local/share/mpw",
"/usr/share/mpw",
};
char *cp;
struct passwd *pw;
if (initialized) return path;
initialized = true;
// check $MPW, $HOME/mpw, /usr/local/share/mpw/, /usr/share/mpw
// for a directory.
cp = getenv("MPW");
if (cp && *cp)
{
std::string s(cp);
if (isdir(s))
{
path = std::move(s);
return path;
}
}
// home/mpw
pw = getpwuid(getuid());
if (pw && pw->pw_dir && pw->pw_dir[0])
{
std::string s(pw->pw_dir);
if (s.back() != '/') s.push_back('/');
s.append("mpw");
if (isdir(s))
{
path = std::move(s);
return path;
}
}
#if 0
// thread-safe
{
int size;
size = sysconf(_SC_GETPW_R_SIZE_MAX);
if (size >= 0)
{
struct passwd pwd, *result = nullptr;
char *buffer = alloca(size);
if (getpwuid_r(getuid(), &pwd, buffer, size, &result) == 0 && result)
{
std::string s(pwd.pw_dir);
if (s.back() != '/') s.push_back('/');
s.append("mpw");
if (isdir(s))
{
path = std::move(s);
return path;
}
}
}
}
#endif
for (auto &iter : paths)
{
if (isdir(iter))
{
path = iter;
return path;
}
}
return path; // unknown.
}
uint16_t InitEnvironment(const std::vector<std::string> &defines)
{
@ -116,24 +209,30 @@ namespace MPW
uint16_t Init(int argc, char **argv)
{
/*
FDTable.resize(16);
FDTable[STDIN_FILENO] = 1;
FDTable[STDOUT_FILENO] = 1;
FDTable[STDERR_FILENO] = 1;
*/
// stdin/stdout/stderr
{
native::file_ptr io;
/*
OS::Internal::FDTable.resize(3);
FDTable[STDIN_FILENO].refcount = 1;
FDTable[STDIN_FILENO].text = true;
io.reset(new native::fd_file("<stdin>", STDIN_FILENO));
io->text = true;
OS::Internal::open_file(std::move(io));
FDTable[STDOUT_FILENO].refcount = 1;
FDTable[STDOUT_FILENO].text = true;
io.reset(new native::fd_file("<stdout>", STDOUT_FILENO));
io->text = true;
OS::Internal::open_file(std::move(io));
FDTable[STDERR_FILENO].refcount = 1;
FDTable[STDERR_FILENO].text = true;
*/
OS::Internal::FDEntry::allocate(STDIN_FILENO).text = true;
OS::Internal::FDEntry::allocate(STDOUT_FILENO).text = true;
OS::Internal::FDEntry::allocate(STDERR_FILENO).text = true;
io.reset(new native::fd_file("<stderr>", STDERR_FILENO));
io->text = true;
OS::Internal::open_file(std::move(io));
}
std::string command = argv[0];
@ -164,6 +263,8 @@ namespace MPW
uint32_t devptr = 0;
uint32_t fptr = 0;
uint16_t error;
// create the argv-data.
{
uint32_t size = 0;
@ -177,9 +278,8 @@ namespace MPW
size += l;
}
auto tmp = MM::Native::NewPtr(size, true);
if (tmp.error()) return tmp.error();
argvptr = tmp.value();
error = MM::Native::NewPtr(size, true, argvptr);
if (error) return error;
uint8_t *xptr = memoryPointer(argvptr);
@ -231,9 +331,9 @@ namespace MPW
size += 4; // space for null terminator.
auto tmp = MM::Native::NewPtr(size, true);
if (tmp.error()) return tmp.error();
envptr = tmp.value();
error = MM::Native::NewPtr(size, true, envptr);
if (error) return error;
uint8_t *xptr = memoryPointer(envptr);
uint32_t offset = 0;
@ -264,9 +364,9 @@ namespace MPW
// these are ftraps for emulated/native function ptrs.
uint32_t size = 6 * 4;
auto tmp = MM::Native::NewPtr(size, true);
if (tmp.error()) return tmp.error();
fptr = tmp.value();
error = MM::Native::NewPtr(size, true, fptr);
if (error) return error;
memoryWriteWord(fQuit, fptr + 0);
memoryWriteWord(0x4E75, fptr + 2); // rts
@ -293,9 +393,9 @@ namespace MPW
{
uint32_t size = 0x78;
auto tmp = MM::Native::NewPtr(size, true);
if (tmp.error()) return tmp.error();
devptr = tmp.value();
error = MM::Native::NewPtr(size, true, devptr);
if (error) return error;
memoryWriteLong(0x46535953, devptr + 0); // 'FSYS'
memoryWriteLong(fptr + 4, devptr + 4);
@ -315,9 +415,9 @@ namespace MPW
uint32_t size = 0x3c;
uint32_t ptr;
auto tmp = MM::Native::NewPtr(size, true);
if (tmp.error()) return tmp.error();
ioptr = tmp.value();
error = MM::Native::NewPtr(size, true, ioptr);
if (error) return error;
ptr = ioptr;
// stdin
@ -350,9 +450,10 @@ namespace MPW
auto tmp = MM::Native::NewPtr(8 + 0x30, true);
if (tmp.error()) return tmp.error();
uint32_t mpi = tmp.value();
uint32_t mpi = 0;
error = MM::Native::NewPtr(8 + 0x30, true, mpi);
if (error) return error;
MacProgramInfo = mpi + 8;

View File

@ -40,6 +40,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/paths.h>
#include <cpu/defs.h>
#include <cpu/fmem.h>
@ -50,20 +51,12 @@
#include <toolbox/os_internal.h>
#include <macos/errors.h>
#include <native/native.h>
/*
* access return errors are |= 0x40000000. Not entirely sure why...
* may return an errno or an oserr, too, apparently.
*/
/* 2016 update -- faccess checks if the error (16-bit) is negative (tool error)
* or positive (errno) and calls _uerror(errno, toolerr). toolerr is stored into
* the MacOSErr variable and remapped to an errno. if toolerr == 0, errno is stored in
* errno.
*/
using MacOS::macos_error_from_errno;
namespace MPW
{
@ -162,13 +155,54 @@ namespace MPW
}
/*
MPW's open logic pseudo code:
if (flags & 0x1000) { // undocumented - use old tool calls
oserr = flags & O_RSRC ? PBOPENRF() : PBOPEN();
} else {
oserr = flags & O_RSRC ? PBHOPENRF() : PBHOPEN();
}
if (!oserr) {
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
errno = EEXIST;
return;
}
return;
}
if (oserr == file not found) {
if (flags & O_CREAT) {
oserr = PBCreate();
if (!oserr) {
oserr = flag & O_RSRC ? PBOpenRF() : PBOpen();
}
}
PBGETFCBINFO();
if (file size) {
if (flags & O_TRUNC) {
oserr = PBSetEOF();
}
if (!permission check) {
errno = EPERM;
PBClose();
}
*/
uint32_t ftrap_open(uint32_t name, uint32_t parm)
{
uint32_t d0;
int fd;
std::string sname;
MPWFile f;
int nativeFlags;
int nativeFlags = 0;
std::memset(&f, 0, sizeof(f));
f.flags = memoryReadWord(parm);
@ -200,47 +234,58 @@ namespace MPW
Log(" open(%s, %04x)\n", sname.c_str(), f.flags);
// TODO -- can you create a resource file like this?
auto fd = native::open_fork(sname, f.flags & kO_RSRC, nativeFlags);
if (f.flags & kO_RSRC) {
if (!fd)
// O_CREAT and O_EXCL apply to the file, not the fork.
int flags = O_RDONLY | (nativeFlags & (O_CREAT | O_EXCL));
int parent = ::open(sname.c_str(), flags, 0666);
fd = -1;
if (parent >= 0) {
sname.append(_PATH_RSRCFORKSPEC);
nativeFlags &= ~O_EXCL;
// APFS, etc - resource fork doesn't automatically exist so
// need O_CREAT.
if ((nativeFlags & O_ACCMODE) != O_RDONLY) nativeFlags |= O_CREAT;
fd = ::open(sname.c_str(), nativeFlags, 0666);
close(parent);
}
} else {
fd = ::open(sname.c_str(), nativeFlags, 0666);
}
if (fd < 0)
{
// return a tool error.
auto e = fd.error();
d0 = 0x40000000 | (uint16_t)e; /* | mpw_errno_from_errno(); */
f.error = (uint16_t)e;
// return an errno.
d0 = 0x40000000 | mpw_errno_from_errno();
f.error = MacOS::ioErr;
f.cookie = 0;
}
else
{
d0 = 0;
f.error = 0;
//f.cookie = fd;
f.cookie = fd;
native::file_ptr ff = std::move(fd).value();
// adjust the binary flags...
// some apps are good about this but
// dumpobj, makelib, linkiigs don't set O_BINARY (but should)
// MPW Assembler sets O_BINARY (but shouldn't)
if (native::is_text_file(sname)) f.flags &= ~kO_BINARY;
if (native::is_binary_file(sname)) f.flags |= kO_BINARY;
if (OS::IsTextFile(sname)) f.flags &= ~kO_BINARY;
if (OS::IsBinaryFile(sname)) f.flags |= kO_BINARY;
if (f.flags & kO_RSRC) f.flags |= kO_BINARY;
ff->text = !(f.flags & kO_BINARY);
ff->resource = f.flags & kO_RSRC;
f.cookie = OS::Internal::open_file(std::move(ff));
/*
auto &e = OS::Internal::FDEntry::allocate(fd, std::move(xname));
e.text = !(f.flags & kO_BINARY);
e.resource = f.flags & kO_RSRC;
*/
}
memoryWriteWord(f.flags, parm + 0);

View File

@ -49,6 +49,9 @@ namespace MPW
void ftrap_close(uint16_t trap)
{
// returns an mpw_errno
// close actually checks the error in the File Entry and converts that to unix.
// (sigh)
uint32_t d0 = 0;
@ -64,24 +67,61 @@ namespace MPW
f.count = memoryReadLong(parm + 12);
f.buffer = memoryReadLong(parm + 16);
f.error = 0;
Log("%04x Close(%08x)\n", trap, parm);
int fd = f.cookie;
Log(" close(%02x)\n", fd);
int rv = OS::Internal::close_file(fd);
if (rv < 0) {
d0 = kEBADF;
if (!parm)
{
cpuSetDReg(0, kEINVAL);
return;
}
int fd = f.cookie;
int rv = OS::Internal::FDEntry::close(fd);
if (rv < 0)
{
f.error = MacOS::notOpenErr;
d0 = kEINVAL;
}
else
{
f.error = 0;
d0 = 0;
}
#if 0
if (fd < 0 || fd >= OS::Internal::FDTable.size())
{
f.error = OS::notOpenErr;
d0 = kEINVAL;
}
else
{
auto &e = OS::Internal::FDTable[fd];
if (e.refcount == 0)
{
f.error = OS::notOpenErr;
d0 = kEINVAL;
}
else
{
if (--e.refcount == 0)
{
Log(" close(%02x)\n", fd);
::close(fd);
}
f.error = 0;
d0 = 0;
}
}
#endif
memoryWriteWord(f.error, parm + 2);
cpuSetDReg(0, d0);
cpuSetDReg(0, 0);
}

View File

@ -128,9 +128,7 @@ namespace MPW {
case kENOMEM: return ENOMEM;
case kEACCES: return EACCES;
case kEFAULT: return EFAULT;
#ifdef ENOTBLK
case kENOTBLK: return ENOTBLK;
#endif
case kEBUSY: return EBUSY;
case kEEXIST: return EEXIST;
case kEXDEV: return EXDEV;
@ -195,9 +193,7 @@ namespace MPW {
case ENOMEM: return kENOMEM;
case EACCES: return kEACCES;
case EFAULT: return kEFAULT;
#ifdef ENOTBLK
case ENOTBLK: return kENOTBLK;
#endif
case EBUSY: return kEBUSY;
case EEXIST: return kEEXIST;
case EXDEV: return kEXDEV;

View File

@ -53,7 +53,7 @@ namespace MPW
void ftrap_read(uint16_t trap)
{
uint32_t d0 = 0;
uint32_t d0;
uint32_t sp = cpuGetAReg(7);
uint32_t parm = memoryReadLong(sp + 4);
@ -67,21 +67,27 @@ namespace MPW
f.count = memoryReadLong(parm + 12);
f.buffer = memoryReadLong(parm + 16);
f.error = 0;
Log("%04x Read(%08x)\n", trap, parm);
d0 = 0;
int fd = f.cookie;
ssize_t size;
Log(" read(%04x, %08x, %08x)", fd, f.buffer, f.count);
Log(" read(%04x, %08x, %08x)\n", fd, f.buffer, f.count);
size = OS::Internal::FDEntry::read(fd, memoryPointer(f.buffer), f.count);
//Log(" -> %ld\n", size);
auto ff = OS::Internal::find_file(fd);
if (ff) {
auto e = ff->read(memoryPointer(f.buffer), f.count);
f.count -= e.value_or(0);
d0 = f.error = e.error();
} else {
d0 = kEBADF;
if (size < 0)
{
//f.count = 0;
f.error = MacOS::ioErr; // ioErr
d0 = mpw_errno_from_errno();
}
else
{
f.count -= size;
f.error = 0;
}
// write back...
@ -93,7 +99,7 @@ namespace MPW
void ftrap_write(uint16_t trap)
{
uint32_t d0 = 0;
uint32_t d0;
uint32_t sp = cpuGetAReg(7);
uint32_t parm = memoryReadLong(sp + 4);
@ -107,21 +113,26 @@ namespace MPW
f.count = memoryReadLong(parm + 12);
f.buffer = memoryReadLong(parm + 16);
f.error = 0;
Log("%04x Write(%08x)\n", trap, parm);
d0 = 0;
int fd = f.cookie;
ssize_t size;
Log(" write(%04x, %08x, %08x)\n", fd, f.buffer, f.count);
size = OS::Internal::FDEntry::write(fd, memoryPointer(f.buffer), f.count);
auto ff = OS::Internal::find_file(fd);
if (ff) {
auto e = ff->write(memoryPointer(f.buffer), f.count);
f.count -= e.value_or(0);
d0 = f.error = e.error();
} else {
d0 = kEBADF;
if (size < 0)
{
//f.count = 0;
f.error = MacOS::ioErr; // ioErr
d0 = mpw_errno_from_errno();
}
else
{
f.count -= size;
f.error = 0;
}
// write back...

View File

@ -40,6 +40,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/paths.h>
#include <cpu/defs.h>
#include <cpu/fmem.h>
@ -59,7 +60,7 @@ namespace MPW
uint32_t ftrap_dup(uint32_t parm, uint32_t arg)
{
uint32_t d0 = 0;
uint32_t d0;
MPWFile f;
f.flags = memoryReadWord(parm);
@ -75,13 +76,37 @@ namespace MPW
Log(" dup(%02x)\n", fd);
auto ff = OS::Internal::find_file(fd);
if (ff) {
ff->refcount++;
d0 = OS::Internal::FDEntry::action(fd,
[](int fd, OS::Internal::FDEntry &e){
e.refcount++;
return 0;
},
[](int fd){
return kEINVAL;
}
);
#if 0
try
{
auto &e = OS::Internal::FDTable.at(fd);
if (e.refcount)
{
d0 = 0;
fd.refcount++;
}
else
{
d0 = kEINVAL;
}
}
else {
d0 = kEBADF;
catch(std::out_of_range &ex)
{
d0 = kEINVAL;
}
#endif
memoryWriteWord(f.error, parm + 2);
return d0;
@ -92,7 +117,6 @@ namespace MPW
// should return the preferred buffsize in *arg
// an error will use the default size (0x400 bytes).
uint32_t d0 = 0;
MPWFile f;
f.flags = memoryReadWord(parm);
@ -108,24 +132,18 @@ namespace MPW
Log(" bufsize(%02x)\n", fd);
auto ff = OS::Internal::find_file(fd);
if (ff) {
d0 = kEINVAL;
} else {
d0 = kEBADF;
}
memoryWriteWord(f.error, parm + 2);
return d0;
return kEINVAL;
}
uint32_t ftrap_interactive(uint32_t parm, uint32_t arg)
{
// return 0 if interactive, an error if
// non-interactive. arg is null.
// non-interactive.
uint32_t d0;
uint32_t d0 = 0;
MPWFile f;
f.flags = memoryReadWord(parm);
@ -145,13 +163,37 @@ namespace MPW
Log(" interactive(%02x)\n", fd);
d0 = OS::Internal::FDEntry::action(fd,
[](int fd, OS::Internal::FDEntry &e){
auto ff = OS::Internal::find_file(fd);
if (!ff) {
d0 = kEBADF;
} else if (!ff->interactive()) {
f.error = d0 = MacOS::paramErr;
int tty = ::isatty(fd);
return tty ? 0 : kEINVAL;
},
[](int fd){
return kEINVAL;
}
);
#if 0
try
{
auto &e = OS::Internal::FDTable.at(fd);
if (e.refcount)
{
int tty = ::isatty(fd);
d0 = tty ? 0 : kEINVAL;
}
else
{
d0 = kEINVAL;
}
}
catch(std::out_of_range &ex)
{
d0 = kEINVAL;
}
#endif
memoryWriteWord(f.error, parm + 2);
return d0;
@ -159,11 +201,9 @@ namespace MPW
uint32_t ftrap_fname(uint32_t parm, uint32_t arg)
{
// return file name (full path).
// return file name.
// AsmIIgs uses this...
// arg is a c-string ptr.
uint32_t d0 = 0;
MPWFile f;
f.flags = memoryReadWord(parm);
@ -179,22 +219,15 @@ namespace MPW
Log(" fname(%02x)\n", fd);
auto ff = OS::Internal::find_file(fd);
if (ff) {
f.error = d0 = MacOS::paramErr;
} else {
d0 = kEBADF;
}
memoryWriteWord(f.error, parm + 2);
return d0;
return kEINVAL;
}
uint32_t ftrap_refnum(uint32_t parm, uint32_t arg)
{
// returns the refnum in *arg
// on mpw, stdin/stdout/stderr return a param error.
uint32_t d0 = 0;
uint32_t d0;
MPWFile f;
f.flags = memoryReadWord(parm);
@ -210,13 +243,27 @@ namespace MPW
Log(" refnum(%02x)\n", fd);
auto ff = OS::Internal::find_file(fd);
if (ff) {
if (ff->interactive()) f.error = d0 = MacOS::paramErr;
else memoryWriteWord(fd, arg);
} else {
d0 = kEBADF;
d0 = OS::Internal::FDEntry::action(fd,
[arg](int fd, OS::Internal::FDEntry &e){
memoryWriteWord(fd, arg);
return 0;
},
[](int fd){
return kEINVAL;
}
);
#if 0
if (fd < 0 || fd >= FDTable.size() || !FDTable[fd])
{
d0 = kEINVAL;
}
else
{
d0 = 0;
memoryWriteWord(fd, arg);
}
#endif
memoryWriteWord(f.error, parm + 2);
return d0;
@ -226,8 +273,8 @@ namespace MPW
uint32_t ftrap_lseek(uint32_t parm, uint32_t arg)
{
uint32_t d0 = 0;
MPWFile f;
uint32_t d0;
uint32_t whence = memoryReadLong(arg);
int32_t offset = memoryReadLong(arg + 4); // signed value.
@ -240,8 +287,8 @@ namespace MPW
f.count = memoryReadLong(parm + 12);
f.buffer = memoryReadLong(parm + 16);
f.error = 0;
int fd = f.cookie;
/*
* LinkIIgs does a seek on stdin. If it doesn't cause an
@ -270,21 +317,33 @@ namespace MPW
return kEINVAL;
}
int fd = f.cookie;
Log(" lseek(%02x, %08x, %02x)\n", fd, offset, nativeWhence);
if (::isatty(fd))
{
off_t rv = -1;
off_t rv = - 1;
auto ff = OS::Internal::find_file(fd);
if (ff) {
MacOS::tool_return<size_t> e(MacOS::noErr);
if (ff->interactive()) e = MacOS::paramErr;
else e = ff->seek(offset, nativeWhence);
rv = e.value_or(-1);
f.error = d0 = e.error();
} else {
d0 = kEBADF;
}
d0 = kEINVAL;
f.error = 0;
memoryWriteLong(rv, arg + 4);
memoryWriteWord(f.error, parm + 2);
return d0;
}
off_t rv = ::lseek(fd, offset, nativeWhence);
if (rv < 0)
{
d0 = mpw_errno_from_errno();
f.error = macos_error_from_errno();
//perror(NULL);
}
else
{
d0 = 0;
f.error = 0;
}
memoryWriteLong(rv, arg + 4);
memoryWriteWord(f.error, parm + 2);
@ -295,7 +354,8 @@ namespace MPW
uint32_t ftrap_seteof(uint32_t parm, uint32_t arg)
{
uint32_t d0 = 0;
uint32_t d0;
MPWFile f;
f.flags = memoryReadWord(parm);
@ -311,15 +371,18 @@ namespace MPW
Log(" seteof(%02x, %08x)\n", fd, arg);
auto ff = OS::Internal::find_file(fd);
if (ff) {
MacOS::tool_return<size_t> e(MacOS::noErr);
if (ff->interactive()) e = MacOS::paramErr;
else e = ff->set_eof(arg);
f.error = d0 = e.error();
} else {
d0 = kEBADF;
}
d0 = OS::Internal::FDEntry::action(fd,
[arg, &f](int fd, OS::Internal::FDEntry &e){
int ok = ftruncate(fd, arg);
if (ok == 0) return 0;
f.error = macos_error_from_errno();
return (int)mpw_errno_from_errno();
},
[](int fd){
return kEINVAL;
}
);
memoryWriteWord(f.error, parm + 2);
return d0;

View File

@ -1,6 +0,0 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(NATIVE_SRC native.cpp file.cpp ${CMAKE_SYSTEM_NAME}.cpp)
add_library(NATIVE_LIB ${NATIVE_SRC})
target_link_libraries(NATIVE_LIB MACOS_LIB)

View File

@ -1,408 +0,0 @@
/*
* Copyright (c) 2016, Kelvin W Sherlock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "native_internal.h"
#include <sys/attr.h>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/paths.h>
#include <unistd.h>
#include <fcntl.h>
#include "config.h"
#include <include/endian.h>
//using MacOS::macos_error_from_errno;
//using MacOS::macos_error;
using namespace MacOS;
// pre 10.5 I guess...
#ifndef HAVE_STAT_ST_BIRTHTIME
#undef st_birthtime
#define st_birthtime st_ctime
#endif
namespace {
uint32_t rforksize(const std::string &path_name)
{
ssize_t rv;
rv = getxattr(path_name.c_str(), XATTR_RESOURCEFORK_NAME, nullptr, 0, 0, 0);
if (rv < 0) return 0;
return rv;
}
/*
uint32_t rforksize(int fd)
{
ssize_t rv;
rv = fgetxattr(fd, XATTR_RESOURCEFORK_NAME, nullptr, 0, 0, 0);
if (rv < 0) return 0;
return rv;
}
*/
}
namespace native {
/*
tech note PT515
ProDOS -> Macintosh conversion
ProDOS Macintosh
Filetype Auxtype Creator Filetype
$00 $0000 'pdos' 'BINA'
$B0 (SRC) (any) 'pdos' 'TEXT'
$04 (TXT) $0000 'pdos' 'TEXT'
$FF (SYS) (any) 'pdos' 'PSYS'
$B3 (S16) (any) 'pdos' 'PS16'
$uv $wxyz 'pdos' 'p' $uv $wx $yz
Programmer's Reference for System 6.0:
ProDOS Macintosh
File Type Auxiliary Type Creator Type File Type
$00 $0000 pdos BINA
$04 (TXT) $0000 pdos TEXT
$FF (SYS) (any) pdos PSYS
$B3 (S16) $DByz pdos p $B3 $DB $yz
$B3 (S16) (any) pdos PS16
$D7 $0000 pdos MIDI
$D8 $0000 pdos AIFF
$D8 $0001 pdos AIFC
$E0 $0005 dCpy dImg
$FF (SYS) (any) pdos PSYS
$uv $wxyz pdos p $uv $wx $yz
mpw standard:
$uv (any) "pdos" printf("%02x ",$uv)
*/
macos_error get_finder_info(const std::string &path_name, void *info, bool extended) {
uint8_t buffer[32];
int rv;
std::memset(buffer, 0, sizeof(buffer));
rv = getxattr(path_name.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
if (rv == 16 || rv == 32) {
prodos_ftype_out(buffer);
memcpy(info, buffer, extended ? 32 : 16);
return noErr;
}
if (rv < 0) {
switch (errno) {
case ENOATTR:
case ENOTSUP:
break;
default:
return macos_error_from_errno();
}
}
/* finder info does not exist */
/* 1. check prodos ftype/aux type */
uint8_t ftype;
uint16_t atype;
int rv1 = ::getxattr(path_name.c_str(), "prodos.FileType", &ftype, 1, 0, 0);
int rv2 = ::getxattr(path_name.c_str(), "prodos.AuxType", &atype, 2, 0, 0);
if (rv1 == 1 && rv2 == 2) {
ftype = le16toh(ftype);
memcpy(buffer, "pxxxpdos", 8);
buffer[1] = (char)ftype;
buffer[2] = (char)((atype >> 8) & 0xff);
buffer[3] = (char)(atype & 0xff);
switch (atype)
{
case 0x00:
std::memcpy(buffer, "BINA", 4);
break;
case 0x04:
case 0xb0:
std::memcpy(buffer, "TEXT", 4);
break;
case 0xff:
std::memcpy(buffer, "PSYS", 4);
break;
case 0xd7:
std::memcpy(buffer, "MIDI", 4);
break;
case 0xd8:
switch (atype)
{
case 0x0000:
std::memcpy(buffer, "AIFF", 4);
break;
case 0x0001:
std::memcpy(buffer, "AIFC", 4);
break;
}
break;
case 0xe0:
switch (atype)
{
case 0x0005:
std::memcpy(buffer, "dImgdCpy", 8);
break;
}
case 0xb3:
if (atype == 0)
{
std::memcpy(buffer, "PS16", 4); // verify dumpobj.
break;
}
}
prodos_ftype_out(buffer);
memcpy(info, buffer, extended ? 32 : 16);
return noErr;
}
/* if it's a text file, call it a text file */
if (is_text_file_internal(path_name)) {
memcpy(buffer, "TEXTMPS ", 8);
}
memcpy(info, buffer, extended ? 32 : 16);
return noErr;
}
macos_error set_finder_info(const std::string &path_name, const void *info, bool extended) {
uint8_t buffer[32];
ssize_t rv;
std::memset(buffer, 0, sizeof(buffer));
if (extended) {
std::memcpy(buffer, info, 32);
} else {
get_finder_info(path_name, buffer, true);
std::memcpy(buffer, info, 16);
}
prodos_ftype_in(buffer);
rv = setxattr(path_name.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
if ( rv < 0) return macos_error_from_errno();
return noErr;
}
macos_error get_file_info(const std::string &path_name, file_info &fi)
{
struct stat st;
if (stat(path_name.c_str(), &st) < 0)
return macos_error_from_errno();
fi.create_date = unix_to_mac(st.st_birthtime);
fi.modify_date = unix_to_mac(st.st_mtime);
fi.backup_date = 0;
fi.attributes = 0;
if (S_ISDIR(st.st_mode)) {
fi.type = file_info::directory;
fi.attributes = 1 << 4;
int links = st.st_nlink - 2;
if (links < 0) links = 0;
if (links > 65535) links = 65535;
fi.entry_count = links;
return noErr;
}
// todo -- get actual block size instead of assuming 512. oh well!
fi.type = file_info::file;
fi.data_logical_size = st.st_size;
fi.data_physical_size = (st.st_size + 511) & ~511;
fi.resource_physical_size = 0;
fi.resource_logical_size = 0;
get_finder_info(path_name, fi.finder_info);
ssize_t rsize = rforksize(path_name);
if (rsize > 0) {
fi.resource_physical_size = rsize;
fi.resource_logical_size = (rsize + 511) & ~511;
}
return noErr;
}
macos_error set_file_info(const std::string &path_name, const file_info &fi) {
struct stat st;
if (stat(path_name.c_str(), &st) < 0) return macos_error_from_errno();
if (S_ISREG(st.st_mode)) {
auto rv = set_finder_info(path_name, fi.finder_info);
if (rv) return rv;
}
time_t create_date = fi.create_date ? mac_to_unix(fi.create_date) : 0;
time_t modify_date = fi.modify_date ? mac_to_unix(fi.modify_date) : 0;
time_t backup_date = fi.backup_date ? mac_to_unix(fi.backup_date) : 0;
// todo -- value of 0 == set to current date/time?
if (create_date == st.st_birthtime) create_date = 0;
if (modify_date == st.st_mtime) modify_date = 0;
// try setattr list.
int rv;
struct attrlist list;
unsigned i = 0;
timespec dates[3];
memset(&list, 0, sizeof(list));
memset(dates, 0, sizeof(dates));
list.bitmapcount = ATTR_BIT_MAP_COUNT;
list.commonattr = 0;
if (create_date)
{
dates[i++].tv_sec = create_date;
list.commonattr |= ATTR_CMN_CRTIME;
}
if (fi.modify_date)
{
dates[i++].tv_sec = modify_date;
list.commonattr |= ATTR_CMN_MODTIME;
}
if (backup_date)
{
dates[i++].tv_sec = backup_date;
list.commonattr |= ATTR_CMN_BKUPTIME;
}
if (!i) return noErr;
rv = setattrlist(path_name.c_str(), &list, dates, i * sizeof(timespec), 0);
if (rv < 0 && errno == ENOTSUP)
{
// try utimes.
struct timeval tv[2];
memset(tv, 0, sizeof(tv));
rv = 0;
if (modify_date) {
tv[0].tv_sec = st.st_atime;
tv[1].tv_sec = modify_date;
rv = utimes(path_name.c_str(), tv);
}
}
if (rv < 0) return macos_error_from_errno();
return noErr;
}
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
std::string rname = path_name + _PATH_RSRCFORKSPEC;
// todo -- verify behavior on non-hfs volume.
//if ((oflag & O_ACCMODE) & O_WRONLY) oflag |= O_CREAT;
// under apfs, resource fork needs to be specifically created.
// (if 0-length, it doesn't actually exist...)
// apfs -- zero-length resource fork
int parent;
if (oflag & O_CREAT) {
int excl = oflag & O_EXCL;
parent = open(path_name.c_str(), O_RDONLY | O_CREAT | excl, 0666);
} else {
parent = open(path_name.c_str(), O_RDONLY);
}
if (parent < 0) return macos_error_from_errno();
close(parent);
oflag &= ~(O_CREAT | O_EXCL);
int mode = oflag & O_ACCMODE;
if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT;
int fd = open(rname.c_str(), oflag, 0666);
if (fd < 0) {
auto e = macos_error_from_errno();
if (errno == ENOENT && mode == O_RDONLY) {
auto tmp = new empty_file(path_name);
tmp->resource = true;
return file_ptr(tmp);
}
return e;
}
auto tmp = new fd_file(path_name, fd);
tmp->resource = true;
return file_ptr(tmp);
}
}

View File

@ -1,342 +0,0 @@
/*
* Copyright (c) 2016, Kelvin W Sherlock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define XATTR_FINDERINFO_NAME "user.apple.FinderInfo"
#define XATTR_RESOURCEFORK_NAME "user.apple.ResourceFork"
#define XATTR_FILETYPE_NAME "user.prodos.FileType"
#define XATTR_AUXTYPE_NAME "user.prodos.AuxType"
#include "native_internal.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <utime.h>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cerrno>
#include <macos/errors.h>
#ifndef ENOATTR
#define ENOATTR ENODATA
#endif
using MacOS::tool_return;
using MacOS::macos_error;
using MacOS::macos_error_from_errno;
namespace {
class xattr_file final : public native::file {
public:
xattr_file(const std::string &path, int fd, bool readonly): file(path), _fd(fd), _readonly(readonly)
{}
~xattr_file();
virtual tool_return<size_t> read(void *out_buffer, size_t count) override;
virtual tool_return<size_t> write(const void *in_buffer, size_t count) override;
virtual tool_return<size_t> get_mark() override;
virtual tool_return<size_t> set_mark(ssize_t new_mark) override;
virtual tool_return<size_t> get_eof() override;
virtual tool_return<size_t> set_eof(ssize_t new_eof) override;
private:
ssize_t read_rfork(std::vector<uint8_t> &buffer);
int _fd = -1;
size_t _displacement = 0;
bool _readonly = false;
};
xattr_file::~xattr_file() {
close(_fd);
}
ssize_t xattr_file::read_rfork(std::vector<uint8_t> &buffer) {
ssize_t eof = -1;
buffer.clear();
do {
eof = fgetxattr(_fd, XATTR_RESOURCEFORK_NAME, NULL, 0);
if (eof < 0) break;
buffer.resize(eof);
eof = fgetxattr(_fd, XATTR_RESOURCEFORK_NAME, buffer.data(), eof);
} while (eof < 0 && errno == ERANGE);
return eof;
}
tool_return<size_t> xattr_file::read(void *out_buffer, size_t count) {
std::vector<uint8_t> buffer;
ssize_t size;
size = read_rfork(buffer);
if (size < 0) size = 0;
if (_displacement >= buffer.size()) return 0;
count = std::min(count, buffer.size() - _displacement);
std::copy_n(buffer.begin() + _displacement, count, (uint8_t *)out_buffer);
_displacement += count;
return count;
}
tool_return<size_t> xattr_file::write(const void *in_buffer, size_t count) {
if (_readonly) return MacOS::wrPermErr;
std::vector<uint8_t> buffer;
ssize_t size;
size = read_rfork(buffer);
if (size < 0) size = 0;
if (_displacement >= buffer.size()) {
buffer.resize(_displacement, 0);
}
if (_displacement + count >= buffer.size()) {
buffer.resize(_displacement + count, 0);
}
std::copy_n((const uint8_t *)in_buffer, count, buffer.begin() + _displacement);
int ok = fsetxattr(_fd, XATTR_RESOURCEFORK_NAME, buffer.data(), buffer.size(), 0);
if (ok < 0) return macos_error_from_errno();
_displacement += count;
return count;
}
tool_return<size_t> xattr_file::get_mark() {
return _displacement;
}
tool_return<size_t> xattr_file::set_mark(ssize_t new_mark) {
if (new_mark < 0) return MacOS::paramErr;
_displacement = new_mark;
return new_mark;
}
tool_return<size_t> xattr_file::get_eof() {
ssize_t eof = fgetxattr(_fd, XATTR_RESOURCEFORK_NAME, NULL, 0);
if (eof < 0) eof = 0;
return eof;
}
tool_return<size_t> xattr_file::set_eof(ssize_t new_eof) {
if (_readonly) return MacOS::wrPermErr;
if (new_eof < 0) return MacOS::paramErr;
std::vector<uint8_t> buffer;
ssize_t eof = read_rfork(buffer);
if (eof < 0) eof = 0;
if (eof == new_eof) return MacOS::noErr;
buffer.resize(new_eof, 0);
int ok = fsetxattr(_fd, XATTR_RESOURCEFORK_NAME, buffer.data(), buffer.size(), 0);
if (ok < 0) return macos_error_from_errno();
return new_eof;
}
uint32_t rforksize(const std::string &path_name)
{
ssize_t ok = getxattr(path_name.c_str(), XATTR_RESOURCEFORK_NAME, NULL, 0);
if (ok < 0) ok = 0;
return ok;
}
}
namespace native {
macos_error get_finder_info(const std::string &path_name, void *info, bool extended) {
uint8_t buffer[32];
std::memset(buffer, 0, sizeof(buffer));
ssize_t ok;
ok = getxattr(path_name.c_str(), XATTR_FINDERINFO_NAME, buffer, 32);
if (ok ==16 || ok == 32) {
prodos_ftype_out(buffer);
memcpy(info, buffer, extended ? 32 : 16);
return MacOS::noErr;
}
if (ok < 0 && errno != ENOATTR && errno != ENOTSUP) return macos_error_from_errno();
/* if it's a text file, call it a text file */
if (is_text_file_internal(path_name)) {
memcpy(buffer, "TEXTMPS ", 8);
}
memcpy(info, buffer, extended ? 32 : 16);
return MacOS::noErr;
}
macos_error set_finder_info(const std::string &path_name, const void *info, bool extended) {
uint8_t buffer[32];
ssize_t rv;
std::memset(buffer, 0, sizeof(buffer));
if (extended) {
std::memcpy(buffer, info, 32);
} else {
std::memcpy(buffer, info, 16);
}
prodos_ftype_in(buffer);
int ok = setxattr(path_name.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0);
if ( ok < 0) return macos_error_from_errno();
return MacOS::noErr;
}
macos_error get_file_info(const std::string &path_name, file_info &fi)
{
struct stat st;
if (stat(path_name.c_str(), &st) < 0)
return macos_error_from_errno();
fi.create_date = unix_to_mac(st.st_ctime);
fi.modify_date = unix_to_mac(st.st_mtime);
fi.backup_date = 0;
if (S_ISDIR(st.st_mode)) {
fi.type = file_info::directory;
fi.attributes = 1 << 4;
int links = st.st_nlink - 2;
if (links < 0) links = 0;
if (links > 65535) links = 65535;
fi.entry_count = links;
return MacOS::noErr;
}
// todo -- get actual block size instead of assuming 512. oh well!
fi.type = file_info::file;
fi.data_logical_size = st.st_size;
fi.data_physical_size = (st.st_size + 511) & ~511;
fi.resource_physical_size = 0;
fi.resource_logical_size = 0;
get_finder_info(path_name, fi.finder_info);
ssize_t rsize = rforksize(path_name);
if (rsize > 0) {
fi.resource_physical_size = rsize;
fi.resource_logical_size = (rsize + 511) & ~511;
}
return MacOS::noErr;
}
macos_error set_file_info(const std::string &path_name, const file_info &fi) {
struct stat st;
if (stat(path_name.c_str(), &st) < 0) return macos_error_from_errno();
if (S_ISREG(st.st_mode)) {
auto rv = set_finder_info(path_name, fi.finder_info);
if (rv) return rv;
}
time_t create_date = fi.create_date ? mac_to_unix(fi.create_date) : 0;
time_t modify_date = fi.modify_date ? mac_to_unix(fi.modify_date) : 0;
time_t backup_date = fi.backup_date ? mac_to_unix(fi.backup_date) : 0;
// todo -- value of 0 == set to current date/time?
if (modify_date == st.st_mtime) modify_date = 0;
// try utimes.
struct timeval tv[2];
memset(tv, 0, sizeof(tv));
int rv = 0;
if (modify_date) {
tv[0].tv_sec = st.st_atime;
tv[1].tv_sec = modify_date;
rv = utimes(path_name.c_str(), tv);
}
if (rv < 0) return macos_error_from_errno();
return MacOS::noErr;
}
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
/* under HFS, every file has a resource fork.
* Therefore, create it if opening for O_RDWR or O_WRONLY
*/
int parent;
if (oflag & O_CREAT) {
int excl = oflag & O_EXCL;
parent = open(path_name.c_str(), O_RDONLY | O_CREAT | excl, 0666);
} else {
parent = open(path_name.c_str(), O_RDONLY);
}
if (parent < 0) return macos_error_from_errno();
int mode = oflag & O_ACCMODE;
auto tmp = new xattr_file(path_name, parent, mode == O_RDONLY);
tmp->resource = true;
return file_ptr(tmp);
}
}

View File

@ -1,242 +0,0 @@
/*
* Copyright (c) 2016, Kelvin W Sherlock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "native_internal.h"
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <fcntl.h>
#include "config.h"
#define XATTR_FINDERINFO_NAME "com.apple.FinderInfo"
#define XATTR_RESOURCEFORK_NAME "com.apple.ResourceFork"
#define XATTR_FILETYPE_NAME "prodos.FileType"
#define XATTR_AUXTYPE_NAME "prodos.AuxType"
using namespace MacOS;
namespace {
uint32_t rforksize(const std::string &path_name)
{
int fd;
uint32_t rv = 0;
struct stat st;
fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, O_RDONLY);
if (fd >= 0) {
if (fstat(fd, &st) == 0) rv = st.st_size;
close(fd);
}
return rv;
}
}
namespace native {
macos_error get_finder_info(const std::string &path_name, void *info, bool extended) {
uint8_t buffer[32];
std::memset(buffer, 0, sizeof(buffer));
int fd;
fd = attropen(path_name.c_str(), XATTR_FINDERINFO_NAME, O_RDONLY);
if (fd >= 0) {
ssize_t x = read(fd, buffer, 32);
close(fd);
if (x == 32 || x == 16){
prodos_ftype_out(buffer);
memcpy(info, buffer, extended ? 32 : 16);
return noErr;
}
}
/* if it's a text file, call it a text file */
if (is_text_file_internal(path_name)) {
memcpy(buffer, "TEXTMPS ", 8);
}
memcpy(info, buffer, extended ? 32 : 16);
return noErr;
}
macos_error set_finder_info(const std::string &path_name, const void *info, bool extended) {
uint8_t buffer[32];
ssize_t rv;
std::memset(buffer, 0, sizeof(buffer));
if (extended) {
std::memcpy(buffer, info, 32);
} else {
std::memcpy(buffer, info, 16);
}
prodos_ftype_in(buffer);
int fd = attropen(path_name.c_str(), XATTR_FINDERINFO_NAME, O_WRONLY | O_CREAT, 0666);
if (fd < 0) return macos_error_from_errno();
rv = write(fd, info, extended ? 32 : 16);
close(fd);
if ( rv < 0) return macos_error_from_errno();
return noErr;
}
macos_error get_file_info(const std::string &path_name, file_info &fi)
{
struct stat st;
if (stat(path_name.c_str(), &st) < 0)
return macos_error_from_errno();
fi.create_date = unix_to_mac(st.st_ctime);
fi.modify_date = unix_to_mac(st.st_mtime);
fi.backup_date = 0;
if (S_ISDIR(st.st_mode)) {
fi.type = file_info::directory;
fi.attributes = 1 << 4;
int links = st.st_nlink - 2;
if (links < 0) links = 0;
if (links > 65535) links = 65535;
fi.entry_count = links;
return noErr;
}
// todo -- get actual block size instead of assuming 512. oh well!
fi.type = file_info::file;
fi.data_logical_size = st.st_size;
fi.data_physical_size = (st.st_size + 511) & ~511;
fi.resource_physical_size = 0;
fi.resource_logical_size = 0;
get_finder_info(path_name, fi.finder_info);
ssize_t rsize = rforksize(path_name);
if (rsize > 0) {
fi.resource_physical_size = rsize;
fi.resource_logical_size = (rsize + 511) & ~511;
}
return noErr;
}
macos_error set_file_info(const std::string &path_name, const file_info &fi) {
struct stat st;
if (stat(path_name.c_str(), &st) < 0) return macos_error_from_errno();
if (S_ISREG(st.st_mode)) {
auto rv = set_finder_info(path_name, fi.finder_info);
if (rv) return rv;
}
time_t create_date = fi.create_date ? mac_to_unix(fi.create_date) : 0;
time_t modify_date = fi.modify_date ? mac_to_unix(fi.modify_date) : 0;
time_t backup_date = fi.backup_date ? mac_to_unix(fi.backup_date) : 0;
// todo -- value of 0 == set to current date/time?
if (modify_date == st.st_mtime) modify_date = 0;
// try utimes.
struct timeval tv[2];
memset(tv, 0, sizeof(tv));
int rv = 0;
if (modify_date) {
tv[0].tv_sec = st.st_atime;
tv[1].tv_sec = modify_date;
rv = utimes(path_name.c_str(), tv);
}
if (rv < 0) return macos_error_from_errno();
return noErr;
}
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
/* under HFS, every file has a resource fork.
* Therefore, create it if opening for O_RDWR or O_WRONLY
*/
int parent;
if (oflag & O_CREAT) {
int excl = oflag & O_EXCL;
parent = open(path_name.c_str(), O_RDONLY | O_CREAT | excl, 0666);
} else {
parent = open(path_name.c_str(), O_RDONLY);
}
if (parent < 0) return macos_error_from_errno();
oflag &= ~(O_CREAT | O_EXCL);
int mode = oflag & O_ACCMODE;
if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT;
//int fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666);
int fd = openat(parent, XATTR_RESOURCEFORK_NAME, oflag | O_XATTR, 0666);
if (fd < 0) {
int e = macos_error_from_errno();
close(parent);
if (e == ENOENT && mode == O_RDONLY) {
auto tmp = new empty_file(path_name);
tmp->resource = true;
return file_ptr(tmp);
}
return e;
}
close(parent);
auto tmp = new fd_file(path_name, fd);
tmp->resource = true;
return file_ptr(tmp);
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2016, Kelvin W Sherlock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <filesystem>
#include <string>
#include <Windows.h>
#include <Shlobj.h>
namespace fs = std::experimental::filesystem;
namespace native {
static fs::path FindRoot() {
fs::path p;
std::error_code ec;
PWSTR tmp = nullptr;
auto ok = SHGetKnownFolderPath(
FOLDERID_Profile,
0,
nullptr,
&tmp
);
if ((ok == S_OK) && (tmp != nullptr)) {
p = tmp;
p /= "mpw";
if (fs::is_directory(p, ec)) return p;
}
p = "c:\\mpw\\";
if (!fs::is_directory(p, ec)) {
fprintf(stderr, "Warning: %ls does not exist\n", p.c_str());
}
return p;
}
fs::path RootPath() {
// todo -- do it.
static fs::path root;
if (root.empty()) {
root = FindRoot();
}
return root;
}
}

View File

@ -1,214 +0,0 @@
#include "file.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <macos/errors.h>
#include <algorithm>
using MacOS::tool_return;
using MacOS::macos_error_from_errno;
namespace native {
tool_return<size_t> file::seek(ssize_t position, int whence) {
if (interactive()) {
if (position == 0) return 0;
return MacOS::paramErr;
}
switch(whence) {
case SEEK_SET:
return set_mark(position);
break;
case SEEK_CUR: {
auto current = get_mark();
if (!current) return current;
return set_mark(*current + position);
}
break;
case SEEK_END: {
auto eof = get_eof();
if (!eof) return eof;
return set_mark(*eof + position);
}
break;
default:
return MacOS::paramErr;
}
}
bool file::interactive() {
return false;
}
fd_file::fd_file(const std::string &s, int fd): file(s), _fd(fd) {
_interactive = ::isatty(fd);
}
fd_file::~fd_file() {
// don't close stdin/stdout/stderr.
if (_fd >= 3) ::close(_fd);
};
namespace {
ssize_t safe_read(int fd, void *buffer, size_t count) {
ssize_t rv;
do {
rv = read(fd, buffer, count);
} while (rv < 0 && errno == EINTR);
return rv;
}
ssize_t safe_write(int fd, const void *buffer, size_t count) {
ssize_t rv;
do {
rv = write(fd, buffer, count);
} while (rv < 0 && errno == EINTR);
return rv;
}
}
tool_return<size_t> fd_file::read(void *buffer, size_t count) {
if (_interactive || text) {
std::unique_ptr<uint8_t[]> trbuffer(new uint8_t[count]);
ssize_t ok = ::read(_fd, trbuffer.get(), count);
if (ok < 0) return macos_error_from_errno();
std::transform(trbuffer.get(), trbuffer.get() + ok, (uint8_t *)buffer,
[](uint8_t c) { return c == '\n' ? '\r' : c; }
);
return ok;
}
ssize_t ok = ::read(_fd, buffer, count);
if (ok < 0) return macos_error_from_errno();
return ok;
}
tool_return<size_t> fd_file::write(const void *buffer, size_t count) {
if (_interactive || text) {
std::unique_ptr<uint8_t[]> trbuffer(new uint8_t[count]);
std::transform((const uint8_t *)buffer, (const uint8_t *)buffer + count, trbuffer.get(),
[](uint8_t c) { return c == '\r' ? '\n' : c; }
);
ssize_t ok = ::write(_fd, trbuffer.get(), count);
if (ok < 0) return macos_error_from_errno();
return ok;
}
ssize_t ok = ::write(_fd, buffer, count);
if (ok < 0) return macos_error_from_errno();
return ok;
}
tool_return<size_t> fd_file::seek(ssize_t position, int whence) {
if (_interactive) {
// seek set, cur, eof w/ position 0 ok.
if (position == 0) return 0;
return MacOS::paramErr;
}
off_t pos = ::lseek(_fd, position, whence);
if (pos < 0) return macos_error_from_errno();
return pos;
}
tool_return<size_t> fd_file::get_mark() {
if (_interactive) return 0;
off_t pos = ::lseek(_fd, 0, SEEK_CUR);
if (pos < 0) return macos_error_from_errno();
return pos;
}
tool_return<size_t> fd_file::set_mark(ssize_t new_mark) {
if (_interactive) {
if (new_mark == 0) return 0;
return MacOS::paramErr;
}
off_t pos = ::lseek(_fd, new_mark, SEEK_SET);
if (pos < 0) return macos_error_from_errno();
return new_mark;
}
tool_return<size_t> fd_file::get_eof() {
if (_interactive) return MacOS::paramErr;
struct stat st;
int ok = ::fstat(_fd, &st);
if (ok < 0) return macos_error_from_errno();
return st.st_size;
}
tool_return<size_t> fd_file::set_eof(ssize_t new_eof) {
if (_interactive) return MacOS::paramErr;
int ok = ftruncate(_fd, new_eof);
if (ok < 0) return macos_error_from_errno();
return new_eof;
}
bool fd_file::interactive() {
return _interactive;
}
tool_return<size_t> empty_file::read(void *out_buffer, size_t count) {
if (count == 0) return 0;
return 0; // eofErr handled elsewhere.
}
tool_return<size_t> empty_file::write(const void *in_buffer, size_t count) {
return MacOS::wrPermErr;
}
tool_return<size_t> empty_file::seek(ssize_t position, int whence) {
if (position == 0) return 0;
return MacOS::posErr;
}
tool_return<size_t> empty_file::get_mark() {
return 0;
}
tool_return<size_t> empty_file::set_mark(ssize_t new_mark) {
if (new_mark == 0) return 0;
return MacOS::posErr;
}
tool_return<size_t> empty_file::get_eof() {
return 0;
}
tool_return<size_t> empty_file::set_eof(ssize_t new_eof) {
return MacOS::wrPermErr;
}
} // namespace native

View File

@ -1,88 +0,0 @@
#ifndef __native_file_h__
#define __native_file_h__
#include <memory>
#include <string>
#include <stddef.h>
#include <sys/types.h>
#include <macos/tool_return.h>
#ifdef _WIN32
typedef long ssize_t;
#endif
namespace native {
using MacOS::tool_return;
class file {
public:
int refcount = 1;
bool text = false;
bool resource = false;
std::string filename;
virtual ~file() = default;
virtual tool_return<size_t> read(void *out_buffer, size_t count) = 0;
virtual tool_return<size_t> write(const void *in_buffer, size_t count) = 0;
virtual tool_return<size_t> seek(ssize_t position, int whence);
virtual tool_return<size_t> get_mark() = 0;
virtual tool_return<size_t> set_mark(ssize_t new_mark) = 0;
virtual tool_return<size_t> get_eof() = 0;
virtual tool_return<size_t> set_eof(ssize_t new_eof) = 0;
virtual bool interactive();
protected:
file() = default;
file(const std::string &s) : filename(s)
{}
file(std::string &&s) : filename(std::move(s))
{}
};
class fd_file final : public file {
public:
fd_file(const std::string &s, int fd);
virtual ~fd_file();
virtual tool_return<size_t> read(void *out_buffer, size_t count) override;
virtual tool_return<size_t> write(const void *in_buffer, size_t count) override;
virtual tool_return<size_t> seek(ssize_t position, int whence) override;
virtual tool_return<size_t> get_mark() override;
virtual tool_return<size_t> set_mark(ssize_t new_mark) override;
virtual tool_return<size_t> get_eof() override;
virtual tool_return<size_t> set_eof(ssize_t new_eof) override;
virtual bool interactive() override;
private:
int _fd;
bool _interactive = false;
};
/* empty, read-only pseudo file (for empty resource forks?) */
class empty_file final : public file {
public:
empty_file(const std::string &s) : file(s) {}
virtual tool_return<size_t> read(void *out_buffer, size_t count) override;
virtual tool_return<size_t> write(const void *in_buffer, size_t count) override;
virtual tool_return<size_t> seek(ssize_t position, int whence) override;
virtual tool_return<size_t> get_mark() override;
virtual tool_return<size_t> set_mark(ssize_t new_mark) override;
virtual tool_return<size_t> get_eof() override;
virtual tool_return<size_t> set_eof(ssize_t new_eof) override;
};
typedef std::unique_ptr<file> file_ptr;
}
#endif

View File

@ -1,362 +0,0 @@
/*
* Copyright (c) 2016, Kelvin W Sherlock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "native_internal.h"
#include <string>
#include <algorithm>
#include <unistd.h>
#include <strings.h>
#include <cctype>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
using namespace MacOS;
namespace {
const long epoch_adjust = 86400 * (365 * (1970 - 1904) + 17); // 17 leap years.
std::string extension(const std::string &s)
{
std::string tmp;
int pos;
pos = s.find_last_of("./:");
if (pos == s.npos) return tmp;
if (s[pos++] != '.') return tmp;
if (pos >= s.length()) return tmp;
tmp = s.substr(pos);
std::transform(tmp.begin(), tmp.end(), tmp.begin(),
[](char c) { return tolower(c); }
);
return tmp;
}
std::string basename(const std::string &s)
{
int pos = s.find_last_of("/:");
if (pos == s.npos) return s;
return s.substr(pos + 1);
}
unsigned tox(unsigned x)
{
if (x >= '0' && x <= '9') return x - '0';
if (x >= 'a' && x <= 'f') return x - 'a' + 10;
if (x >= 'A' && x <= 'F') return x - 'A' + 10;
return 0;
}
}
namespace native {
uint32_t unix_to_mac(time_t t) {
if (!t) return 0;
return t + epoch_adjust;
}
time_t mac_to_unix(uint32_t t) {
if (!t) return 0;
return t - epoch_adjust;
}
void prodos_ftype_out(uint8_t *buffer) {
if (memcmp(buffer + 4, "pdos", 4) == 0) {
// mpw expects 'xx ' where
// xx are the ascii-encode hex value of the file type.
// the hfs fst uses 'p' ftype8 auxtype16
// todo -- but only if auxtype is $0000 ??
if (buffer[0] == 'p' && buffer[2] == 0 && buffer[3] == 0)
{
static char Hex[] = "0123456789ABCDEF";
uint8_t ftype = buffer[1];
buffer[0] = Hex[ftype >> 4];
buffer[1] = Hex[ftype & 0x0f];
buffer[2] = ' ';
buffer[3] = ' ';
}
}
}
void prodos_ftype_in(uint8_t *buffer) {
if (::memcmp(buffer + 2, " pdos", 6) == 0)
{
unsigned a = buffer[0];
unsigned b = buffer[1];
if (isxdigit(a) && isxdigit(b))
{
buffer[0] = 'p';
buffer[1] = (tox(a) << 4) | tox(b);
buffer[2] = 0;
buffer[3] = 0;
}
}
}
void synthesize_finder_info(const std::string &path_name, uint8_t *buffer, bool extended) {
::memset(buffer, 0, extended ? 32 : 16);
/* if it's a text file, call it a text file */
if (is_text_file_internal(path_name)) {
::memcpy(buffer, "TEXTMPS ", 8);
}
}
macos_error get_finder_info(const std::string &path_name, uint32_t &ftype, uint32_t &ctype) {
uint8_t buffer[16];
auto err = get_finder_info(path_name, buffer, false);
if (err) return err;
return noErr;
ftype = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
ctype = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | (buffer[7] << 0);
}
macos_error set_finder_info(const std::string &path_name, uint32_t ftype, uint32_t ctype) {
uint8_t buffer[32];
memset(buffer, 0, sizeof(buffer));
buffer[0] = ftype >> 24;
buffer[1] = ftype >> 16;
buffer[2] = ftype >> 8;
buffer[3] = ftype >> 0;
buffer[4] = ctype >> 24;
buffer[5] = ctype >> 16;
buffer[6] = ctype >> 8;
buffer[7] = ctype >> 0;
return set_finder_info(path_name, buffer, true);
}
bool is_text_file_internal(const std::string &path_name) {
std::string ext = extension(path_name);
if (ext.empty()) return false;
char c = ext[0];
switch(c)
{
case 'a':
if (ext == "aii") // assembler
return true;
if (ext == "asm")
return true;
break;
case 'c':
if (ext == "c")
return true;
if (ext == "cpp")
return true;
break;
case 'e':
if (ext == "equ") // asm iigs include file.
return true;
if (ext == "equates") // asm iigs include file.
return true;
break;
case 'i':
if (ext == "i") // asmiigs include file
return true;
if (ext == "inc")
return true;
break;
case 'h':
if (ext == "h") // c header
return true;
break;
case 'l':
if (ext == "lst") // asm iigs listing
return true;
break;
case 'm':
if (ext == "macros")
return true;
break;
case 'p':
if (ext == "p") // pascal
return true;
if (ext == "pas") // pascal
return true;
if (ext == "pii") // pascal
return true;
break;
case 'r':
if (ext == "r")
return true;
if (ext == "rez")
return true;
if (ext == "rii") // rez
return true;
break;
case 's':
if (ext == "src") // asm equates
return true;
break;
}
// check for e16.xxxx or m16.xxxx
ext = basename(path_name);
if (ext.length() > 4)
{
switch (ext[0])
{
case 'm':
case 'M':
case 'e':
case 'E':
if (!strncmp("16.", ext.c_str() + 1, 3))
return true;
break;
}
}
return false;
}
bool is_binary_file_internal(const std::string &path_name) {
std::string ext = extension(path_name);
if (ext.empty()) return false;
char c = ext[0];
switch(c)
{
case 'l':
if (ext == "lib")
return true;
break;
case 'n':
// MrC / MrCpp temp file.
if (ext == "n")
return true;
// Newton C++ Tools output
if (ext == "ntkc")
return true;
break;
case 'o':
if (ext == "o")
return true;
if (ext == "obj")
return true;
break;
case 's':
// Newton C++ Intermediate file
if (ext == "sym")
return true;
break;
}
return false;
}
bool is_text_file(const std::string &path_name) {
uint32_t ftype, ctype;
auto err = get_finder_info(path_name, ftype, ctype);
if (!err) return ftype == 'TEXT';
return is_text_file_internal(path_name);
}
bool is_binary_file(const std::string &path_name) {
uint32_t ftype, ctype;
auto err = get_finder_info(path_name, ftype, ctype);
if (!err) {
if (ctype == 'pdos') {
// 'Bx '
if ((ftype & 0xf0ff) == 'B\x00 ') return true;
/* really, anything not TEXT is binary... */
if ((ftype & 0xf000) == 'p') return true;
//if (ftype >= 'p\xb1\x00\x00' && ftype <= 'p\xbf\xff\xff') return true;
//if (ftype == 'PSYS' || ftype == 'PS16') return true;
}
if (ftype == 'BINA') return true;
}
return is_binary_file_internal(path_name);
}
tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag) {
if (!fork) {
int fd = ::open(path_name.c_str(), oflag, 0666);
if (fd < 0) return macos_error_from_errno();
return file_ptr(new fd_file(path_name, fd));
}
return open_resource_fork(path_name, oflag);
}
}

View File

@ -1,62 +0,0 @@
#ifndef __native_h__
#define __native_h__
#include <string>
#include <cstdint>
#include <ctime>
#include <macos/errors.h>
#include <macos/tool_return.h>
#include "file.h"
namespace native {
using MacOS::macos_error;
using MacOS::tool_return;
struct file_info {
enum { none, file, directory } type = none;
uint16_t attributes = 0;
uint32_t create_date = 0;
uint32_t modify_date = 0;
uint32_t backup_date = 0;
/* for files */
uint32_t data_logical_size = 0;
uint32_t data_physical_size = 0;
uint32_t resource_logical_size = 0;
uint32_t resource_physical_size = 0;
unsigned char finder_info[32] = {};
/* for directories */
uint32_t entry_count = 0; //
};
macos_error get_file_info(const std::string &path_name, file_info &fi);
macos_error set_file_info(const std::string &path_name, const file_info &fi);
macos_error get_finder_info(const std::string &path_name, void *buffer, bool extended = true);
macos_error get_finder_info(const std::string &path_name, uint32_t &ftype, uint32_t &ctype);
macos_error set_finder_info(const std::string &path_name, const void *buffer, bool extended = true);
macos_error set_finder_info(const std::string &path_name, uint32_t ftype, uint32_t ctype);
uint32_t unix_to_mac(time_t t);
time_t mac_to_unix(uint32_t t);
bool is_text_file(const std::string &path_name);
bool is_binary_file(const std::string &path_name);
tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag);
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag);
}
#endif

View File

@ -1,23 +0,0 @@
#ifndef __native_internal_h__
#define __native_internal_h__
#include <string>
#include <cstdint>
#include "native.h"
namespace native {
/* use filename only */
bool is_text_file_internal(const std::string &path_name);
bool is_binary_file_internal(const std::string &path_name);
void prodos_ftype_in(uint8_t *buffer);
void prodos_ftype_out(uint8_t *buffer);
void synthesize_finder_info(const std::string &path_name, uint8_t *buffer, bool extended);
}
#endif

@ -1 +0,0 @@
Subproject commit a4844c1505644c79c805fb1df23d9b4df4387d33

View File

@ -46,7 +46,7 @@ clean :
# mpw Link $(LDFLAGS) -o $@ $^ $(LIBS)
test_sane: o/nan.o o/test_sane.o
$(MPW) $(MPWFLAGS) Link $(LDFLAGS) -o $@ $^ $(LIBS)
$(MPW) $(MPWFLAGS) Link $(LDFLAGS) -o $@ $^ $(LIBS) {CLibraries}CSANELib.o
% : o/%.o
$(MPW) $(MPWFLAGS) Link $(LDFLAGS) -o $@ $^ $(LIBS)

View File

@ -253,6 +253,104 @@ void test_fxc2dec(void)
dump_decimal(&d);
// s/b -4 0
df.style = 1;
df.digits = 6;
num2dec(&df, 0.0625, &d);
dump_decimal(&d);
// s/b -6 62500
df.style = 1;
df.digits = 6;
num2dec(&df, 1.125, &d);
dump_decimal(&d);
// s/b -6 1125000
df.style = 1;
df.digits = 6;
num2dec(&df, 1.0625, &d);
dump_decimal(&d);
// s/b -6 1062500
}
pascal void fp68k_3(void *, void *, unsigned short) = 0xA9EB;
void test_fx2l(void) {
long double x;
long int l;
int i;
static long double data[] = {
1.25,
1.5,
1.75,
2.25,
2.5,
2.75,
-1.25,
-1.5,
-1.75,
-2.25,
-2.5,
-2.75,
};
x = inf(); // 1.0 / 0.0;
fp68k_3(&x, &l, 0x2810);
printf("fx2l(inf) = %lx\n", l);
x = -inf(); // -1.0 / 0.0;
fp68k_3(&x, &l, 0x2810);
printf("fx2l(-inf) = %lx\n", l);
x = nan(1); // -1.0 / 0.0;
fp68k_3(&x, &l, 0x2810);
printf("fx2l(nan) = %lx\n", l);
x = 1e21;
fp68k_3(&x, &l, 0x2810);
printf("fx2l(1e21) = %lx\n", l);
x = -1e21;
fp68k_3(&x, &l, 0x2810);
printf("fx2l(-1e21) = %lx\n", l);
setround(UPWARD);
for (i = 0; i < 12; ++i) {
x = data[i];
fp68k_3(&x, &l, 0x2810);
printf("fx2l(%f) = %ld\n", x, l);
}
setround(DOWNWARD);
for (i = 0; i < 12; ++i) {
x = data[i];
fp68k_3(&x, &l, 0x2810);
printf("fx2l(%f) = %ld\n", x, l);
}
setround(TONEAREST);
for (i = 0; i < 12; ++i) {
x = data[i];
fp68k_3(&x, &l, 0x2810);
printf("fx2l(%f) = %ld\n", x, l);
}
setround(TOWARDZERO);
for (i = 0; i < 12; ++i) {
x = data[i];
fp68k_3(&x, &l, 0x2810);
printf("fx2l(%f) = %ld\n", x, l);
}
}
int main(int argc, char **argv)
@ -276,6 +374,7 @@ int main(int argc, char **argv)
test_nan();
test_fxc2dec();
test_fx2l();
return 0;
}

View File

@ -1,11 +1,16 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# Clang or AppleClang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
endif()
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
set(TOOLBOX_SRC
toolbox.cpp
mm.cpp
loader.cpp
# rm.cpp
rm-new.cpp
rm.cpp
os.cpp
os_alias.cpp
os_fileinfo.cpp
@ -17,7 +22,6 @@ set(TOOLBOX_SRC
os_volume.cpp
qd.cpp
sane.cpp
saneparser.cpp
packages.cpp
pathnames.cpp
process.cpp
@ -25,29 +29,24 @@ set(TOOLBOX_SRC
fs_spec.cpp
realpath.c
dispatch.cpp
floating_point.cpp
fpinfo.cpp
debug.cpp
)
add_custom_command(
OUTPUT saneparser.cpp
COMMAND ragel -p -G2 -o saneparser.cpp "${CMAKE_CURRENT_SOURCE_DIR}/saneparser.rl"
MAIN_DEPENDENCY saneparser.rl
)
add_custom_command(
OUTPUT pathnames.cpp
COMMAND ragel -p -G2 -o pathnames.cpp "${CMAKE_CURRENT_SOURCE_DIR}/pathnames.rl"
COMMAND "${RAGEL}" -p -G2 -o pathnames.cpp "${CMAKE_CURRENT_SOURCE_DIR}/pathnames.rl"
MAIN_DEPENDENCY pathnames.rl
)
set_source_files_properties(
saneparser.cpp pathnames.cpp
pathnames.cpp
PROPERTIES
COMPILE_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-unused-variable"
)
add_library(TOOLBOX_LIB ${TOOLBOX_SRC})
target_link_libraries(TOOLBOX_LIB MACOS_LIB NATIVE_LIB)
target_link_libraries(TOOLBOX_LIB MACOS_LIB sane)

View File

@ -42,6 +42,7 @@
#include "mm.h"
#include "os.h"
#include "packages.h"
#include "process.h"
#include "qd.h"
#include "rm.h"
#include "sane.h"
@ -54,11 +55,8 @@
#include <macos/errors.h>
#include <macos/traps.h>
#include <config.h>
#include <include/endian.h>
// yuck. TST.W d0
extern "C" void cpuSetFlagsNZ00NewW(UWO res);
extern "C" void cpuSetFlagsNZ00NewW(uint16_t res);
namespace {
@ -102,6 +100,20 @@ namespace {
return trap & 0x0600;
}
#if BYTE_ORDER == LITTLE_ENDIAN
inline constexpr uint16_t host_to_big_endian_16(uint16_t x)
{
return __builtin_bswap16(x);
}
#endif
#if BYTE_ORDER == BIG_ENDIAN
inline constexpr uint16_t host_to_big_endian_16(uint16_t x)
{
return x;
}
#endif
}
namespace OS {
@ -318,6 +330,11 @@ namespace OS {
case 0x0020:
return MM::TempDisposeHandle();
case 0x0037:
return Process::GetCurrentProcess();
case 0x003a:
return Process::GetProcessInformation();
default:
fprintf(stderr, "OSDispatch: selector %04x not implemented\n",
@ -339,20 +356,19 @@ namespace ToolBox {
// alternate entry code
auto tmp = MM::Native::NewPtr(1024 * 4 + 256 * 4, false);
ToolGlue = tmp.value();
MM::Native::NewPtr(1024 * 4 + 256 * 4, false, ToolGlue);
OSGlue = ToolGlue + 1024 * 4;
uint16_t *code = (uint16_t *)memoryPointer(ToolGlue);
for (unsigned i = 0; i < 1024; ++i) {
*code++ = htobe16(0xafff);
*code++ = htobe16(0xa800 | i);
*code++ = host_to_big_endian_16(0xafff);
*code++ = host_to_big_endian_16(0xa800 | i);
}
for (unsigned i = 0; i < 256; ++i) {
*code++ = htobe16(0xafff);
*code++ = htobe16(0xa000 | i);
*code++ = host_to_big_endian_16(0xafff);
*code++ = host_to_big_endian_16(0xa000 | i);
}
// os return code... pull registers, TST.W d0, etc.
@ -489,7 +505,7 @@ namespace ToolBox {
*/
Push<4>(returnPC == 0 ? cpuGetPC() : returnPC);
Log("$04x *%s - $%08x", trap, TrapName(trap), address);
Log("$04x *%s - $%08x\n", trap, TrapName(trap), address);
cpuInitializeFromNewPC(address);
return;
}
@ -819,6 +835,15 @@ namespace ToolBox {
d0 = OS::CmpString(trap);
break;
//_RelString [MARKS,CASE]
case 0xa050:
case 0xa250:
case 0xa450:
case 0xa650:
d0 = OS::RelString(trap);
break;
// NewPtr [Sys, Clear] (logicalSize: Size): Ptr;
case 0xa11e:
case 0xa31e:
@ -1085,6 +1110,10 @@ namespace ToolBox {
d0 = OS::OSDispatch(trap);
break;
case 0xa8b5:
d0 = Packages::ScriptUtil(trap);
break;
case 0xABFF:
d0 = Debug::DebugStr(trap);
break;

View File

@ -1,249 +0,0 @@
#include "floating_point.h"
#include <cstdint>
namespace floating_point {
void info::read_single(const void *vp) {
uint32_t i;
std::memcpy(&i, vp, 4);
sign = i >> 31;
one = 1;
exp = (i >> 23) & ((1 << 8) - 1);
sig = i & ((1 << 23) - 1);
if (exp == 255) {
exp = 0;
if (sig == 0) inf = true;
else {
nan = true;
sig &= ~(UINT64_C(1) << 22);
}
return;
}
if (exp == 0 && sig != 0) {
// denormalized.
one = 0;
sig <<= 40; //?
exp = -126;
return;
}
if (exp) exp -= 127; // bias
// adjust to 64 bit significand.
sig <<= 40;
if (one) sig |= (UINT64_C(1) << 63);
}
void info::read_double(const void *vp) {
uint64_t i;
std::memcpy(&i, vp, 8);
sign = i >> 63;
one = 1;
exp = (i >> 52) & ((1 << 11) - 1);
sig = i & ((UINT64_C(1) << 52) - 1);
if (exp == 2047) {
exp = 0;
if (sig == 0) inf = true;
else {
nan = true;
sig &= ~(UINT64_C(1) << 51);
}
return;
}
if (exp == 0 && sig != 0) {
// denormalized.
one = 0;
sig <<= 10; //?
exp = -1022;
return;
}
if (exp) exp -= 1023; // bias
sig <<= 11;
if (one) sig |= (UINT64_C(1) << 63);
}
void info::read_extended(const void *vp) {
uint64_t i;
uint16_t sexp;
if (endian::native == endian::little) {
std::memcpy(&i, (const uint8_t *)vp, 8);
std::memcpy(&sexp, (const uint8_t *)vp + 8, 2);
} else {
std::memcpy(&sexp, (const uint8_t *)vp, 2);
std::memcpy(&i, (const uint8_t *)vp + 2, 8);
}
sign = (sexp >> 15) & 0x01;
exp = sexp & ((1 << 15) - 1);
one = i >> 63;
sig = i; // includes 1. i & ((UINT64_C(1) << 63) - 1);
if (exp == 32767) {
exp = 0;
sig &= ((UINT64_C(1) << 63) - 1);
if (sig == 0) inf = true;
else {
nan = true;
sig &= ((UINT64_C(1) << 62) - 1);
}
return;
}
#if 0
if (exp == 0 && sig != 0) {
// denormalized.
exp -= 16382;
return;
}
#endif
//
if (exp) exp -= 16383;
}
void info::write_single(void *vp) const {
using namespace single_traits;
uint32_t i = 0;
if (sign) i |= sign_bit;
if (nan) {
// todo -- better signalling vs quiet...
i |= nan_exp;
i |= quiet_nan; // nan bit.
unsigned tmp = sig & 0xff;
if (!tmp) tmp = 1;
i |= tmp;
}
else if (inf || exp > max_exp ) {
i |= nan_exp; // also infinite.
}
else if (exp < min_exp || !one) {
// todo -- could de-normalize here...
// if too small -> 0.
// no need to modify i!
}
else {
// de-normalized numbers handled above (as 0)
uint32_t e = exp + bias;
e <<= significand_bits;
i |= e;
uint32_t s = sig >> (63 - significand_bits);
// and clear 1-bit
s &= significand_mask;
i |= s;
}
std::memcpy(vp, &i, 4);
}
void info::write_double(void *vp) const {
using namespace double_traits;
uint64_t i = 0;
if (sign) i |= sign_bit;
if (nan) {
// todo -- better signalling vs quiet...
i |= nan_exp;
i |= quiet_nan; // nan bit.
unsigned tmp = sig & 0xff;
if (!tmp) tmp = 1;
i |= tmp;
}
else if (inf || exp > max_exp ) {
i |= nan_exp;
}
else if (exp < min_exp || !one) {
// if too small -> 0.
// no need to modify i!
}
else {
// de-normalized numbers handled above (as 0)
uint64_t e = exp + bias;
e <<= significand_bits;
i |= e;
uint64_t s = sig >> (63 - significand_bits);
// and clear 1-bit
s &= significand_mask;
i |= s;
}
std::memcpy(vp, &i, 8);
}
void info::write_extended(void *vp) const {
//...
using namespace extended_traits;
uint64_t i = 0;
uint16_t sexp = 0;
if (sign) sexp |= sign_bit;
if (nan) {
// todo -- better signalling vs quiet...
sexp |= nan_exp;
i |= quiet_nan; // nan bit.
i |= one_bit;
unsigned tmp = sig & 0xff;
if (!tmp) tmp = 1;
i |= tmp;
}
else if (inf || exp > max_exp ) {
sexp |= nan_exp;
i |= one_bit;
}
else if (exp < min_exp || !one) {
// if too small -> 0.
// no need to modify i!
}
else {
// de-normalized numbers handled above (as 0)
uint64_t e = exp + bias;
sexp |= e;
i = sig; // 1-bit already set.
}
uint8_t *cp = (uint8_t *)vp;
if (endian::native == endian::little) {
std::memcpy(cp + 0, &i, 8);
std::memcpy(cp + 8, &sexp, 2);
} else {
std::memcpy(cp + 0, &sexp, 2);
std::memcpy(cp + 2, &i, 8);
}
}
}

View File

@ -1,259 +0,0 @@
#ifndef __floating_point_h__
#define __floating_point_h__
#include <type_traits>
#include <cstdint>
#include <cmath>
#include <cstring>
//#include <inttypes.h>
//#include "endian.h"
enum class endian {
little = 3412,
big = 1234,
native = little
};
namespace floating_point {
template<size_t size>
void reverse_bytes(void *vp) {
char *cp = (char *)vp;
for (size_t i = 0; i < size / 2; ++i)
std::swap(cp[i], cp[size - i - 1]);
}
template<size_t size>
void reverse_bytes_if(void *vp, std::true_type) {
reverse_bytes<size>(vp);
}
template<size_t size>
void reverse_bytes_if(void *vp, std::false_type) {
}
#if 0
enum classification {
zero,
infinite,
quiet_nan,
signaling_nan,
normal,
subnormal
};
#endif
namespace single_traits {
constexpr size_t bias = 127;
constexpr size_t exponent_bits = 8;
constexpr size_t significand_bits = 23;
constexpr int max_exp = 127;
constexpr int min_exp = -127;
constexpr uint32_t significand_mask = ((1 << significand_bits) - 1);
constexpr uint32_t sign_bit = UINT32_C(1) << 31;
constexpr uint32_t nan_exp = UINT32_C(255) << significand_bits;
constexpr uint32_t quiet_nan = UINT32_C(0x02) << (significand_bits - 2);
constexpr uint32_t signaling_nan = UINT32_C(0x01) << (significand_bits - 2);
}
namespace double_traits {
constexpr size_t bias = 1023;
constexpr size_t exponent_bits = 11;
constexpr size_t significand_bits = 52;
constexpr int max_exp = 1023;
constexpr int min_exp = -1023;
constexpr uint64_t significand_mask = ((UINT64_C(1) << significand_bits) - 1);
constexpr uint64_t sign_bit = UINT64_C(1) << 63;
constexpr uint64_t nan_exp = UINT64_C(2047) << significand_bits;
constexpr uint64_t quiet_nan = UINT64_C(0x02) << (significand_bits - 2);
constexpr uint64_t signaling_nan = UINT64_C(0x01) << (significand_bits - 2);
}
namespace extended_traits {
constexpr size_t bias = 16383;
constexpr size_t exponent_bits = 15;
constexpr size_t significand_bits = 63; // does not include explicit 1.
constexpr int max_exp = 16383;
constexpr int min_exp = -16383;
constexpr uint64_t significand_mask = ((UINT64_C(1) << significand_bits) - 1);
constexpr uint64_t quiet_nan = UINT64_C(0x02) << (significand_bits - 2);
constexpr uint64_t signaling_nan = UINT64_C(0x01) << (significand_bits - 2);
constexpr uint64_t one_bit = UINT64_C(0x8000000000000000);
// stored separately.
constexpr uint16_t sign_bit = 0x8000;
constexpr uint16_t nan_exp = 0x7fff;
}
template<size_t _size, endian _byte_order>
struct format {
static constexpr size_t size = _size;
static constexpr endian byte_order = _byte_order;
};
class info {
private:
void read_single(const void *);
void read_double(const void *);
void read_extended(const void *);
void write_single(void *) const;
void write_double(void *) const;
void write_extended(void *) const;
public:
bool sign = false;
bool one = false;
int exp = 0;
uint64_t sig = 0; // includes explicit 1 bit, adjusted to 63 bits of fraction.
bool nan = false;
bool inf = false;
//classification type = zero;
template<class T, typename = std::enable_if<std::is_floating_point<T>::value> >
void read(T x)
{ read(format<sizeof(x), endian::native>{}, &x); }
template<size_t size, endian byte_order>
void read(format<size, byte_order>, const void *vp) {
uint8_t buffer[size];
static_assert(byte_order != endian::native, "byte order");
std::memcpy(buffer, vp, size);
reverse_bytes<size>(buffer);
read(format<size, endian::native>{}, buffer);
}
void read(format<4, endian::native>, const void *vp) {
read_single(vp);
}
void read(format<8, endian::native>, const void *vp) {
read_double(vp);
}
void read(format<10, endian::native>, const void *vp) {
read_extended(vp);
}
void read(format<12, endian::native>, const void *vp) {
read_extended(vp);
}
void read(format<16, endian::native>, const void *vp) {
read_extended(vp);
}
template<class T, typename = std::enable_if<std::is_floating_point<T>::value> >
void write(T &x) const
{ write(format<sizeof(x), endian::native>{}, &x); }
template<size_t size, endian byte_order>
void write(format<size, byte_order>, void *vp) const {
uint8_t buffer[size];
static_assert(byte_order != endian::native, "byte order");
write(format<size, endian::native>{}, buffer);
reverse_bytes<size>(buffer);
std::memcpy(vp, buffer, size);
}
void write(format<4, endian::native>, void *vp) const {
write_single(vp);
}
void write(format<8, endian::native>, void *vp) const {
write_double(vp);
}
void write(format<10, endian::native>, void *vp) const {
write_extended(vp);
}
void write(format<12, endian::native>, void *vp) const {
write_extended(vp);
std::memset((uint8_t *)vp + 10, 0, 12-10);
}
void write(format<16, endian::native>, void *vp) const {
write_extended(vp);
std::memset((uint8_t *)vp + 10, 0, 16-10);
}
template<class T, typename = std::enable_if<std::is_floating_point<T>::value> >
info(T x) { read(x); }
info() = default;
};
/*
std::string to_string(const info &fpi)
{
}
*/
inline int fpclassify(const info &fpi) {
if (fpi.nan) return FP_NAN;
if (fpi.inf) return FP_INFINITE;
if (fpi.sig == 0) return FP_ZERO;
return fpi.sig >> 63 ? FP_NORMAL : FP_SUBNORMAL;
}
inline int signbit(const info &fpi) {
return fpi.sign;
}
inline int isnan(const info &fpi) {
return fpi.nan;
}
inline int isinf(const info &fpi) {
return fpi.inf;
}
inline int isfinite(const info &fpi) {
if (fpi.nan || fpi.inf) return false;
return true;
}
inline int isnormal(const info &fpi) {
if (fpi.nan || fpi.inf) return false;
return fpi.sig >> 63;
}
}
#endif

View File

@ -1,160 +1,12 @@
#include "fpinfo.h"
#include <config.h>
#include <include/endian.h>
#include <machine/endian.h>
static_assert(sizeof(float) == 4, "Unexpected float size");
static_assert(sizeof(double) == 8, "Unexpected double size");
static_assert(sizeof(long double) == 8 || sizeof(long double) == 12 || sizeof(long double) == 16, "Unexpected long double size");
static_assert(sizeof(long double) == 8 || sizeof(long double) == 16, "Unexpected long double size");
namespace {
template<int size>
void init(const void *vp, fpinfo &info);
// 32-bit float
template<>
void init<4>(const void *vp, fpinfo &info) {
uint32_t i = *(uint32_t *)vp;
info.sign = i >> 31;
info.one = 1;
info.exp = (i >> 23) & ((1 << 8) - 1);
info.sig = i & ((1 << 24) - 1);
if (info.exp == 255) {
if (info.sig == 0) info.inf = true;
else info.nan = true;
return;
}
if (info.exp == 0) {
// 0 or denormalized.
info.one = 0;
info.exp = -126;
return;
}
info.exp -= 127; // bias
}
// 64-bit double or long double.
template<>
void init<8>(const void *vp, fpinfo &info) {
uint64_t i = *(uint64_t *)vp;
info.sign = i >> 63;
info.one = 1;
info.exp = (i >> 52) & ((1 << 11) - 1);
info.sig = i & ((UINT64_C(1) << 53) - 1);
if (info.exp == 2047) {
if (info.sig == 0) info.inf = true;
else info.nan = true;
return;
}
if (info.exp == 0) {
// 0 or denormalized.
info.one = 0;
info.exp = -1022;
return;
}
info.exp -= 1023; // bias
}
/* solaris - 96-bit long double. */
template<>
void init<12>(const void *vp, fpinfo &info) {
uint64_t i;
uint32_t sexp;
// this needs to be verified.
#if BYTE_ORDER == LITTLE_ENDIAN
i = ((uint64_t *)vp)[0];
sexp = ((uint32_t *)vp)[2] & 0xffff;
#else
#error "please verify big-endian long double format."
sexp = *((uint32_t *)vp) & 0xffff;
i = *((uint64_t *)((uint8_t *)vp+4);
#endif
info.sign = (sexp >> 15) & 0x01;
info.exp = sexp & ((1 << 15) - 1);
info.one = i >> 63;
info.sig = i & ((UINT64_C(1) << 63) - 1);
if (info.exp == 32767) {
if (info.sig == 0) info.inf = true;
else info.nan = true;
return;
}
//
info.exp -= 16383;
}
/* 128-bit long double. same format as 96 but extra padding */
template<>
void init<16>(const void *vp, fpinfo &info) {
uint64_t i;
uint32_t sexp;
// this needs to be verified.
#if BYTE_ORDER == LITTLE_ENDIAN
i = ((uint64_t *)vp)[0];
sexp = ((uint32_t *)vp)[2] & 0xffff;
#else
#error "please verify big-endian long double format."
i = ((uint64_t *)vp)[1];
sexp = ((uint64_t *)vp)[0] & 0xffff;
#endif
info.sign = (sexp >> 15) & 0x01;
info.exp = sexp & ((1 << 15) - 1);
info.one = i >> 63;
info.sig = i & ((UINT64_C(1) << 63) - 1);
if (info.exp == 32767) {
if (info.sig == 0) info.inf = true;
else info.nan = true;
return;
}
//
info.exp -= 16383;
}
}
fpinfo::fpinfo(const float &f) {
init<sizeof(f)>(&f, *this);
}
fpinfo::fpinfo(const double &d) {
init<sizeof(d)>(&d, *this);
}
fpinfo::fpinfo(const long double &ld) {
init<sizeof(ld)>(&ld, *this);
}
#if 0
void fpinfo::init(float *f)
{
union split {
@ -251,6 +103,4 @@ void fpinfo::init(long double *ld)
//
exp -= 16383;
}
#endif
}

View File

@ -4,16 +4,6 @@
#include <cstdint>
struct fpinfo {
private:
/*
void init(float *);
void init(double *);
void init(long double *);
*/
public:
bool sign = false;
bool one = false;
int exp = 0;
@ -22,9 +12,17 @@ public:
bool nan = false;
bool inf = false;
fpinfo(const float &f);
fpinfo(const double &d);
fpinfo(const long double &ld);
fpinfo(float f) { init(&f); }
fpinfo(double d) { init(&d); }
fpinfo(long double ld) {
if (sizeof(long double) == 16) init(&ld);
if (sizeof(long double) == 8) init((double *)&ld);
}
private:
void init(float *);
void init(double *);
void init(long double *);
};

View File

@ -2,11 +2,8 @@
#include <algorithm>
#include <cassert>
#include <filesystem>
namespace fs = std::experimental::filesystem;
#include <unistd.h>
#include <sys/param.h>
namespace OS {
@ -34,12 +31,13 @@ namespace OS {
int32_t FSSpecManager::IDForCWD()
{
char buffer[MAXPATHLEN];
char *cp;
std::error_code ec;
fs::path p = fs::current_path(ec);
if (ec) return 0;
cp = getcwd(buffer, sizeof(buffer));
if (cp == 0) return 0;
std::string path(p.generic_u8string());
std::string path(cp);
return FSSpecManager::IDForPath(std::move(path), true);
}

View File

@ -26,11 +26,12 @@
#include <string>
#include <cstring>
#include <cassert>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <CoreServices/CoreServices.h>
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
#include <cpu/fmem.h>
@ -43,19 +44,6 @@
#include "mm.h"
#include <macos/sysequ.h>
#include <macos/tool_return.h>
using MacOS::tool_return;
enum {
fsCurPerm = 0x00, /* open access permissions in ioPermssn */
fsRdPerm = 0x01,
fsWrPerm = 0x02,
fsRdWrPerm = 0x03,
fsRdWrShPerm = 0x04,
fsRdDenyPerm = 0x10, /* for use with OpenDeny and OpenRFDeny */
fsWrDenyPerm = 0x20 /* for use with OpenDeny and OpenRFDeny */
};
using ToolBox::Log;
@ -158,26 +146,23 @@ namespace Loader {
// load code seg 0.
tool_return<void> LoadCode0(Segment0Info &rv)
uint16_t LoadCode0(Segment0Info &rv)
{
uint16_t err;
uint32_t rHandle;
uint32_t size;
uint32_t address;
SegmentInfo si;
{
auto tmp = RM::Native::GetResource(kCODE, 0);
if (tmp.error()) return tmp.error();
rHandle = tmp.value();
}
err = RM::Native::GetResource(kCODE, 0, rHandle);
if (err) return err;
MM::Native::HLock(rHandle);
{
auto tmp = MM::Native::GetHandleInfo(rHandle);
address = tmp.value().address;
size = tmp.value().size;
}
MM::Native::GetHandleSize(rHandle, size);
address = memoryReadLong(rHandle);
uint32_t above = memoryReadLong(address);
uint32_t below = memoryReadLong(address + 4);
@ -188,12 +173,8 @@ namespace Loader {
// create a new handle for the a5 segment.
{
auto tmp = MM::Native::NewHandle(si.size, true);
if (tmp.error()) return tmp.error();
si.handle = tmp.value().handle;
si.address = tmp.value().pointer;
}
err = MM::Native::NewHandle(si.size, true, si.handle, si.address);
if (err) return err;
MM::Native::HLock(si.handle);
@ -211,27 +192,23 @@ namespace Loader {
rv.jtEnd = rv.jtStart + rv.jtSize;
// TODO -- should ReleaseResource on rHandle.
return MacOS::noErr;
return 0;
}
// load a standard code segment.
tool_return<void> LoadCode(uint16_t segment)
uint16_t LoadCode(uint16_t segment)
{
uint16_t err;
SegmentInfo si;
{
auto tmp = RM::Native::GetResource(kCODE, segment);
if (tmp.error()) return tmp.error();
si.handle = tmp.value();
}
MM::Native::HLock(si.handle);
err = RM::Native::GetResource(kCODE, segment, si.handle);
if (err) return err;
{
auto tmp = MM::Native::GetHandleInfo(si.handle);
si.size = tmp.value().size;
si.address = tmp.value().address;
}
MM::Native::HLock(si.handle);
MM::Native::GetHandleSize(si.handle, si.size);
si.address = memoryReadLong(si.handle);
if (memoryReadWord(si.address) == 0xffff)
si.farModel = true;
@ -241,7 +218,7 @@ namespace Loader {
Segments[segment] = si;
return MacOS::noErr;
return 0;
}
@ -250,17 +227,35 @@ namespace Loader {
namespace Native
{
tool_return<void> LoadFile(const std::string &path)
uint16_t LoadFile(const std::string &path)
{
tool_return<void> err;
HFSUniStr255 fork = {0,{0}};
ResFileRefNum refNum;
FSRef ref;
OSErr err;
// open the file
// load code seg 0
// iterate and load other segments
auto tmp = RM::Native::OpenResFile(path, fsRdPerm);
if (tmp.error()) return tmp.error();
// TODO -- call RM::Native::OpenResourceFile(...);
err = FSPathMakeRef( (const UInt8 *)path.c_str(), &ref, NULL);
if (err) return err;
::FSGetResourceForkName(&fork);
err = ::FSOpenResourceFile(&ref,
fork.length,
fork.unicode,
fsRdPerm,
&refNum);
if (err) return err;
// in case of restart?
Segments.clear();
@ -270,7 +265,6 @@ namespace Loader {
// load code 0.
Segment0Info seg0;
err = LoadCode0(seg0);
if (!err) return err;
// iterate through the jump table to get the other
// code segments to load
@ -308,7 +302,7 @@ namespace Loader {
if (seg >= Segments.size() || Segments[seg].address == 0)
{
err = LoadCode(seg);
if (!err) return err;
if (err) return err;
const auto &p = Segments[seg];
if (p.farModel)
@ -349,7 +343,7 @@ namespace Loader {
{
std::string s;
auto ix = path.find_last_of("/:", 0, 2);
auto ix = path.rfind('/');
if (ix == path.npos)
{
s = path.substr(0, 31);
@ -364,7 +358,7 @@ namespace Loader {
return MacOS::noErr;
return 0;
}
@ -558,35 +552,5 @@ namespace Loader {
}
uint16_t LoadSeg(uint16_t trap) {
/*
* Jump Table Entry:
*
* Unloaded:
* +0 offset
* +2 instruction that pushes segment number onto stack
* +6 LoadSeg trap
*
* Loaded:
* +0 offset
* +2 jump instruction.
*
*/
uint32_t sp;
uint16_t segment;
sp = StackFrame<2>(segment);
Log("%04x LoadSeg(%04x)\n", trap, segment);
return 0;
}
}

View File

@ -6,16 +6,11 @@
#include <cstdint>
#include <macos/tool_return.h>
namespace Loader {
typedef std::map<std::string, std::pair<uint32_t, uint32_t>> DebugNameTable;
namespace Native {
using MacOS::tool_return;
/*
* loads the file
* sets registers PC and A5.
@ -23,7 +18,7 @@ namespace Loader {
*
* Dependencies: MM, RM
*/
tool_return<void> LoadFile(const std::string &path);
uint16_t LoadFile(const std::string &path);
// scans segments for MacsBug debug names.
// associates them with the start of the segment.
@ -31,7 +26,6 @@ namespace Loader {
}
uint16_t LoadSeg(uint16_t trap);
uint16_t UnloadSeg(uint16_t trap);
}

View File

@ -45,9 +45,6 @@
using ToolBox::Log;
using MacOS::tool_return;
using MacOS::macos_error_from_errno;
using MacOS::macos_error;
namespace
{
@ -68,15 +65,15 @@ namespace
// map of handle -> size [? just use Ptr map?]
std::map<uint32_t, MM::HandleInfo> HandleMap;
inline macos_error SetMemError(macos_error error)
inline MacOS::macos_error SetMemError(MacOS::macos_error error)
{
memoryWriteWord(error, MacOS::MemErr);
return error;
}
inline macos_error SetMemError(int16_t error)
inline MacOS::macos_error SetMemError(int16_t error)
{
return SetMemError((macos_error)error);
return SetMemError((MacOS::macos_error)error);
}
@ -101,46 +98,18 @@ namespace
}
template<class Fx>
int16_t with_handle(uint32_t handle, Fx fx)
{
auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return MacOS::memWZErr;
return fx(iter->second);
}
}
namespace MM
{
using MacOS::tool_return_type;
template<class T, class FRT, class F>
T with_handle_helper(F &&f, HandleInfo &info, typename std::enable_if<!std::is_void<FRT>::value>::type* = 0) {
T rv = f(info);
return rv;
}
template<class T, class FRT, class F>
T with_handle_helper(F &&f, HandleInfo &info, typename std::enable_if<std::is_void<FRT>::value>::type* = 0) {
f(info);
return tool_return<void>();
}
template<class F,
typename FRT = typename std::result_of<F(HandleInfo &)>::type, // function return type
typename TRT = typename tool_return_type<FRT>::type> // tool return type.
TRT __with_handle(uint32_t handle, F &&f)
{
if (handle == 0) return SetMemError(MacOS::nilHandleErr);
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
TRT rv = with_handle_helper<TRT, FRT>(std::forward<F>(f), info);
SetMemError(rv.error());
return rv;
}
bool Init(uint8_t *memory, uint32_t memorySize, uint32_t globals, uint32_t stack)
{
int ok;
@ -170,8 +139,6 @@ namespace MM
namespace Native {
// debugger support.
// print info on an address.
void MemoryInfo(uint32_t address)
@ -187,7 +154,7 @@ namespace MM
}
// 2. check if it's contained in a pointer
for (const auto kv : PtrMap)
for (const auto &kv : PtrMap)
{
if (address < kv.first) continue;
if (address >= kv.first + kv.second) continue;
@ -217,7 +184,7 @@ namespace MM
// 3. check if the address is within a handle.
{
for (const auto kv : HandleMap)
for (const auto &kv : HandleMap)
{
const HandleInfo &info = kv.second;
@ -266,11 +233,11 @@ namespace MM
}
tool_return<uint32_t> NewPtr(uint32_t size, bool clear)
uint16_t NewPtr(uint32_t size, bool clear, uint32_t &mcptr)
{
// native pointers.
uint32_t mcptr = 0;
mcptr = 0;
//if (size == 0) return 0;
uint8_t *ptr = nullptr;
@ -286,11 +253,10 @@ namespace MM
mcptr = ptr - Memory;
PtrMap.emplace(std::make_pair(mcptr, size));
SetMemError(0);
return mcptr;
return SetMemError(0);
}
tool_return<void> DisposePtr(uint32_t mcptr)
uint16_t DisposePtr(uint32_t mcptr)
{
auto iter = PtrMap.find(mcptr);
@ -305,34 +271,13 @@ namespace MM
return SetMemError(0);
}
/* create a NULL handle (for resource manager) */
tool_return<uint32_t> NewEmptyHandle()
{
uint32_t hh;
if (!HandleQueue.size())
{
if (!alloc_handle_block())
{
return SetMemError(MacOS::memFullErr);
}
}
hh = HandleQueue.front();
HandleQueue.pop_front();
HandleMap.emplace(std::make_pair(hh, HandleInfo(0, 0)));
memoryWriteLong(0, hh);
return hh;
}
tool_return<hp> NewHandle(uint32_t size, bool clear)
uint16_t NewHandle(uint32_t size, bool clear, uint32_t &handle, uint32_t &mcptr)
{
uint8_t *ptr;
uint32_t hh;
uint32_t handle = 0;
uint32_t mcptr = 0;
handle = 0;
mcptr = 0;
if (!HandleQueue.size())
{
@ -345,68 +290,44 @@ namespace MM
hh = HandleQueue.front();
HandleQueue.pop_front();
ptr = (uint8_t *)mplite_malloc(&pool, size ? size : 1);
if (!ptr)
{
HandleQueue.push_back(hh);
return SetMemError(MacOS::memFullErr);
}
mcptr = ptr - Memory;
ptr = nullptr;
if (clear)
std::memset(ptr, 0, size);
// todo -- size 0 should have a ptr to differentiate
// from purged.
// PPCLink calls NewHandle(0) but expects a valid pointer
// Assertion failed: *fHandle != NULL
//if (size)
//{
ptr = (uint8_t *)mplite_malloc(&pool, size ? size : 1);
if (!ptr)
{
HandleQueue.push_back(hh);
return SetMemError(MacOS::memFullErr);
}
mcptr = ptr - Memory;
if (clear)
std::memset(ptr, 0, size);
//}
// need a handle -> ptr map?
HandleMap.emplace(std::make_pair(hh, HandleInfo(mcptr, size)));
memoryWriteLong(mcptr, hh);
handle = hh;
SetMemError(0);
return hp{handle, mcptr};
return SetMemError(0);
}
tool_return<hp> NewHandleWithAttr(uint32_t size, unsigned attr)
uint16_t NewHandle(uint32_t size, bool clear, uint32_t &handle)
{
uint8_t *ptr;
uint32_t hh;
uint32_t handle = 0;
uint32_t mcptr = 0;
if (!HandleQueue.size())
{
if (!alloc_handle_block())
{
return SetMemError(MacOS::memFullErr);
}
}
hh = HandleQueue.front();
HandleQueue.pop_front();
ptr = (uint8_t *)mplite_malloc(&pool, size ? size : 1);
if (!ptr)
{
HandleQueue.push_back(hh);
return SetMemError(MacOS::memFullErr);
}
mcptr = ptr - Memory;
// always clear it.
std::memset(ptr, 0, size);
// need a handle -> ptr map?
HandleMap.emplace(std::make_pair(hh, HandleInfo(mcptr, size, attr)));
memoryWriteLong(mcptr, hh);
handle = hh;
SetMemError(0);
return hp{handle, mcptr};
uint32_t ptr;
return NewHandle(size, clear, handle, ptr);
}
tool_return<void> DisposeHandle(uint32_t handle)
uint16_t DisposeHandle(uint32_t handle)
{
auto iter = HandleMap.find(handle);
@ -428,11 +349,20 @@ namespace MM
}
tool_return<uint32_t> ReallocHandle(uint32_t handle, uint32_t logicalSize)
uint16_t GetHandleSize(uint32_t handle, uint32_t &handleSize)
{
handleSize = 0;
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
handleSize = iter->second.size;
return SetMemError(0);
}
uint16_t ReallocHandle(uint32_t handle, uint32_t logicalSize)
{
if (handle == 0) return SetMemError(MacOS::nilHandleErr);
auto iter = HandleMap.find(handle);
@ -442,15 +372,18 @@ namespace MM
if (info.locked) return SetMemError(MacOS::memLockedErr);
uint32_t mcptr = 0;
// todo -- purge & retry on failure.
if (logicalSize)
{
// todo -- purge & retry on failure.
void *address = mplite_malloc(&pool, logicalSize ? logicalSize : 1);
if (!address) return SetMemError(MacOS::memFullErr);
void *address = mplite_malloc(&pool, logicalSize);
if (!address) return SetMemError(MacOS::memFullErr);
std::memset(address, 0, logicalSize);
mcptr = (uint8_t *)address - Memory;
mcptr = (uint8_t *)address - Memory;
}
// the handle is not altered in the event of an error.
if (info.address)
@ -463,46 +396,16 @@ namespace MM
info.address = mcptr;
info.size = logicalSize;
// "The new block is unlocked and unpurgeable."
info.locked = false;
info.purgeable = false;
memoryWriteLong(mcptr, handle);
return mcptr;
// lock? clear purged flag?
return 0;
}
/* returns true if memory has been purged. */
bool Purge(uint32_t but_not_this_handle = 0) {
bool rv = false;
for (auto & kv : HandleMap)
{
uint32_t ph = kv.first;
auto &info = kv.second;
if (info.address == 0) continue;
if (ph == but_not_this_handle) continue;
if (info.purgeable && !info.locked)
{
mplite_free(&pool, Memory + info.address);
info.size = 0;
info.address = 0;
// also need to update memory
memoryWriteLong(0, ph);
rv = true;
}
}
return rv;
}
tool_return<uint32_t> SetHandleSize(uint32_t handle, uint32_t newSize)
uint16_t SetHandleSize(uint32_t handle, uint32_t newSize)
{
if (handle == 0) return SetMemError(MacOS::nilHandleErr);
@ -538,9 +441,7 @@ namespace MM
info.size = 0;
memoryWriteLong(info.address, handle);
SetMemError(0);
return info.address;
return SetMemError(0);
}
// 2. - resizing from 0.
@ -557,8 +458,7 @@ namespace MM
info.size = newSize;
memoryWriteLong(info.address, handle);
SetMemError(0);
return info.address;
return SetMemError(0);
}
for (unsigned i = 0; i < 2; ++i)
@ -570,8 +470,7 @@ namespace MM
if (mplite_resize(&pool, ptr, mplite_roundup(&pool, newSize)) == MPLITE_OK)
{
info.size = newSize;
SetMemError(0);
return info.address;
return SetMemError(0);
}
}
else
@ -588,8 +487,7 @@ namespace MM
info.size = newSize;
memoryWriteLong(info.address, handle);
SetMemError(0);
return info.address;
return SetMemError(0);
}
}
@ -597,87 +495,113 @@ namespace MM
fprintf(stderr, "mplite_realloc failed.\n");
Native::PrintMemoryStats();
if (i > 0 || !Purge(handle)) break;
if (i > 0) return SetMemError(MacOS::memFullErr);
// purge...
for (auto & kv : HandleMap)
{
uint32_t ph = kv.first;
auto &info = kv.second;
if (ph == handle) continue;
if (info.size && info.purgeable && !info.locked)
{
mplite_free(&pool, Memory + info.address);
info.size = 0;
info.address = 0;
// also need to update memory
memoryWriteLong(0, ph);
}
}
}
return SetMemError(MacOS::memFullErr);
}
tool_return<void> HSetState(uint32_t handle, uint16_t attr)
// template class to validate handle and work on it.
template<class FX>
uint16_t HandleIt(uint32_t handle, FX fx)
{
return __with_handle(handle, [attr](HandleInfo &info){
info.resource = attr & attrResource;
info.purgeable = attr & attrPurgeable;
info.locked = attr & attrLocked;
});
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
fx(info);
return SetMemError(0);
}
tool_return<uint16_t> HGetState(uint32_t handle)
uint16_t HSetRBit(uint32_t handle)
{
return __with_handle(handle, [](const HandleInfo &info){
uint16_t attr = 0;
if (info.resource) attr |= attrResource;
if (info.purgeable) attr |= attrPurgeable;
if (info.locked) attr |= attrLocked;
return attr;
});
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
info.resource = true;
return SetMemError(0);
}
tool_return<void> HSetRBit(uint32_t handle)
uint16_t HClrRBit(uint32_t handle)
{
return __with_handle(handle, [](HandleInfo &info) { info.resource = true; });
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
info.resource = false;
return SetMemError(0);
}
tool_return<void> HClrRBit(uint32_t handle)
uint16_t HLock(uint32_t handle)
{
return __with_handle(handle, [](HandleInfo &info) { info.resource = false; });
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
info.locked = true;
return SetMemError(0);
}
tool_return<void> HLock(uint32_t handle)
uint16_t HUnlock(uint32_t handle)
{
return __with_handle(handle, [](HandleInfo &info) { info.locked = true; });
}
const auto iter = HandleMap.find(handle);
tool_return<void> HUnlock(uint32_t handle)
{
return __with_handle(handle, [](HandleInfo &info) { info.locked = false; });
}
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
tool_return<uint32_t> GetHandleSize(uint32_t handle)
{
return __with_handle(handle, [](const HandleInfo &info){ return info.size; });
}
tool_return<HandleInfo> GetHandleInfo(uint32_t handle)
{
return __with_handle(handle, [](const HandleInfo &info){ return info; });
auto &info = iter->second;
info.locked = false;
return SetMemError(0);
}
tool_return<void> EmptyHandle(uint32_t handle) {
return __with_handle(handle, [handle](HandleInfo &info) {
if (info.address == 0) return MacOS::noErr;
// "The block whose handle is h must be unlocked but need not be purgeable."
if (info.locked) return MacOS::memPurErr;
void *address = Memory + info.address;
mplite_free(&pool, address);
info.address = 0;
info.size = 0;
memoryWriteLong(0, handle);
return MacOS::noErr;
});
}
}
#pragma mark --
tool_return<uint32_t> GetHandleSize(uint32_t handle)
{
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
SetMemError(0);
return iter->second.size;
}
tool_return<HandleInfo> GetHandleInfo(uint32_t handle)
{
const auto iter = HandleMap.find(handle);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
SetMemError(0);
return iter->second;
}
#pragma mark --
@ -904,10 +828,12 @@ namespace MM
// todo -- separate pools for sys vs non-sys?
// todo -- NewPtr(0) -- null or empty ptr?
auto rv = Native::NewPtr(size, clear);
uint32_t mcptr;
uint16_t error;
error = Native::NewPtr(size, clear, mcptr);
cpuSetAReg(0, rv.value());
return rv.error(); //SetMemError(error);
cpuSetAReg(0, mcptr);
return error; //SetMemError(error);
}
uint16_t DisposePtr(uint16_t trap)
@ -925,7 +851,11 @@ namespace MM
Log("%04x DisposePtr(%08x)\n", trap, mcptr);
return Native::DisposePtr(mcptr).error();
uint16_t error;
error = Native::DisposePtr(mcptr);
return error; //SetMemError(error);
}
uint32_t GetPtrSize(uint16_t trap)
@ -998,6 +928,8 @@ namespace MM
*
*/
uint32_t hh = 0;
uint16_t error;
bool clear = trap & (1 << 9);
//bool sys = trap & (1 << 10);
@ -1006,10 +938,10 @@ namespace MM
Log("%04x NewHandle(%08x)\n", trap, size);
auto rv = Native::NewHandle(size, clear);
error = Native::NewHandle(size, clear, hh);
cpuSetAReg(0, rv.value().handle);
return rv.error();
cpuSetAReg(0, hh);
return error;
}
uint16_t DisposeHandle(uint16_t trap)
@ -1027,7 +959,7 @@ namespace MM
Log("%04x DisposeHandle(%08x)\n", trap, hh);
return Native::DisposeHandle(hh).error();
return Native::DisposeHandle(hh);
}
uint16_t EmptyHandle(uint16_t trap)
@ -1044,7 +976,23 @@ namespace MM
uint32_t hh = cpuGetAReg(0);
Log("%04x EmptyHandle(%08x)\n", trap, hh);
return Native::EmptyHandle(hh).error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
if (info.address == 0) return SetMemError(0);
if (info.locked) return SetMemError(MacOS::memLockedErr); // ?
void *address = Memory + info.address;
mplite_free(&pool, address);
info.address = 0;
info.size = 0;
memoryWriteLong(0, hh);
return 0;
}
/*
@ -1078,7 +1026,45 @@ namespace MM
Log("%04x ReallocHandle(%08x, %08x)\n", trap, hh, logicalSize);
return Native::ReallocHandle(hh, logicalSize).error();
return Native::ReallocHandle(hh, logicalSize);
#if 0
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto& info = iter->second;
if (info.locked) return SetMemError(MacOS::memLockedErr);
if (info.address)
{
void *address = Memory + info.address;
mplite_free(&pool, address);
info.address = 0;
info.size = 0;
memoryWriteLong(0, hh);
}
// allocate a new block...
if (logicalSize == 0) return SetMemError(0);
void *address = mplite_malloc(&pool, logicalSize);
if (!address) return SetMemError(MacOS::memFullErr);
uint32_t mcptr = (uint8_t *)address - Memory;
info.size = logicalSize;
info.address = mcptr;
memoryWriteLong(mcptr, hh);
// lock? clear purged flag?
return 0;
#endif
}
@ -1107,7 +1093,13 @@ namespace MM
Log("%04x GetHandleSize(%08x)\n", trap, hh);
return Native::GetHandleSize(hh).value_or_error();
if (hh == 0) return SetMemError(MacOS::nilHandleErr); // ????
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
return iter->second.size;
}
uint16_t SetHandleSize(uint16_t trap)
@ -1129,7 +1121,7 @@ namespace MM
Log("%04x SetHandleSize(%08x, %08x)\n", trap, hh, newSize);
return Native::SetHandleSize(hh, newSize).error();
return Native::SetHandleSize(hh, newSize);
}
uint32_t RecoverHandle(uint16_t trap)
@ -1153,7 +1145,7 @@ namespace MM
Log("%04x RecoverHandle(%08x)\n", trap, p);
uint16_t error = MacOS::memBCErr;
for (const auto kv : HandleMap)
for (const auto &kv : HandleMap)
{
const HandleInfo &info = kv.second;
@ -1196,7 +1188,31 @@ namespace MM
Log("%04x HGetState(%08x)\n", trap, hh);
return Native::HGetState(hh).value_or_error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
/*
* flag bits:
* 0-4: reserved
* 5: is a resource
* 6: set if purgeable
* 7: set if locked
*/
const auto &info = iter->second;
// resource not yet supported...
// would need extra field and support in RM:: when
// creating.
// see HSetRBit, HClrRBit
if (info.resource) flags |= (1 << 5);
if (info.purgeable) flags |= (1 << 6);
if (info.locked) flags |= (1 << 7);
SetMemError(0);
return flags;
}
uint16_t HSetState(uint16_t trap)
@ -1216,7 +1232,18 @@ namespace MM
Log("%04x HSetState(%08x, %04x)\n", trap, hh, flags);
return Native::HSetState(hh, flags).error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
auto &info = iter->second;
info.resource = (flags & (1 << 5));
info.purgeable = (flags & (1 << 6));
info.locked = (flags & (1 << 7));
return SetMemError(0);
}
uint16_t HPurge(uint16_t trap)
@ -1235,7 +1262,12 @@ namespace MM
Log("%04x HPurge(%08x)\n", trap, hh);
return __with_handle(hh, [](HandleInfo &info){ info.purgeable = true; }).error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
iter->second.purgeable = true;
return SetMemError(0);
}
@ -1255,8 +1287,12 @@ namespace MM
Log("%04x HNoPurge(%08x)\n", trap, hh);
return __with_handle(hh, [](HandleInfo &info){ info.purgeable = false; }).error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
iter->second.purgeable = false;
return SetMemError(0);
}
uint16_t HLock(uint16_t trap)
@ -1274,7 +1310,12 @@ namespace MM
Log("%04x HLock(%08x)\n", trap, hh);
return __with_handle(hh, [](HandleInfo &info){ info.locked = true; }).error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
iter->second.locked = true;
return SetMemError(0);
}
uint16_t HUnlock(uint16_t trap)
@ -1292,8 +1333,12 @@ namespace MM
Log("%04x HUnlock(%08x)\n", trap, hh);
return __with_handle(hh, [](HandleInfo &info){ info.locked = false; }).error();
auto iter = HandleMap.find(hh);
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
iter->second.locked = false;
return SetMemError(0);
}
#pragma mark - OS Utility Routines
@ -1323,15 +1368,16 @@ namespace MM
auto const info = iter->second;
auto rv = Native::NewHandle(info.size, false);
if (!rv.error())
uint32_t destHandle;
uint32_t destPtr;
uint32_t d0 = Native::NewHandle(info.size, false, destHandle, destPtr);
if (d0 == 0)
{
std::memmove(memoryPointer(rv.value().pointer), memoryPointer(info.address), info.size);
std::memmove(memoryPointer(destPtr), memoryPointer(info.address), info.size);
}
cpuSetAReg(0, rv.value().handle);
return rv.error(); // SetMemError called by Native::NewHandle.
cpuSetAReg(0, destHandle);
return d0; // SetMemError called by Native::NewHandle.
}
@ -1353,14 +1399,16 @@ namespace MM
Log("%04x PtrToHand(%08x, %08x)\n", trap, mcptr, size);
auto rv = Native::NewHandle(size, false);
if (!rv.error())
uint32_t destHandle;
uint32_t destPtr;
uint32_t d0 = Native::NewHandle(size, false, destHandle, destPtr);
if (d0 == 0)
{
std::memmove(memoryPointer(rv.value().pointer), memoryPointer(mcptr), size);
std::memmove(memoryPointer(destPtr), memoryPointer(mcptr), size);
}
cpuSetAReg(0, rv.value().handle);
return rv.error(); // SetMemError called by Native::NewHandle.
cpuSetAReg(0, destHandle);
return d0; // SetMemError called by Native::NewHandle.
}
uint16_t PtrAndHand(uint16_t trap)
@ -1387,16 +1435,18 @@ namespace MM
cpuSetAReg(0, handle);
auto tmp = Native::GetHandleSize(handle);
if (tmp.error()) return tmp.error();
uint32_t oldSize = tmp.value();
uint32_t oldSize = 0;
uint32_t d0;
d0 = Native::GetHandleSize(handle, oldSize);
if (d0) return d0;
if ((uint64_t)oldSize + (uint64_t)size > UINT32_MAX)
return SetMemError(MacOS::memFullErr);
auto err = Native::SetHandleSize(handle, oldSize + size);
if (err.error()) return err.error();
d0 = Native::SetHandleSize(handle, oldSize + size);
if (d0) return d0;
auto iter = HandleMap.find(handle);
if (iter == HandleMap.end())
@ -1587,18 +1637,20 @@ namespace MM
{
// FUNCTION TempNewHandle (logicalSize: Size;
// VAR resultCode: OSErr): Handle;
uint16_t rv;
uint32_t logicalSize;
uint32_t resultCode;
uint32_t theHandle;
uint32_t sp = StackFrame<8>(logicalSize, resultCode);
Log(" TempNewHandle(%08x, %08x)\n", logicalSize, resultCode);
auto rv = Native::NewHandle(logicalSize, true);
rv = Native::NewHandle(logicalSize, true, theHandle);
if (resultCode) memoryWriteWord(rv.error(), resultCode);
ToolReturn<4>(sp, rv.value().handle);
return rv.error();
if (resultCode) memoryWriteWord(rv, resultCode);
ToolReturn<4>(sp, theHandle);
return rv;
}
uint16_t TempHLock(void)
@ -1611,10 +1663,10 @@ namespace MM
Log(" TempHLock(%08x, %08x)\n", theHandle, resultCode);
auto rv = Native::HLock(theHandle);
uint16_t rv = Native::HLock(theHandle);
if (resultCode) memoryWriteWord(rv.error(), resultCode);
return rv.error();
if (resultCode) memoryWriteWord(rv, resultCode);
return rv;
}
uint16_t TempHUnlock(void)
@ -1627,10 +1679,10 @@ namespace MM
Log(" TempHUnlock(%08x, %08x)\n", theHandle, resultCode);
auto rv = Native::HUnlock(theHandle);
uint16_t rv = Native::HUnlock(theHandle);
if (resultCode) memoryWriteWord(rv.error(), resultCode);
return rv.error();
if (resultCode) memoryWriteWord(rv, resultCode);
return rv;
}
@ -1644,9 +1696,9 @@ namespace MM
Log(" TempDisposeHandle(%08x, %08x)\n", theHandle, resultCode);
auto rv = Native::DisposeHandle(theHandle);
uint16_t rv = Native::DisposeHandle(theHandle);
if (resultCode) memoryWriteWord(rv.error(), resultCode);
return rv.error();
if (resultCode) memoryWriteWord(rv, resultCode);
return rv;
}
}

View File

@ -5,15 +5,37 @@
#include <macos/tool_return.h>
namespace MM
{
// native functions.
namespace Native
{
void MemoryInfo(uint32_t address);
void PrintMemoryStats();
uint16_t NewHandle(uint32_t size, bool clear, uint32_t &handle);
uint16_t NewHandle(uint32_t size, bool clear, uint32_t &handle, uint32_t &ptr);
uint16_t NewPtr(uint32_t size, bool clear, uint32_t &pointer);
uint16_t DisposeHandle(uint32_t handle);
uint16_t DisposePtr(uint32_t pointer);
uint16_t GetHandleSize(uint32_t handle, uint32_t &handleSize);
uint16_t SetHandleSize(uint32_t handle, uint32_t newSize);
uint16_t ReallocHandle(uint32_t handle, uint32_t newSize);
uint16_t HSetRBit(uint32_t handle);
uint16_t HClrRBit(uint32_t handle);
uint16_t HLock(uint32_t handle);
uint16_t HUnlock(uint32_t handle);
}
bool Init(uint8_t *memory, uint32_t memorySize, uint32_t globals, uint32_t stack);
enum {
attrResource = 1 << 5,
attrPurgeable = 1 << 6,
attrLocked = 1 << 7,
};
struct HandleInfo
{
@ -26,73 +48,13 @@ namespace MM
HandleInfo(uint32_t a = 0, uint32_t s = 0) :
address(a), size(s)
{}
HandleInfo(uint32_t a, uint32_t s, unsigned attr) :
address(a), size(s)
{
resource = attr & attrResource;
purgeable = attr & attrPurgeable;
locked = attr & attrLocked;
}
};
// native functions.
namespace Native
{
using MacOS::tool_return;
struct hp {
uint32_t handle = 0;
uint32_t pointer = 0;
hp() = default;
hp(uint32_t a, uint32_t b) : handle(a), pointer(b) {};
};
void MemoryInfo(uint32_t address);
void PrintMemoryStats();
tool_return<hp> NewHandle(uint32_t size, bool clear);
tool_return<hp> NewHandleWithAttr(uint32_t size, unsigned attr);
tool_return<uint32_t> NewEmptyHandle();
tool_return<uint32_t> NewPtr(uint32_t size, bool clear);
tool_return<void> DisposeHandle(uint32_t handle);
tool_return<void> DisposePtr(uint32_t pointer);
tool_return<uint32_t> GetHandleSize(uint32_t handle);
tool_return<uint32_t> SetHandleSize(uint32_t handle, uint32_t newSize);
tool_return<uint32_t> ReallocHandle(uint32_t handle, uint32_t newSize);
tool_return<void> HSetState(uint32_t handle, uint16_t attr);
tool_return<uint16_t> HGetState(uint32_t handle);
tool_return<void> HSetRBit(uint32_t handle);
tool_return<void> HClrRBit(uint32_t handle);
tool_return<void> HLock(uint32_t handle);
tool_return<void> HUnlock(uint32_t handle);
tool_return<void> EmptyHandle(uint32_t handle);
tool_return<HandleInfo> GetHandleInfo(uint32_t handle);
tool_return<uint32_t> GetHandleSize(uint32_t handle);
}
bool Init(uint8_t *memory, uint32_t memorySize, uint32_t globals, uint32_t stack);
using MacOS::tool_return;
tool_return<HandleInfo> GetHandleInfo(uint32_t handle);
tool_return<uint32_t> GetHandleSize(uint32_t handle);
uint16_t BlockMove(uint16_t trap);

View File

@ -32,17 +32,15 @@
#include <deque>
#include <string>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/paths.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <strings.h>
#include <filesystem>
namespace fs = std::experimental::filesystem;
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
#include <cpu/fmem.h>
@ -51,9 +49,6 @@ namespace fs = std::experimental::filesystem;
#include <macos/errors.h>
#include <macos/traps.h>
#include <native/native.h>
#include <native/file.h>
#include "os.h"
#include "os_internal.h"
#include "toolbox.h"
@ -74,7 +69,7 @@ namespace {
#if 0
std::string extension(const std::string &s)
{
std::string tmp;
@ -102,7 +97,7 @@ namespace {
return s.substr(pos + 1);
}
#endif
}
@ -125,6 +120,184 @@ namespace OS
}
// known text file extensions
bool IsTextFile(const std::string &s)
{
// 1. check for a TEXT file type.
{
int rv;
char buffer[32];
rv = ::getxattr(s.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
if (rv >= 8 && memcmp(buffer, "TEXT", 4) == 0)
return true;
}
std::string ext = extension(s);
if (ext.empty()) return false;
char c = ext[0];
switch(c)
{
case 'a':
if (ext == "aii") // assembler
return true;
if (ext == "asm")
return true;
break;
case 'c':
if (ext == "c")
return true;
if (ext == "cpp")
return true;
break;
case 'e':
if (ext == "equ") // asm iigs include file.
return true;
if (ext == "equates") // asm iigs include file.
return true;
break;
case 'i':
if (ext == "i") // asmiigs include file
return true;
if (ext == "inc")
return true;
break;
case 'h':
if (ext == "h") // c header
return true;
break;
case 'l':
if (ext == "lst") // asm iigs listing
return true;
break;
case 'm':
if (ext == "macros")
return true;
break;
case 'p':
if (ext == "p") // pascal
return true;
if (ext == "pas") // pascal
return true;
if (ext == "pii") // pascal
return true;
break;
case 'r':
if (ext == "r")
return true;
if (ext == "rez")
return true;
if (ext == "rii") // rez
return true;
break;
case 's':
if (ext == "src") // asm equates
return true;
break;
}
// check for e16.xxxx or m16.xxxx
ext = basename(s);
if (ext.length() > 4)
{
switch (ext[0])
{
case 'm':
case 'M':
case 'e':
case 'E':
if (!strncmp("16.", ext.c_str() + 1, 3))
return true;
break;
}
}
return false;
}
// known binary file extensions
bool IsBinaryFile(const std::string &s)
{
// first -- check for a finder info extension.
{
uint8_t buffer[32];
int rv;
rv = ::getxattr(s.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
if (rv >= 8 && ::memcmp(buffer + 4, "pdos",4) == 0)
{
// Bx__ ?
if (buffer[0] == 'B' && buffer[2] == ' ' && buffer[3] == ' ')
return true;
// "p" $uv $wx $yz
if (buffer[0] == 'p')
{
uint8_t fileType = buffer[1];
//uint16_t auxType = buffer[2] | (buffer[3] << 8);
if (fileType >= 0xb1 && fileType <= 0xbf)
return true;
}
}
}
std::string ext = extension(s);
if (ext.empty()) return false;
char c = ext[0];
switch(c)
{
case 'l':
if (ext == "lib")
return true;
break;
case 'n':
// MrC / MrCpp temp file.
if (ext == "n")
return true;
// Newton C++ Tools output
if (ext == "ntkc")
return true;
break;
case 'o':
if (ext == "o")
return true;
if (ext == "obj")
return true;
break;
case 's':
// Newton C++ Intermediate file
if (ext == "sym")
return true;
break;
case 'x':
// xcoff object file
if (ext == "x")
return true;
break;
}
return false;
}
uint16_t Close(uint16_t trap)
{
uint32_t d0;
@ -136,8 +309,8 @@ namespace OS
uint16_t ioRefNum = memoryReadWord(parm + 24);
int rv = OS::Internal::close_file(ioRefNum, true);
if (rv < 0) d0 = MacOS::rfNumErr;
int rv = OS::Internal::FDEntry::close(ioRefNum, true);
if (rv < 0) d0 = macos_error_from_errno();
else d0 = 0;
memoryWriteWord(d0, parm + 16);
@ -251,7 +424,9 @@ namespace OS
};
uint32_t d0 = 0;
uint32_t d0;
int fd;
uint8_t ioPermission = memoryReadByte(parm + _ioPermssn);
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
@ -264,11 +439,12 @@ namespace OS
sname = FSSpecManager::ExpandPath(sname, ioDirID);
}
Log(" open(%s, %02x, %02x)\n", sname.c_str(), resource, ioPermission);
auto fd = Internal::open_file(sname, resource, ioPermission);
if (fd) memoryWriteWord(fd.value(), parm + _ioRefNum);
d0 = fd.error();
fd = Internal::FDEntry::open(sname, ioPermission, resource);
d0 = fd < 0 ? fd : 0;
if (fd >= 0)
{
memoryWriteWord(fd, parm + _ioRefNum);
}
memoryWriteWord(d0, parm + _ioResult);
return d0;
@ -299,7 +475,8 @@ namespace OS
uint16_t Read(uint16_t trap)
{
uint32_t d0 = 0;
uint32_t d0;
int32_t pos;
uint32_t parm = cpuGetAReg(0);
Log("%04x Read(%08x)\n", trap, parm);
@ -312,24 +489,6 @@ namespace OS
uint16_t ioPosMode = memoryReadWord(parm + 44);
int32_t ioPosOffset = memoryReadLong(parm + 46);
Log(" read(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
/*
* per inside macintosh II-101:
* bit 6 (0x40) of ioPosOffset is used for read-verify operation
* (write date, call read w/ bit 6 to verify disk matches memory)
* returns ioError if it doesn't match.
*
* bit 7 (0x80) of ioPosMode indicate new-line mode is enabled --
* bits 8-15 are a newline character. reading terminates when newline
* char is encountered (or eof or ioReqCount).
*
* bit 4 is please cache bit
* bit 5 is please don't cache bit
* (if neither or both set, no preference)
*
*/
if (ioReqCount < 0)
{
d0 = MacOS::paramErr;
@ -337,48 +496,46 @@ namespace OS
return d0;
}
if (ioPosMode & 0x80) {
fprintf(stderr, "Newline Read (eof char = %02x)\n", ioPosMode >> 8);
exit(1);
}
pos = Internal::mac_seek(ioRefNum, ioPosMode, ioPosOffset);
if (pos < 0)
{
d0 = pos;
pos = 0;
ssize_t offset = ioPosOffset;
int whence = ioPosMode;
uint32_t transferCount = 0;
Internal::remap_seek(offset, whence);
auto ff = Internal::find_file(ioRefNum);
if (!ff) {
d0 = MacOS::rfNumErr;
memoryWriteLong(pos, parm + 46); // new offset.
memoryWriteWord(d0, parm + 16);
return d0;
}
auto pos = ff->seek(offset, whence);
if (!pos) {
d0 = pos.error();
memoryWriteWord(d0, parm + 16);
return d0;
Log(" read(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
ssize_t count = OS::Internal::FDEntry::read(ioRefNum, memoryPointer(ioBuffer), ioReqCount);
if (count >= 0)
{
d0 = 0;
pos += count;
memoryWriteLong(count, parm + 40);
}
auto xfer = ff->read(memoryPointer(ioBuffer), ioReqCount);
if (xfer && *xfer == 0) xfer = MacOS::eofErr;
if (count == 0 && ioReqCount > 0)
{
d0 = MacOS::eofErr;
}
if (count < 0)
{
d0 = macos_error_from_errno();
}
d0 = xfer.error();
transferCount = xfer.value_or(0);
offset = ff->get_mark().value_or((size_t)0);
memoryWriteLong(offset, parm + 46); // new offset.
memoryWriteLong(transferCount, parm + 40);
memoryWriteLong(pos, parm + 46); // new offset.
memoryWriteWord(d0, parm + 16);
return d0;
}
uint16_t Write(uint16_t trap)
{
uint32_t d0 = 0;
uint32_t d0;
int32_t pos;
uint32_t parm = cpuGetAReg(0);
Log("%04x Write(%08x)\n", trap, parm);
@ -391,8 +548,6 @@ namespace OS
uint16_t ioPosMode = memoryReadWord(parm + 44);
int32_t ioPosOffset = memoryReadLong(parm + 46);
Log(" write(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
if (ioReqCount < 0)
{
d0 = MacOS::paramErr;
@ -400,37 +555,36 @@ namespace OS
return d0;
}
ssize_t offset = ioPosOffset;
int whence = ioPosMode;
uint32_t transferCount = 0;
pos = Internal::mac_seek(ioRefNum, ioPosMode, ioPosOffset);
if (pos < 0)
{
d0 = pos;
pos = 0;
Internal::remap_seek(offset, whence);
auto ff = Internal::find_file(ioRefNum);
if (!ff) {
d0 = MacOS::rfNumErr;
memoryWriteLong(pos, parm + 46); // new offset.
memoryWriteWord(d0, parm + 16);
return d0;
}
auto pos = ff->seek(offset, whence);
if (!pos) {
d0 = pos.error();
memoryWriteWord(d0, parm + 16);
return d0;
Log(" write(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
ssize_t count = OS::Internal::FDEntry::write(ioRefNum, memoryPointer(ioBuffer), ioReqCount);
if (count >= 0)
{
d0 = 0;
pos += count;
memoryWriteLong(count, parm + 40);
}
auto xfer = ff->write(memoryPointer(ioBuffer), ioReqCount);
if (xfer && *xfer == 0) xfer = MacOS::eofErr;
if (count < 0)
{
d0 = macos_error_from_errno();
}
d0 = xfer.error();
transferCount = xfer.value_or(0);
offset = ff->get_mark().value_or((size_t)0);
memoryWriteLong(offset, parm + 46); // new offset.
memoryWriteLong(transferCount, parm + 40);
memoryWriteLong(pos, parm + 46); // new offset.
memoryWriteWord(d0, parm + 16);
return d0;
}
@ -469,6 +623,8 @@ namespace OS
_ioDirID = 48,
};
struct stat st;
bool htrap = trap & 0x0200;
const char *func = htrap ? "HDelete" : "Delete";
@ -496,10 +652,21 @@ namespace OS
Log(" %s(%s)\n", func, sname.c_str());
std::error_code ec;
if (fs::remove(sname, ec)) d0 = 0;
else if (ec) d0 = macos_error_from_errno(ec);
else d0 = MacOS::fnfErr;
int ok;
ok = ::lstat(sname.c_str(), &st);
if (ok == 0)
{
if (S_ISDIR(st.st_mode))
ok = ::rmdir(sname.c_str());
else
ok = ::unlink(sname.c_str());
}
if (ok < 0)
d0 = macos_error_from_errno();
else
d0 = 0;
memoryWriteWord(d0, parm + _ioResult);
return d0;
@ -509,8 +676,8 @@ namespace OS
uint16_t GetEOF(uint16_t trap)
{
uint32_t d0 = 0;
size_t size = 0;
uint32_t d0;
size_t size;
uint32_t parm = cpuGetAReg(0);
@ -519,15 +686,18 @@ namespace OS
//uint32_t ioCompletion = memoryReadLong(parm + 12);
uint16_t ioRefNum = memoryReadWord(parm + 24);
auto ff = Internal::find_file(ioRefNum);
if (ff) {
auto eof = ff->get_eof();
d0 = eof.error();
size = eof.value_or(0);
} else {
d0 = MacOS::rfNumErr;
struct stat st;
if (::fstat(ioRefNum, &st) < 0)
{
d0 = macos_error_from_errno();
size = 0;
}
else
{
d0 = 0;
size = st.st_size;
}
memoryWriteWord(d0, parm + 16);
memoryWriteLong(size, parm + 28);
@ -547,14 +717,9 @@ namespace OS
uint16_t ioRefNum = memoryReadWord(parm + 24);
uint32_t ioMisc = memoryReadLong(parm + 28);
int rv = ::ftruncate(ioRefNum, ioMisc);
auto ff = Internal::find_file(ioRefNum);
if (ff) {
auto eof = ff->set_eof(ioMisc);
d0 = eof.error();
} else {
d0 = MacOS::rfNumErr;
}
d0 = rv < 0 ? macos_error_from_errno() : 0;
memoryWriteWord(d0, parm + 16);
return d0;
@ -562,8 +727,7 @@ namespace OS
uint16_t GetFPos(uint16_t trap)
{
uint32_t d0 = 0;
size_t size = 0;
uint32_t d0;
uint32_t parm = cpuGetAReg(0);
@ -572,22 +736,19 @@ namespace OS
//uint32_t ioCompletion = memoryReadLong(parm + 12);
uint16_t ioRefNum = memoryReadWord(parm + 24);
auto ff = Internal::find_file(ioRefNum);
if (ff) {
auto mark = ff->get_mark();
d0 = mark.error();
size = mark.value_or(0);
} else {
d0 = MacOS::rfNumErr;
size = 0;
int rv = ::lseek(ioRefNum, 0, SEEK_CUR);
if (rv < 0)
{
d0 = macos_error_from_errno();
}
else
{
memoryWriteLong(0, parm + 36); // ioReqCount
memoryWriteLong(0, parm + 40); // ioActCount
memoryWriteWord(0, parm + 44); // ioPosMode
memoryWriteLong(rv, parm + 46); // ioPosOffset
d0 = 0;
}
memoryWriteLong(0, parm + 36); // ioReqCount
memoryWriteLong(0, parm + 40); // ioActCount
memoryWriteWord(0, parm + 44); // ioPosMode
memoryWriteLong(size, parm + 46); // ioPosOffset
memoryWriteWord(d0, parm + 16);
return d0;
@ -607,23 +768,15 @@ namespace OS
int32_t ioPosOffset = memoryReadLong(parm + 46);
ssize_t offset = ioPosOffset;
int whence = ioPosMode;
Internal::remap_seek(offset, whence);
auto ff = Internal::find_file(ioRefNum);
if (ff) {
auto pos = ff->seek(offset, whence);
d0 = pos.error();
offset = pos.value_or(0);
} else {
d0 = MacOS::rfNumErr;
offset = 0;
ioPosOffset = Internal::mac_seek(ioRefNum, ioPosMode, ioPosOffset);
d0 = 0;
if (ioPosOffset < 0)
{
d0 = ioPosOffset;
ioPosOffset = 0;
}
memoryWriteLong(offset, parm + 46); // new offset.
memoryWriteLong(ioPosOffset, parm + 46); // new offset.
memoryWriteWord(d0, parm + 16);
return d0;
}
@ -647,8 +800,8 @@ namespace OS
*
*/
bool caseSens = trap & (1 << 9);
//bool diacSens = trap & (1 << 10); // ignore for now...
//bool diacSens = trap & (1 << 9); // ignore for now...
bool caseSens = trap & (1 << 10);
uint32_t aStr = cpuGetAReg(0);
uint32_t bStr = cpuGetAReg(1);
@ -685,6 +838,55 @@ namespace OS
}
uint16_t RelString(uint16_t trap)
{
/*
* on entry:
* A0 Pointer to first character of first string
* A1 Pointer to first character of second string
* D0 (high) length of first string
* D0 (low) length of second string
*
* on exit:
* D0 0 if strings equal, -1 if first < second, 1 if first > second
*
*/
//bool diacSens = trap & (1 << 9); // ignore for now...
bool caseSens = trap & (1 << 10);
uint32_t aStr = cpuGetAReg(0);
uint32_t bStr = cpuGetAReg(1);
uint32_t length = cpuGetDReg(0);
uint32_t aLen = (length >> 16);
uint32_t bLen = (length & 0xffff);
std::string a = ToolBox::ReadString(aStr, aLen);
std::string b = ToolBox::ReadString(bStr, bLen);
Log("%04x RelString(%s, %s)\n", trap, a.c_str(), b.c_str());
if (aStr == bStr) return 0; // same ptr...
for (uint32_t i = 0; i < std::min(aLen, bLen); ++i) {
unsigned aa = a[i];
unsigned bb = b[i];
if (!caseSens) {
aa = toupper(aa);
bb = toupper(bb);
}
if (aa == bb) continue;
return aa < bb ? -1 : 1;
}
if (aLen == bLen) return 0;
return aLen < bLen ? -1 : 1;
}
#pragma mark - Time Utilities
time_t UnixToMac(time_t t)

View File

@ -29,10 +29,9 @@ namespace OS
bool Init();
/*
bool IsTextFile(const std::string &s);
bool IsBinaryFile(const std::string &s);
*/
time_t UnixToMac(time_t);
time_t MacToUnix(time_t);
@ -72,6 +71,7 @@ namespace OS
#pragma mark String Utilities
uint16_t CmpString(uint16_t trap);
uint16_t RelString(uint16_t trap);
#pragma mark - Time Utilities

View File

@ -32,7 +32,9 @@
#include <deque>
#include <string>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/paths.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

View File

@ -26,14 +26,15 @@
#include <cerrno>
#include <cctype>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <chrono>
#include <deque>
#include <string>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/paths.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
@ -53,87 +54,42 @@
#include "stackframe.h"
#include "fs_spec.h"
#include <native/native.h>
using ToolBox::Log;
using MacOS::macos_error_from_errno;
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#define st_birthtime st_mtime
#endif
namespace {
uint32_t rforksize(const std::string &path)
{
ssize_t rv;
rv = getxattr(path.c_str(), XATTR_RESOURCEFORK_NAME, nullptr, 0, 0, 0);
if (rv < 0) return 0;
return rv;
}
uint32_t rforksize(int fd)
{
ssize_t rv;
rv = fgetxattr(fd, XATTR_RESOURCEFORK_NAME, nullptr, 0, 0, 0);
if (rv < 0) return 0;
return rv;
}
}
namespace OS {
static uint16_t FileInfoByName(const std::string &sname, uint32_t parm) {
enum { // FileParam
_qLink = 0,
_qType = 4,
_ioTrap = 6,
_ioCmdAddr = 8,
_ioCompletion = 12,
_ioResult = 16,
_ioNamePtr = 18,
_ioVRefNum = 22,
_ioFRefNum = 24,
_ioFVersNum = 26,
_filler1 = 27,
_ioFDirIndex = 28,
_ioFlAttrib = 30,
_ioFlVersNum = 31,
_ioFlFndrInfo = 32,
_ioFlNum = 48, // ioDirID in other
_ioFlStBlk = 52,
_ioFlLgLen = 54,
_ioFlPyLen = 58,
_ioFlRStBlk = 62,
_ioFlRLgLen = 64,
_ioFlRPyLen = 68,
_ioFlCrDat = 72,
_ioFlMdDat = 76,
_ioDirID = 48,
};
using namespace native;
file_info fi;
auto err = native::get_file_info(sname, fi);
if (err) return err;
// if this is not a file, error out?
std::memcpy(memoryPointer(parm + _ioFlFndrInfo), fi.finder_info, 16);
// file reference number
memoryWriteWord(0, parm + _ioFRefNum);
// file attributes
memoryWriteByte(0, parm + _ioFlAttrib);
// version (unused)
memoryWriteByte(0, parm + _ioFlVersNum);
// file id
memoryWriteLong(0, parm + _ioFlNum);
// file size
memoryWriteWord(0, parm + _ioFlStBlk);
memoryWriteLong(fi.data_logical_size, parm + _ioFlLgLen);
memoryWriteLong(fi.data_physical_size, parm + _ioFlPyLen);
// create date.
memoryWriteLong(fi.create_date, parm + _ioFlCrDat);
memoryWriteLong(fi.modify_date, parm + _ioFlMdDat);
// res fork...
memoryWriteWord(0, parm + _ioFlRStBlk);
memoryWriteLong(fi.resource_logical_size, parm + _ioFlRLgLen);
memoryWriteLong(fi.resource_physical_size, parm + _ioFlRPyLen);
return 0;
}
uint16_t GetFileInfo(uint16_t trap)
{
@ -203,10 +159,52 @@ namespace OS {
Log(" GetFileInfo(%s)\n", sname.c_str());
d0 = FileInfoByName(sname, parm);
memoryWriteWord(d0, parm + _ioResult);
return d0;
struct stat st;
if (::stat(sname.c_str(), &st) < 0)
{
d0 = macos_error_from_errno();
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
Internal::GetFinderInfo(sname, memoryPointer(parm + _ioFlFndrInfo), false);
// file reference number
memoryWriteWord(0, parm + _ioFRefNum);
// file attributes
memoryWriteByte(0, parm + _ioFlAttrib);
// version (unused)
memoryWriteByte(0, parm + _ioFlVersNum);
// file id
memoryWriteLong(0, parm + _ioFlNum);
// file size
memoryWriteWord(0, parm + _ioFlStBlk);
memoryWriteLong(st.st_size, parm + _ioFlLgLen);
memoryWriteLong(st.st_size, parm + _ioFlPyLen);
// create date.
memoryWriteLong(UnixToMac(st.st_birthtime), parm + _ioFlCrDat);
memoryWriteLong(UnixToMac(st.st_mtime), parm + _ioFlMdDat);
// res fork...
uint32_t rf = rforksize(sname);
memoryWriteWord(0, parm + _ioFlRStBlk);
memoryWriteLong(rf, parm + _ioFlRLgLen);
memoryWriteLong(rf, parm + _ioFlRPyLen);
// no error.
memoryWriteWord(0, parm + _ioResult);
}
else
{
@ -286,14 +284,26 @@ namespace OS {
Log(" SetFileInfo(%s)\n", sname.c_str());
native::file_info fi;
fi.create_date = memoryReadLong(parm + _ioFlCrDat);
fi.modify_date = memoryReadLong(parm + _ioFlMdDat);
native::get_finder_info(sname, fi.finder_info); // get extended bits.
std::memcpy(fi.finder_info, memoryPointer(parm + _ioFlFndrInfo), 16);
d0 = native::set_file_info(sname, fi);
// check if the file actually exists
{
struct stat st;
int ok;
ok = ::stat(sname.c_str(), &st);
if (ok < 0)
{
d0 = macos_error_from_errno();
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
}
d0 = Internal::SetFinderInfo(sname, memoryPointer(parm + 32), false);
if (d0 == 0) d0 = Internal::SetFileDates(sname, memoryReadLong(parm + _ioFlCrDat), memoryReadLong(parm + _ioFlMdDat), 0);
memoryWriteWord(d0, parm + _ioResult);
return d0;
}

View File

@ -34,7 +34,9 @@
#include <map>
#include <type_traits>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/paths.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

View File

@ -33,16 +33,17 @@
#include <deque>
#include <string>
#include <cstring>
#include <vector>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <sys/paths.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <filesystem>
#include <dirent.h>
#include <strings.h>
#include <sys/param.h>
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
@ -56,16 +57,14 @@
#include "stackframe.h"
#include "fs_spec.h"
#include <config.h>
#include <native/native.h>
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#define st_birthtime st_mtime
#endif
using ToolBox::Log;
using MacOS::macos_error_from_errno;
namespace fs = std::experimental::filesystem;
namespace OS {
uint16_t PBGetWDInfo(uint32_t parm)
@ -172,63 +171,78 @@ namespace OS {
_ioDrParID = 100,
};
struct stat st;
using namespace native;
file_info fi;
auto rv = get_file_info(sname, fi);
if (rv) return rv;
memoryWriteByte(0, parm + _ioACUser);
if (fi.type == file_info::directory) {
if (::stat(sname.c_str(), &st) < 0)
{
return macos_error_from_errno();
}
if (S_ISDIR(st.st_mode))
{
// bit 4 - is a directory.
memoryWriteByte(1 << 4, parm + _ioFlAttrib);
memoryWriteByte(0, parm + _ioACUser);
std::memset(memoryPointer(parm + _ioDrUsrWds), 0, 16); // DInfo
// cw68k expects the directory ID to be set.
uint32_t dirID = FSSpecManager::IDForPath(sname);
memoryWriteLong(dirID, parm + _ioDrDirID);
memoryWriteWord(fi.entry_count, parm + _ioDrNmFls); // ioDrNmFls - # of files in dir
// the links count should be ~= number of dirents ( +2 for . and ..)
int links = st.st_nlink - 2;
if (links < 0) links = 0;
if (links > 65535) links = 65535;
memoryWriteLong(fi.create_date, parm + _ioDrCrDat); // create
memoryWriteLong(fi.modify_date, parm + _ioDrMdDat); // modify
memoryWriteLong(fi.backup_date, parm + _ioDrBkDat); // backup
memoryWriteWord(links, parm + _ioDrNmFls); // ioDrNmFls - # of files in dir
memoryWriteLong(UnixToMac(st.st_birthtime), parm + _ioDrCrDat); // create
memoryWriteLong(UnixToMac(st.st_mtime), parm + _ioDrMdDat); // modify
memoryWriteLong(UnixToMac(st.st_mtime), parm + _ioDrBkDat); // backup
std::memset(memoryPointer(parm + _ioDrFndrInfo), 0, 16); // DXInfo
memoryWriteLong(0, parm + _ioDrParID);
} else {
}
else
{
memoryWriteByte(0, parm + _ioFlAttrib);
std::memcpy(memoryPointer(parm + _ioFlFndrInfo), fi.finder_info , 16); // finder info
std::memcpy(memoryPointer(parm + _ioFlXFndrInfo), fi.finder_info + 16, 16); // FXInfo
memoryWriteByte(0, parm + _ioACUser);
Internal::GetFinderInfo(sname, memoryPointer(parm + _ioFlFndrInfo), false); // finder info
memoryWriteLong(0, parm + _ioDirID);
memoryWriteWord(0, parm + _ioFlStBlk);
memoryWriteWord(0, parm + _ioFlRStBlk);
memoryWriteLong(st.st_size, parm + _ioFlLgLen);
memoryWriteLong(st.st_size, parm + _ioFlPyLen);
memoryWriteLong(fi.create_date, parm + _ioFlCrDat); // create
memoryWriteLong(fi.modify_date, parm + _ioFlMdDat); // modify
memoryWriteLong(fi.backup_date, parm + _ioFlBkDat); // backup
// resource info... below
memoryWriteLong(fi.data_logical_size, parm + _ioFlLgLen);
memoryWriteLong(fi.data_physical_size, parm + _ioFlPyLen);
memoryWriteLong(fi.resource_logical_size, parm + _ioFlRLgLen);
memoryWriteLong(fi.resource_physical_size, parm + _ioFlRPyLen);
memoryWriteLong(UnixToMac(st.st_birthtime), parm + _ioFlCrDat); // create
memoryWriteLong(UnixToMac(st.st_mtime), parm + _ioFlMdDat); // modify
memoryWriteLong(UnixToMac(st.st_mtime), parm + _ioFlBkDat); // backup
std::memset(memoryPointer(parm + _ioFlXFndrInfo), 0, 16); // FXInfo
memoryWriteWord(0, parm + _ioFlParID);
memoryWriteWord(0, parm + _ioFlClpSiz);
sname.append(_PATH_RSRCFORKSPEC);
if (::stat(sname.c_str(), &st) >= 0)
{
memoryWriteWord(0, parm + _ioFlRStBlk);
memoryWriteLong(st.st_size, parm + _ioFlRLgLen);
memoryWriteLong(st.st_size, parm + _ioFlRPyLen);
}
else
{
memoryWriteWord(0, parm + _ioFlRStBlk);
memoryWriteLong(0, parm + _ioFlRLgLen);
memoryWriteLong(0, parm + _ioFlRPyLen);
}
}
return 0;
}
uint16_t PBGetCatInfo(uint32_t parm)
@ -331,8 +345,11 @@ namespace OS {
std::string sname = FSSpecManager::PathForID(ioDirID);
if (sname.empty()) {
auto path = fs::current_path();
sname = path.empty() ? "." : path.generic_u8string();
char buffer[MAXPATHLEN];
char *cp;
cp = getcwd(buffer, sizeof(buffer));
sname = cp ? cp : ".";
}
d0 = CatInfoByName(sname, parm);
@ -366,26 +383,42 @@ namespace OS {
sname = OS::realpath(sname);
// if sname == "", error...
DIR *dp;
struct dirent *dir;
fs::directory_iterator dir(sname);
std::vector<fs::path> names(fs::begin(dir), fs::end(dir));
if (ioFDirIndex >= names.size()) {
d0 = MacOS::fnfErr; // end of dir error?
dp = opendir(sname.c_str());
if (!dp) {
d0 = macos_error_from_errno();
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
// alphabetical order...
std::sort(names.begin(), names.end());
auto e = names[ioFDirIndex - 1];
if (ioNamePtr) {
ToolBox::WritePString(ioNamePtr, e.filename().generic_u8string());
while ((dir = readdir(dp))) {
if (dir->d_name[0] == '.') {
if (!strcmp(dir->d_name, ".")) continue;
if (!strcmp(dir->d_name, "..")) continue;
}
if (dir->d_namlen > 255) continue; // too long!
if (--ioFDirIndex == 0) break;
}
d0 = CatInfoByName(e.generic_u8string(), parm);
if (!dir) {
closedir(dp);
d0 = MacOS::fnfErr;
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
if (ioNamePtr) {
ToolBox::WritePString(ioNamePtr, dir->d_name);
}
sname.push_back('/');
sname.append(dir->d_name);
closedir(dp);
d0 = CatInfoByName(sname, parm);
}
memoryWriteWord(d0, parm + _ioResult);
@ -466,17 +499,44 @@ namespace OS {
Log(" PBSetCatInfo(%s)\n", sname.c_str());
native::file_info fi;
fi.create_date = memoryReadLong(parm + _ioFlCrDat);
fi.modify_date = memoryReadLong(parm + _ioFlMdDat);
fi.backup_date = memoryReadLong(parm + _ioFlBkDat);
// check if the file actually exists
{
struct stat st;
int ok;
ok = ::stat(sname.c_str(), &st);
if (ok < 0)
{
d0 = macos_error_from_errno();
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
// just nop if it's a directory.
if (S_ISDIR(st.st_mode))
{
d0 = 0;
d0 = Internal::SetFileDates(sname,
memoryReadLong(parm + _ioDrCrDat),
memoryReadLong(parm + _ioDrMdDat),
memoryReadLong(parm + _ioDrBkDat));
memoryWriteWord(d0, parm + _ioResult);
return d0;
}
}
memcpy(fi.finder_info, memoryPointer(parm + _ioFlFndrInfo), 16);
memcpy(fi.finder_info+16, memoryPointer(parm + _ioFlXFndrInfo), 16);
// set the finder info. could also call utimes or setattrlist, I suppose.
d0 = Internal::SetFinderInfo(sname, memoryPointer(parm + _ioFlFndrInfo), false);
if (d0 == 0) d0 = Internal::SetFileDates(sname,
memoryReadLong(parm + _ioFlCrDat),
memoryReadLong(parm + _ioFlMdDat),
memoryReadLong(parm + _ioFlBkDat));
d0 = native::set_file_info(sname, fi);
memoryWriteWord(d0, parm + _ioResult);
return d0;

Some files were not shown because too many files have changed in this diff Show More