mirror of
https://github.com/ksherlock/mpw.git
synced 2024-06-09 09:29:30 +00:00
Compare commits
61 Commits
pre-rebase
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
d59a35d3a9 | ||
|
9951892251 | ||
|
79a8a93e03 | ||
|
f619ed31b3 | ||
|
f460696b4f | ||
|
6151ca1e87 | ||
|
b9c7d9f95f | ||
|
2dcb161f5e | ||
|
f08d67333d | ||
|
2e7e75a2a9 | ||
|
bdb1f4b2b9 | ||
|
b8d17f4481 | ||
|
a76287876c | ||
|
022d4cffe9 | ||
|
843ea2764c | ||
|
fc15ad1d81 | ||
|
7ac2a88974 | ||
|
2703e00201 | ||
|
5facdb095c | ||
|
194c36c89a | ||
|
3e2c02f796 | ||
|
48d869c6e8 | ||
|
8c911ab83d | ||
|
b6b0abefbf | ||
|
67253a69e5 | ||
|
f3b3d221be | ||
|
f4e3bd70a1 | ||
|
1925dc172b | ||
|
4730a70874 | ||
|
a70270be52 | ||
|
f12b3789c4 | ||
|
6dfefb2343 | ||
|
35443c9aa8 | ||
|
fcdfe76817 | ||
|
a55b38104b | ||
|
fb0d353716 | ||
|
7dc85091a3 | ||
|
0cca883287 | ||
|
58f2557df5 | ||
|
031cdf0d08 | ||
|
c8310c0dbd | ||
|
3480881001 | ||
|
8f64923f9c | ||
|
7cb4c8cbc3 | ||
|
1a9cb0d766 | ||
|
02629c4eee | ||
|
fa1f4623c9 | ||
|
b560c66dda | ||
|
2eb90481bc | ||
|
8c38175492 | ||
|
08fef2cef5 | ||
|
fb6d52a93d | ||
|
26bd3f53b7 | ||
|
d11dab46e2 | ||
|
c3d1121f36 | ||
|
776b385a41 | ||
|
119d9aab57 | ||
|
60b49a1ff4 | ||
|
e21aac4022 | ||
|
60c4977dfa | ||
|
58f4ca4ac6 |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: [ksherlock]
|
38
.github/workflows/cmake-fat.yml
vendored
Normal file
38
.github/workflows/cmake-fat.yml
vendored
Normal 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
41
.github/workflows/cmake.yml
vendored
Normal 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
1
.gitignore
vendored
|
@ -8,4 +8,3 @@ docs/
|
|||
MrC/
|
||||
testing/
|
||||
|
||||
build-msvc/
|
||||
|
|
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
os: osx
|
||||
osx_image:
|
||||
- xcode11
|
||||
- xcode12
|
||||
- xcode12.5
|
||||
language: cpp
|
||||
compiler: clang
|
||||
before_script:
|
||||
|
|
|
@ -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)
|
||||
|
|
17
README.md
17
README.md
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "debugger.h"
|
||||
#include "debugger_internal.h"
|
||||
#include "main.h" // Flags
|
||||
#include "loader.h" // Flags
|
||||
|
||||
|
||||
namespace Debug {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
341
bin/loadtrap.rl
341
bin/loadtrap.rl
|
@ -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
1868
bin/parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
51
bin/parser.h
Normal file
51
bin/parser.h
Normal 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
|
|
@ -1,7 +1,7 @@
|
|||
#include "template.h"
|
||||
#include "debugger.h"
|
||||
#include "debugger_internal.h"
|
||||
#include "main.h" // Flags.
|
||||
#include "loader.h" // Flags.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
@ -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
1291
bin/template_parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
20
bin/template_parser.h
Normal file
20
bin/template_parser.h
Normal 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
|
23
config.h.in
23
config.h.in
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
10465
cpu/CpuModule_Code.h
10465
cpu/CpuModule_Code.h
File diff suppressed because it is too large
Load Diff
2609
cpu/CpuModule_Data.h
2609
cpu/CpuModule_Data.h
File diff suppressed because it is too large
Load Diff
3358
cpu/CpuModule_Decl.h
3358
cpu/CpuModule_Decl.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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;}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1 +1 @@
|
|||
#include "fmem.h"
|
||||
#include "fmem.h"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#ifndef CPUMODULE_PROFILE_H
|
||||
#define CPUMODULE_PROFILE_H
|
||||
#pragma once
|
||||
|
||||
void cpuProfileWrite(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
50
cpu/defs.h
50
cpu/defs.h
|
@ -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
1692
cpu/fmem.c
File diff suppressed because it is too large
Load Diff
152
cpu/fmem.h
152
cpu/fmem.h
|
@ -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
|
||||
|
|
22
cpu/memory.c
22
cpu/memory.c
|
@ -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);
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
set(CXX_SRC mapped_file.cpp)
|
||||
|
||||
add_library(CXX_LIB ${CXX_SRC})
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
119
include/endian.h
119
include/endian.h
|
@ -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
1
libsane
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 8a47aacd7d8a19566701ae60dd03ff3c6e6b3634
|
|
@ -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})
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1047,7 +1047,7 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
_ALMDispatch = 0xAAA4 /* Apple Location Manger*/
|
||||
_ALMDispatch = 0xAAA4 /* Apple Location Manager*/
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(MPLITE_SRC mplite.c)
|
||||
|
||||
add_library(MPLITE_LIB ${MPLITE_SRC})
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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})
|
|
@ -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);
|
||||
|
|
189
mpw/mpw.cpp
189
mpw/mpw.cpp
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
342
native/Linux.cpp
342
native/Linux.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
242
native/SunOS.cpp
242
native/SunOS.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
214
native/file.cpp
214
native/file.cpp
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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 *);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
602
toolbox/mm.cpp
602
toolbox/mm.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
98
toolbox/mm.h
98
toolbox/mm.h
|
@ -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);
|
||||
|
|
482
toolbox/os.cpp
482
toolbox/os.cpp
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue
Block a user