From 9724f587eb7c4979ae950903fa9942de0561750c Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Tue, 2 Aug 2016 13:46:18 -0400 Subject: [PATCH] new resource manager (in progress) --- toolbox/CMakeLists.txt | 5 +- toolbox/mm.h | 2 +- toolbox/rm-new.cpp | 991 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 995 insertions(+), 3 deletions(-) create mode 100644 toolbox/rm-new.cpp diff --git a/toolbox/CMakeLists.txt b/toolbox/CMakeLists.txt index 7f0199c..085cd9f 100644 --- a/toolbox/CMakeLists.txt +++ b/toolbox/CMakeLists.txt @@ -1,6 +1,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -Wno-deprecated-declarations -g") +set(CMAKE_CXX_FLAGS "-std=c++14 -stdlib=libc++ -Wall -Wno-deprecated-declarations -g") add_definitions(-I ${CMAKE_SOURCE_DIR}/) @@ -8,7 +8,8 @@ set(TOOLBOX_SRC toolbox.cpp mm.cpp loader.cpp - rm.cpp +# rm.cpp + rm-new.cpp os.cpp os_alias.cpp os_fileinfo.cpp diff --git a/toolbox/mm.h b/toolbox/mm.h index 2986abf..21de6c9 100644 --- a/toolbox/mm.h +++ b/toolbox/mm.h @@ -40,7 +40,7 @@ namespace MM void PrintMemoryStats(); tool_return NewHandle(uint32_t size, bool clear); - tool_return NewHandle(); + tool_return NewHandle(); tool_return NewPtr(uint32_t size, bool clear); diff --git a/toolbox/rm-new.cpp b/toolbox/rm-new.cpp new file mode 100644 index 0000000..76aaf12 --- /dev/null +++ b/toolbox/rm-new.cpp @@ -0,0 +1,991 @@ +/* + * 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 "rm.h" +#include "mm.h" +#include "toolbox.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + +#include +#include +#include + +#include + + +#include "stackframe.h" +#include "fs_spec.h" + +/* + * todo -- iterators for the resource map? + */ + + +/* + * refNum 0 = system resource + * refNum 1 = ROM resource. + */ + + +using namespace MacOS; +using ToolBox::Log; +using ToolBox::TypeToString; + +inline constexpr uint32_t read_32(const uint8_t *cp) { + return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | (cp[3] << 0); +} + +inline constexpr uint32_t read_24(const uint8_t *cp) { + return (cp[0] << 16) | (cp[1] << 8) | (cp[2] << 0); +} + + +inline constexpr uint16_t read_16(const uint8_t *cp) { + return (cp[0] << 8) | (cp[1] << 0); +} + +inline constexpr uint8_t read_8(const uint8_t *cp) { + return cp[0]; +} + +inline void check_size(const std::vector v, size_t size) { + if (size > v.size()) throw std::out_of_range("check_size"); +} + +inline void check_offset(const std::vector v, size_t offset) { + if (offset >= v.size()) throw std::out_of_range("check_offset"); +} + +inline uint32_t read_32(const std::vector v, size_t offset, const std::nothrow_t &) noexcept { + return (v[offset+0] << 24) | (v[offset+1] << 16) | (v[offset+2] << 8) | (v[offset+3] << 0); +} + +inline uint32_t read_24(const std::vector v, size_t offset, const std::nothrow_t &) noexcept { + return (v[offset+0] << 16) | (v[offset+1] << 8) | (v[offset+2] << 0); +} + +inline uint32_t read_16(const std::vector v, size_t offset, const std::nothrow_t &) noexcept { + return (v[offset+0] << 8) | (v[offset+1] << 0); +} + +inline uint8_t read_8(const std::vector v, size_t offset, const std::nothrow_t &) noexcept { + return v[offset+0]; +} + + +inline uint32_t read_32(const std::vector v, size_t offset) { + check_size(v, offset + 4); + return read_32(v, offset, std::nothrow); +} + +inline uint32_t read_24(const std::vector v, size_t offset) { + check_size(v, offset + 3); + return read_24(v, offset, std::nothrow); +} + +inline uint32_t read_16(const std::vector v, size_t offset) { + check_size(v, offset + 2); + return read_16(v, offset, std::nothrow); +} + +inline uint8_t read_8(const std::vector v, size_t offset) { + return v.at(offset+0); +} + + +inline std::string read_string(const std::vector v, size_t offset, const std::nothrow_t &) noexcept { + int length = v[offset + 0]; + return std::string((const char *)v.data() + offset + 1, length); +} + +inline std::string read_string(const std::vector v, size_t offset) { + int length = v.at(offset + 0); + check_size(v, offset + length + 1); + return std::string((const char *)v.data() + offset + 1, length); +} + + +enum { + resSysHeap = 64, + resPurgeable = 32, + resLocked = 16, + resProtected = 8, + resPreload = 4, + resChanged = 2, +}; + +struct resource { + uint32_t type = 0; + uint16_t id = 0; + uint16_t attr = 0; + uint32_t data_offset = 0; + //uint32_t name_offset = 0; + uint32_t size = -1; + uint32_t handle = 0; + std::string name; +}; + + +struct resource_file { + resource_file *next = nullptr; + int fd = -1; + int refnum = -1; + bool readonly = true; + + + // header + uint32_t offset_rdata = 0; /* offset to resource data */ + uint32_t offset_rmap = 0; /* offset to resource map */ + uint32_t length_rdata = 0; /* length of resource data */ + uint32_t length_rmap = 0; /* length of resource map */ + + // map + uint16_t attr = 0; + + std::vector resources; + + + resource_file() = default; + resource_file(resource_file &&) = delete; + resource_file(const resource_file &) = delete; + + resource_file &operator=(const resource_file &) = delete; + resource_file &operator=(resource_file &&) = delete; + + ~resource_file() { + if (fd >= 0) close(fd); + } +}; + + +bool operator<(const resource &lhs, const resource &rhs) { + return (lhs.type < rhs.type) || (lhs.type == rhs.type && lhs.id < rhs.id); +} + + + +namespace { + + int refnum = 100; + bool res_load = true; + + resource_file *current = nullptr; + resource_file *head = nullptr; + + + tool_return read_resource_map(resource_file &rf) { + + ssize_t ok; + uint8_t header[100]; + + ok = read(rf.fd, header, sizeof(header)); + if (ok != sizeof(header)) return mapReadErr; + + rf.offset_rdata = read_32(header+0); + rf.offset_rmap = read_32(header+4); + rf.length_rdata = read_32(header+8); + rf.length_rmap = read_32(header+12); + + if (rf.length_rmap < 30) return mapReadErr; + std::vector rmap(rf.length_rmap); + + if (lseek(rf.fd, rf.offset_rmap, SEEK_SET) < 0) return macos_error_from_errno(); + ok = read(rf.fd, rmap.data(), rf.length_rmap); + if (ok != rf.length_rmap) return mapReadErr; + + rf.attr = read_16(rmap, 22, std::nothrow); + uint16_t offset_type_list = read_16(rmap, 24, std::nothrow) + 2; + uint16_t offset_name_list = read_16(rmap, 26, std::nothrow); + int16_t count = read_16(rmap, 28, std::nothrow); + + if (offset_type_list < 30) return mapReadErr; + if (offset_name_list < 30) return mapReadErr; + if (offset_type_list > rf.length_rmap) return mapReadErr; + if (offset_name_list > rf.length_rmap) return mapReadErr; + + + try { + + unsigned tl_offset = offset_type_list; + check_size(rmap, tl_offset + (count + 1) * 8); + + while (count-- >= 0) { + + struct resource r; + + r.type = read_32(rmap, tl_offset + 0, std::nothrow); + int16_t count = read_16(rmap, tl_offset + 4, std::nothrow); + unsigned rl_offset = offset_type_list + read_16(rmap, tl_offset + 6, std::nothrow); + + check_size(rmap, rl_offset + (count + 1) * 12); + + while (count-- >= 0) { + + r.id = read_16(rmap, rl_offset + 0, std::nothrow); + + unsigned nl_offset = read_16(rmap, rl_offset + 2, std::nothrow); + r.attr = read_8(rmap, rl_offset + 4, std::nothrow); + r.data_offset = read_24(rmap, rl_offset + 5, std::nothrow); + // 4 bytes reserved. + + r.name.clear(); + if (nl_offset != 0xffff) { + r.name = read_string(rmap, nl_offset + offset_name_list); + } + + + rf.resources.emplace_back(std::move(r)); + + rl_offset += 12; + } + + tl_offset += 8; + } + + } catch (std::out_of_range &ex) { + return mapReadErr; + } + + std::sort(rf.resources.begin(), rf.resources.end()); + return noErr; + } + + tool_return read_resource(resource_file &rf, resource &r) { + + ssize_t ok; + + if (r.handle) return r.handle; + + if (!res_load) { + /* create a null handle */ + auto hh = MM::Native::NewHandle(); + if (hh.error()) return hh.error(); + r.handle = *hh; + return *hh; + } + + if (r.size == -1) { + uint8_t buffer[4]; + if (lseek(rf.fd, rf.offset_rdata + r.data_offset, SEEK_SET) < 0) + return macos_error_from_errno(); + ok = read(rf.fd, buffer, sizeof(buffer)); + if (ok != 4) return badExtResource; + + r.size = read_32(buffer); + } else { + + if (lseek(rf.fd, rf.offset_rdata + r.data_offset + 4, SEEK_SET) < 0) + return macos_error_from_errno(); + + } + + auto hh = MM::Native::NewHandle(r.size, false); + if (hh.error()) return hh.error(); + MM::Native::HSetRBit(hh->handle); + + ok = read(rf.fd, memoryPointer(hh->pointer), r.size); + if (ok < 0) { + auto rv = macos_error_from_errno(); + MM::Native::DisposeHandle(hh->handle); + return rv; + } + + if (ok != r.size) { + MM::Native::DisposeHandle(hh->handle); + return badExtResource; + } + + r.handle = hh->handle; + return hh->handle; + } + + inline macos_error SetResError(uint16_t error) + { + memoryWriteWord(error, MacOS::ResErr); + return (macos_error)error; + } + +}; + + +namespace RM { +#pragma mark - Native + +namespace Native { + + tool_return OpenResFile(const std::string &path_name, uint16_t perm) { + + int fd = native::open_resource_fork(path_name, O_RDONLY); + if (fd < 0) return macos_error_from_errno(); + + auto rf = std::make_unique(); + + rf->fd = fd; + rf->readonly = true; + auto rv = read_resource_map(*rf); + if (rv.error()) return rv.error(); + + rf->refnum = ++refnum; + + rf->next = head; + head = rf.release(); + current = head; + + return refnum; + } + + + tool_return UpdateResFile(resource_file &rf) + { + return noErr; + } + + + + tool_return CloseResFile(uint16_t refNum) { + + resource_file *rf = head; + resource_file *prev = nullptr; + while (rf) { + if (rf->refnum == refNum) break; + prev = rf; + rf = rf->next; + } + if (!rf) return SetResError(MacOS::resFNotFound); + + auto rv = UpdateResFile(*rf); + + for (auto &r : rf->resources) { + if (r.handle) MM::Native::DisposeHandle(r.handle); + } + + if (prev) prev->next = rf->next; + else head = rf->next; + + if (current == rf) current = rf->next; + + delete rf; + + return rv.error(); + } + + tool_return SetResLoad(bool load) + { + res_load = load; + memoryWriteByte(load ? 0xff : 0x00, MacOS::ResLoad); // word or byte? + return SetResError(MacOS::noErr); + } + + + tool_return Get1Resource(resource_file &rf, uint32_t type, uint16_t id) { + + auto &resources = rf.resources; + auto iter = std::lower_bound(resources.begin(), resources.end(), 0, + [type,id](const resource &lhs, int rhs){ + if (lhs.type < type) return true; + if (lhs.type == type && lhs.id < id) return true; + return false; + }); + + if (iter == resources.end()) + return SetResError(MacOS::resNotFound); + + auto &r = *iter; + if (r.type != type || r.id != id) + return SetResError(MacOS::resNotFound); + + auto rv = read_resource(rf, r); + SetResError(rv.error()); + return rv; + } + + + tool_return Get1NamedResource(resource_file &rf, uint32_t type, const std::string &name) { + + auto &resources = rf.resources; + auto iter = std::lower_bound(resources.begin(), resources.end(), 0, + [type](const resource &lhs, int rhs){ + if (lhs.type < type) return true; + return false; + }); + + if (iter == resources.end()) + return SetResError(MacOS::resNotFound); + + for (; iter != resources.end(); ++iter) { + auto &r = *iter; + if (r.type != type) break; + if (r.name == name) { + auto rv = read_resource(rf, r); + SetResError(rv.error()); + return rv; + } + } + return SetResError(MacOS::resNotFound); + } + + + tool_return Get1Resource(uint32_t type, uint16_t id) { + + resource_file *rf = current; + if (rf) return Get1Resource(*rf, type, id); + return SetResError(MacOS::resNotFound); + } + + tool_return Get1NamedResource(uint32_t type, const std::string &name) { + + resource_file *rf = current; + if (rf) return Get1NamedResource(*rf, type, name); + return SetResError(MacOS::resNotFound); + } + + tool_return GetResource(uint32_t type, uint16_t id) { + + for (auto rf = current; rf; rf = rf->next) { + auto rv = Get1Resource(*rf, type, id); + if (!rv.error()) return rv; + } + return SetResError(MacOS::resNotFound); + } + + + tool_return GetNamedResource(uint32_t type, const std::string &name) { + + for (auto rf = current; rf; rf = rf->next) { + auto rv = Get1NamedResource(*rf, type, name); + if (!rv.error()) return rv; + } + return SetResError(MacOS::resNotFound); + } + + +} // Native + + + uint16_t CurResFile(uint16_t trap) + { + + Log("%04x CurResFile()\n", trap); + + uint16_t refNum = 0xffff; + if (current) refNum = current->refnum; + + ToolReturn<2>(-1, refNum); + return SetResError(refNum == 0xffff ? resFNotFound : noErr); + } + + + uint16_t UseResFile(uint16_t trap) + { + uint16_t refNum; + + StackFrame<2>(refNum); + + Log("%04x UseResFile(%04x)\n", trap, refNum); + + // todo -- 0 is the system resource file. + + resource_file *rf; + for (rf = head; rf; rf = rf->next) { + if (rf->refnum == refNum) break; + } + if (rf) current = rf; + + return SetResError(rf ? noErr : resFNotFound); + } + + + + uint16_t GetResInfo(uint16_t trap) + { + // PROCEDURE GetResInfo (theResource: Handle; + // VAR theID: INTEGER; VAR theType: ResType; VAR name: Str255); + + uint32_t theResource; + uint32_t theID; + uint32_t theType; + uint32_t name; + StackFrame<16>(theResource, theID, theType, name); + + Log("%04x GetResInfo(%08x)\n", trap, theResource); + + if (!theResource) return SetResError(resNotFound); + + for (resource_file *rf = head; rf; rf = rf->next) { + for (const auto &r : rf->resources) { + + if (r.handle == theResource) { + if (theID) memoryWriteWord(r.id, theID); + if (theType) memoryWriteLong(r.type, theType); + if (name) ToolBox::WritePString(name, r.name); + + return SetResError(noErr); + } + + } + } + return SetResError(resNotFound); + } + + + uint16_t GetResAttrs(uint16_t trap) + { + // FUNCTION GetResAttrs (theResource: Handle): Integer; + + uint32_t sp; + uint32_t theResource; + + sp = StackFrame<4>(theResource); + + Log("%04x GetResAttrs(%08x)\n", trap, theResource); + + + if (!theResource) return SetResError(resNotFound); + + for (resource_file *rf = head; rf; rf = rf->next) { + for (const auto &r : rf->resources) { + + if (r.handle == theResource) { + ToolReturn<2>(sp, r.attr); + return SetResError(noErr); + } + + } + } + return SetResError(resNotFound); + } + + + + uint16_t DetachResource(uint16_t trap) + { + // PROCEDURE DetachResource (theResource: Handle); + + uint32_t theResource; + StackFrame<4>(theResource); + + Log("%04x DetachResource(%08x)\n", trap, theResource); + + if (!theResource) return SetResError(resNotFound); + + for (resource_file *rf = head; rf; rf = rf->next) { + for (auto &r : rf->resources) { + + if (r.handle == theResource) { + /* + * DetachResource won't let you detach a resource whose resChanged + * attribute has been set; however, ResError will still return noErr. + */ + if ((r.attr & resChanged) == 0) { + r.handle = 0; + MM::Native::HClrRBit(theResource); + } + return SetResError(noErr); + } + } + } + return SetResError(resNotFound); + } + + + uint16_t ReleaseResource(uint16_t trap) + { + // ReleaseResource (theResource: Handle); + + /* + * ------------ + * +0 theResource + * ------------ + * + */ + + uint32_t sp; + uint32_t theResource; + + sp = StackFrame<4>(theResource); + + Log("%04x ReleaseResource(%08x)\n", trap, theResource); + + if (!theResource) return SetResError(resNotFound); + + for (resource_file *rf = head; rf; rf = rf->next) { + for (auto &r : rf->resources) { + + if (r.handle == theResource) { + /* + * ReleaseResource won't let you release a resource whose resChanged + * attribute has been set; however, ResError will still return noErr. + */ + if ((r.attr & resChanged) == 0) { + MM::Native::DisposeHandle(theResource); + r.handle = 0; + } + return SetResError(noErr); + } + } + } + return SetResError(resNotFound); + } + + + + uint16_t HomeResFile(uint16_t trap) + { + // PPCAsm + + // FUNCTION HomeResFile (theResource: Handle): Integer; + + uint32_t sp; + uint32_t theResource; + + sp = StackFrame<4>(theResource); + Log("%04x HomeResFile(%08x)\n", trap, theResource); + + if (!theResource) { + ToolReturn<2>(sp, -1); + return SetResError(resNotFound); + } + + for (resource_file *rf = head; rf; rf = rf->next) { + for (const auto &r : rf->resources) { + + if (r.handle == theResource) { + ToolReturn<2>(sp, rf->refnum); + return SetResError(noErr); + } + + } + } + + + + ToolReturn<2>(sp, -1); + return SetResError(resNotFound); + } + + uint16_t ResError(uint16_t trap) + { + uint32_t sp; + + Log("%04x ResError()\n", trap); + + sp = cpuGetAReg(7); + ToolReturn<2>(sp, memoryReadWord(MacOS::ResErr)); + return 0; + } + + + // SetResLoad (load: BOOLEAN); + uint16_t SetResLoad(uint16_t trap) + { + uint16_t load; + + StackFrame<2>(load); + + Log("%04x SetResLoad(%04x)\n", trap, load); + + res_load = load; + + memoryWriteByte(load ? 0xff : 0x00, MacOS::ResLoad); // word or byte? + return SetResError(0); + } + + + + + +#pragma mark - Open Resource Files + + uint16_t OpenResFile(uint16_t trap) + { + // OpenResFile (fileName: Str255) : INTEGER; + + uint32_t sp; + uint32_t fileName; + + sp = StackFrame<4>(fileName); + + std::string sname = ToolBox::ReadPString(fileName, true); + + Log("%04x OpenResFile(%s)\n", trap, sname.c_str()); + + auto rv = Native::OpenResFile(sname); + + ToolReturn<2>(sp, rv.value_or(-1)); + + return SetResError(rv.error()); + } + + uint16_t HOpenResFile(uint16_t trap) + { + // FUNCTION HOpenResFile (vRefNum: Integer; dirID: LongInt; + // fileName: Str255; permission: SignedByte): Integer; + + uint32_t sp; + + uint16_t vRefNum; + uint32_t dirID; + uint32_t fileName; + uint8_t permission; + + sp = StackFrame<12>(vRefNum, dirID, fileName, permission); + + std::string sname = ToolBox::ReadPString(fileName, true); + + Log("%04x HOpenResFile(%04x, %08x, %s, %04x)\n", + trap, vRefNum, dirID, sname.c_str(), permission); + + if (vRefNum) { + fprintf(stderr, "HOpenResFile: vRefNum not supported yet.\n"); + exit(1); + } + + sname = OS::FSSpecManager::ExpandPath(sname, dirID); + if (sname.empty()) + { + ToolReturn<2>(sp, (uint16_t)-1); + return SetResError(MacOS::dirNFErr); + } + + auto rv = Native::OpenResFile(sname, permission); + + ToolReturn<2>(sp, rv.value_or(-1)); + + return SetResError(rv.error()); + } + + uint16_t OpenRFPerm(uint16_t trap) + { + // FUNCTION OpenRFPerm (fileName: Str255; vRefNum: Integer; + // permission: SignedByte): Integer; + uint32_t sp; + uint32_t fileName; + uint16_t vRefNum; + uint16_t permission; + + sp = StackFrame<8>(fileName, vRefNum, permission); + + std::string sname = ToolBox::ReadPString(fileName, true); + Log("%04x OpenRFPerm(%s, %04x, %04x)\n", + trap, sname.c_str(), vRefNum, permission); + + auto rv = Native::OpenResFile(sname, permission); + + ToolReturn<2>(sp, rv.value_or(-1)); + + return SetResError(rv.error()); + } + + uint16_t FSpOpenResFile(void) + { + // FUNCTION FSpOpenResFile (spec: FSSpec; permission: SignedByte): Integer; + + uint32_t sp; + uint32_t spec; + uint8_t permission; + + sp = StackFrame<6>(spec, permission); + + + int parentID = memoryReadLong(spec + 2); + + std::string sname = ToolBox::ReadPString(spec + 6, false); + + Log(" FSpOpenResFile(%s, %04x)\n", sname.c_str(), permission); + + + sname = OS::FSSpecManager::ExpandPath(sname, parentID); + if (sname.empty()) + { + ToolReturn<2>(sp, (uint16_t)-1); + return SetResError(MacOS::dirNFErr); + } + + auto rv = Native::OpenResFile(sname, permission); + + ToolReturn<2>(sp, rv.value_or(-1)); + + return SetResError(rv.error()); + } + + uint16_t CloseResFile(uint16_t trap) + { + // PROCEDURE CloseResFile (refNum: Integer); + uint16_t refNum; + + StackFrame<2>(refNum); + + Log("%04x CloseResFile(%04x)\n", trap, refNum); + + // If the value of the refNum parameter is 0, it represents the System file and is ignored. + // n.b. -- should close --all-- resources. + + auto rv = Native::CloseResFile(refNum); + return SetResError(rv.error()); + } + + + uint16_t Get1NamedResource(uint16_t trap) + { + // Get1NamedResource (theType: ResType; name: Str255) : Handle; + + /* + * ----------- + * +8 outHandle + * ------------ + * +4 theType + * ------------ + * +0 name + * ------------ + * + */ + + // nb - return address is not on the stack. + + uint32_t sp; + uint32_t theType; + uint32_t name; + + sp = StackFrame<8>(theType, name); + + std::string sname = ToolBox::ReadPString(name); + + Log("%04x Get1NamedResource(%08x ('%s'), %s)\n", + trap, theType, TypeToString(theType).c_str(), sname.c_str()); + + auto rv = Native::Get1NamedResource(theType, sname); + + ToolReturn<4>(sp, rv.value()); + return SetResError(rv.error()); + } + + uint16_t GetNamedResource(uint16_t trap) + { + // FUNCTION GetNamedResource (theType: ResType; name: Str255): Handle; + + uint32_t sp; + uint32_t theType; + uint32_t name; + + sp = StackFrame<8>(theType, name); + + std::string sname = ToolBox::ReadPString(name); + + Log("%04x GetNamedResource(%08x ('%s'), %s)\n", + trap, theType, TypeToString(theType).c_str(), sname.c_str()); + + auto rv = Native::GetNamedResource(theType, sname); + + ToolReturn<4>(sp, rv.value()); + return SetResError(rv.error()); + } + + uint16_t GetResource(uint16_t trap) + { + // GetResource (theType: ResType; theID: Integer): Handle; + + /* + * ----------- + * +6 outHandle + * ------------ + * +2 theType + * ------------ + * +0 theID + * ------------ + * + */ + + // nb - return address is not on the stack. + + uint32_t sp; + uint32_t theType; + uint16_t theID; + + sp = StackFrame<6>(theType, theID); + + Log("%04x GetResource(%08x ('%s'), %04x)\n", + trap, theType, TypeToString(theType).c_str(), theID); + + auto rv = Native::GetResource(theType, theID); + + ToolReturn<4>(sp, rv.value()); + return SetResError(rv.error()); + } + + + uint16_t Get1Resource(uint16_t trap) + { + // Get1Resource (theType: ResType; theID: Integer): Handle; + + /* + * ----------- + * +6 outHandle + * ------------ + * +2 theType + * ------------ + * +0 theID + * ------------ + * + */ + + // nb - return address is not on the stack. + + uint32_t sp; + uint32_t theType; + uint16_t theID; + + sp = StackFrame<6>(theType, theID); + + Log("%04x Get1Resource(%08x ('%s'), %04x)\n", trap, theType, TypeToString(theType).c_str(), theID); + + + auto rv = Native::Get1Resource(theType, theID); + + ToolReturn<4>(sp, rv.value()); + return SetResError(rv.error()); + } + +} // RM + + + + +