2013-07-30 05:06:19 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2013, Kelvin W Sherlock
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
2013-07-30 05:06:19 +00:00
|
|
|
|
*
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* list of conditions and the following disclaimer.
|
2013-07-30 05:06:19 +00:00
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* and/or other materials provided with the distribution.
|
2013-07-30 05:06:19 +00:00
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2013-02-08 03:12:30 +00:00
|
|
|
|
#include "mm.h"
|
2013-02-16 23:51:28 +00:00
|
|
|
|
#include "toolbox.h"
|
2013-02-08 03:12:30 +00:00
|
|
|
|
|
|
|
|
|
#include <cpu/defs.h>
|
|
|
|
|
#include <cpu/CpuModule.h>
|
|
|
|
|
#include <cpu/fmem.h>
|
|
|
|
|
|
|
|
|
|
#include <string>
|
2015-02-17 00:23:12 +00:00
|
|
|
|
#include <cstring>
|
2013-02-08 03:49:20 +00:00
|
|
|
|
#include <deque>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <map>
|
2013-02-08 03:12:30 +00:00
|
|
|
|
|
|
|
|
|
#include <mplite/mplite.h>
|
2013-05-13 02:36:22 +00:00
|
|
|
|
#include <macos/sysequ.h>
|
2013-05-19 01:44:02 +00:00
|
|
|
|
#include <macos/errors.h>
|
2013-02-08 03:12:30 +00:00
|
|
|
|
|
2014-12-15 00:52:08 +00:00
|
|
|
|
#include "stackframe.h"
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
using ToolBox::Log;
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
using MacOS::tool_return;
|
|
|
|
|
using MacOS::macos_error_from_errno;
|
|
|
|
|
using MacOS::macos_error;
|
2015-02-07 17:30:12 +00:00
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
namespace
|
2013-02-08 03:12:30 +00:00
|
|
|
|
{
|
|
|
|
|
mplite_t pool;
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
|
|
|
|
uint8_t *Memory;
|
|
|
|
|
uint32_t MemorySize;
|
2015-01-15 21:35:38 +00:00
|
|
|
|
uint32_t HeapSize;
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
|
|
|
|
// queue of free Handles
|
|
|
|
|
std::deque<uint32_t> HandleQueue;
|
|
|
|
|
|
|
|
|
|
// map of ptr -> size
|
|
|
|
|
std::map<uint32_t, uint32_t> PtrMap;
|
|
|
|
|
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
|
|
|
|
|
2013-02-08 03:49:20 +00:00
|
|
|
|
// map of handle -> size [? just use Ptr map?]
|
2015-02-07 17:30:12 +00:00
|
|
|
|
std::map<uint32_t, MM::HandleInfo> HandleMap;
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
inline macos_error SetMemError(macos_error error)
|
2013-02-08 04:45:29 +00:00
|
|
|
|
{
|
2013-05-13 02:36:22 +00:00
|
|
|
|
memoryWriteWord(error, MacOS::MemErr);
|
2013-02-08 04:45:29 +00:00
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
inline macos_error SetMemError(int16_t error)
|
2015-02-07 17:30:12 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return SetMemError((macos_error)error);
|
2015-02-07 17:30:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-02-08 03:49:20 +00:00
|
|
|
|
bool alloc_handle_block()
|
|
|
|
|
{
|
2013-02-18 02:54:45 +00:00
|
|
|
|
const unsigned HandleCount = 128; // 512 bytes of handle blocks.
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
uint8_t *block = (uint8_t *)mplite_malloc(&pool,
|
2013-02-08 03:49:20 +00:00
|
|
|
|
sizeof(uint32_t) * HandleCount);
|
|
|
|
|
|
|
|
|
|
if (!block) return false;
|
|
|
|
|
|
|
|
|
|
uint32_t hh = block - Memory;
|
|
|
|
|
uint32_t end = hh + 128 * sizeof(uint32_t);
|
|
|
|
|
|
|
|
|
|
for ( ; hh < end; hh += sizeof(uint32_t))
|
|
|
|
|
{
|
|
|
|
|
HandleQueue.push_back(hh);
|
2015-02-18 14:32:01 +00:00
|
|
|
|
}
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 21:37:58 +00:00
|
|
|
|
|
2013-02-08 03:12:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace MM
|
|
|
|
|
{
|
|
|
|
|
|
2016-08-01 18:40:37 +00:00
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct tool_return_base { typedef T type; };
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct tool_return_base<tool_return<T>> { typedef T type; };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class T, class F>
|
|
|
|
|
tool_return<T> with_handle_helper(F &&f, HandleInfo &info, typename std::enable_if<!std::is_void<T>::value>::type* = 0) {
|
|
|
|
|
tool_return<T> rv = f(info);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T, class F>
|
|
|
|
|
tool_return<void> with_handle_helper(F &&f, HandleInfo &info, typename std::enable_if<std::is_void<T>::value>::type* = 0) {
|
|
|
|
|
f(info);
|
|
|
|
|
return tool_return<void>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class F, typename T = typename tool_return_base<typename std::result_of<F(HandleInfo &)>::type>::type>
|
|
|
|
|
tool_return<T>
|
|
|
|
|
__with_handle(uint32_t handle, F &&f)
|
|
|
|
|
{
|
|
|
|
|
const auto iter = HandleMap.find(handle);
|
|
|
|
|
|
|
|
|
|
if (iter == HandleMap.end()) {
|
|
|
|
|
tool_return<T> rv = SetMemError(MacOS::memWZErr);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto &info = iter->second;
|
|
|
|
|
//tool_return<T> rv = f(info);
|
|
|
|
|
tool_return<T> rv = with_handle_helper<T>(std::forward<F>(f), info);
|
|
|
|
|
SetMemError(rv.error());
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-15 21:35:38 +00:00
|
|
|
|
bool Init(uint8_t *memory, uint32_t memorySize, uint32_t globals, uint32_t stack)
|
2013-02-18 02:54:45 +00:00
|
|
|
|
{
|
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
|
|
Memory = memory;
|
|
|
|
|
MemorySize = memorySize;
|
2015-01-15 21:35:38 +00:00
|
|
|
|
HeapSize = memorySize - stack;
|
2013-02-18 02:54:45 +00:00
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
ok = mplite_init(&pool,
|
|
|
|
|
memory + globals,
|
|
|
|
|
memorySize - globals - stack,
|
|
|
|
|
32,
|
2013-02-18 02:54:45 +00:00
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
if (ok != MPLITE_OK) return false;
|
|
|
|
|
|
|
|
|
|
// allocate a handle master block...
|
|
|
|
|
|
|
|
|
|
if (!alloc_handle_block()) return false;
|
|
|
|
|
|
2015-01-15 21:35:38 +00:00
|
|
|
|
|
|
|
|
|
// create system handles for the stack and global space?
|
|
|
|
|
|
2013-02-18 02:54:45 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-17 18:03:03 +00:00
|
|
|
|
namespace Native {
|
|
|
|
|
|
2013-02-18 02:54:45 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
|
|
|
|
|
|
2013-07-05 17:56:06 +00:00
|
|
|
|
// debugger support.
|
|
|
|
|
// print info on an address.
|
|
|
|
|
void MemoryInfo(uint32_t address)
|
|
|
|
|
{
|
|
|
|
|
// 1. check if it's a pointer.
|
|
|
|
|
{
|
|
|
|
|
auto iter = PtrMap.find(address);
|
|
|
|
|
if (iter != PtrMap.end())
|
|
|
|
|
{
|
|
|
|
|
printf("Pointer $%08x Size: $%08x\n", iter->first, iter->second);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. check if it's contained in a pointer
|
|
|
|
|
for (const auto kv : PtrMap)
|
|
|
|
|
{
|
|
|
|
|
if (address < kv.first) continue;
|
|
|
|
|
if (address >= kv.first + kv.second) continue;
|
|
|
|
|
|
|
|
|
|
printf("Pointer $%08x Size: $%08x\n", kv.first, kv.second);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. check if it's a handle.
|
|
|
|
|
{
|
|
|
|
|
auto iter = HandleMap.find(address);
|
|
|
|
|
if (iter != HandleMap.end())
|
|
|
|
|
{
|
|
|
|
|
const HandleInfo &info = iter->second;
|
2015-02-18 14:32:01 +00:00
|
|
|
|
printf("Handle $%08x Pointer: $%08x Size: $%08x Flags: %c %c %c\n",
|
|
|
|
|
iter->first,
|
|
|
|
|
info.address,
|
|
|
|
|
info.size,
|
2013-07-05 17:56:06 +00:00
|
|
|
|
info.locked ? 'L' : ' ',
|
2013-08-16 03:39:08 +00:00
|
|
|
|
info.purgeable ? 'P' : ' ',
|
|
|
|
|
info.resource ? 'R' : ' '
|
2013-07-05 17:56:06 +00:00
|
|
|
|
);
|
|
|
|
|
return;
|
2015-02-18 14:32:01 +00:00
|
|
|
|
}
|
2013-07-05 17:56:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. check if the address is within a handle.
|
|
|
|
|
{
|
|
|
|
|
for (const auto kv : HandleMap)
|
|
|
|
|
{
|
|
|
|
|
const HandleInfo &info = kv.second;
|
|
|
|
|
|
|
|
|
|
if (!info.address) continue;
|
|
|
|
|
|
|
|
|
|
uint32_t begin = info.address;
|
|
|
|
|
uint32_t end = info.address + info.size;
|
|
|
|
|
if (!info.size) end++;
|
|
|
|
|
if (address >= begin && address < end)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
printf("Handle $%08x Pointer: $%08x Size: $%08x Flags: %c %c %c\n",
|
|
|
|
|
kv.first,
|
|
|
|
|
info.address,
|
|
|
|
|
info.size,
|
2013-07-05 17:56:06 +00:00
|
|
|
|
info.locked ? 'L' : ' ',
|
2013-08-16 03:39:08 +00:00
|
|
|
|
info.purgeable ? 'P' : ' ',
|
|
|
|
|
info.resource ? 'R' : ' '
|
2013-07-05 17:56:06 +00:00
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2013-02-18 02:54:45 +00:00
|
|
|
|
|
|
|
|
|
void PrintMemoryStats()
|
|
|
|
|
{
|
|
|
|
|
mplite_print_stats(&pool, std::puts);
|
2013-06-27 02:48:40 +00:00
|
|
|
|
|
|
|
|
|
for (const auto & kv : HandleMap)
|
|
|
|
|
{
|
|
|
|
|
const auto h = kv.first;
|
|
|
|
|
const auto & info = kv.second;
|
2013-08-16 03:39:08 +00:00
|
|
|
|
fprintf(stdout, "%08x %08x %08x %c %c %c\n",
|
2015-02-18 14:32:01 +00:00
|
|
|
|
h,
|
|
|
|
|
info.address,
|
|
|
|
|
info.size,
|
|
|
|
|
info.locked? 'L' : ' ',
|
2013-08-16 03:39:08 +00:00
|
|
|
|
info.purgeable? 'P' : ' ',
|
|
|
|
|
info.resource ? 'R' : ' '
|
|
|
|
|
);
|
2013-06-27 02:48:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-18 02:54:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<uint32_t> NewPtr(uint32_t size, bool clear)
|
2013-02-17 18:03:03 +00:00
|
|
|
|
{
|
|
|
|
|
// native pointers.
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
uint32_t mcptr = 0;
|
2015-01-16 20:38:20 +00:00
|
|
|
|
//if (size == 0) return 0;
|
2013-02-17 18:03:03 +00:00
|
|
|
|
|
|
|
|
|
uint8_t *ptr = nullptr;
|
2015-01-16 20:38:20 +00:00
|
|
|
|
ptr = (uint8_t *)mplite_malloc(&pool, size ? size : 1);
|
2013-02-17 18:03:03 +00:00
|
|
|
|
if (!ptr)
|
|
|
|
|
{
|
2013-05-19 01:44:02 +00:00
|
|
|
|
return SetMemError(MacOS::memFullErr);
|
2013-02-17 18:03:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-17 20:07:32 +00:00
|
|
|
|
if (clear)
|
|
|
|
|
std::memset(ptr, 0, size);
|
|
|
|
|
|
2013-02-17 18:03:03 +00:00
|
|
|
|
mcptr = ptr - Memory;
|
|
|
|
|
PtrMap.emplace(std::make_pair(mcptr, size));
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
SetMemError(0);
|
|
|
|
|
return mcptr;
|
2013-02-17 18:03:03 +00:00
|
|
|
|
}
|
2015-02-18 14:32:01 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> DisposePtr(uint32_t mcptr)
|
2013-02-17 18:03:03 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
auto iter = PtrMap.find(mcptr);
|
|
|
|
|
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == PtrMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-02-17 18:03:03 +00:00
|
|
|
|
PtrMap.erase(iter);
|
|
|
|
|
|
|
|
|
|
uint8_t *ptr = mcptr + Memory;
|
|
|
|
|
|
|
|
|
|
mplite_free(&pool, ptr);
|
|
|
|
|
|
2013-02-21 04:28:35 +00:00
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-02 14:53:22 +00:00
|
|
|
|
/* create a NULL handle (for resource manager) */
|
|
|
|
|
tool_return<uint32_t> NewHandle()
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<hp> NewHandle(uint32_t size, bool clear)
|
2013-02-21 04:28:35 +00:00
|
|
|
|
{
|
|
|
|
|
uint8_t *ptr;
|
|
|
|
|
uint32_t hh;
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
uint32_t handle = 0;
|
|
|
|
|
uint32_t mcptr = 0;
|
2013-02-21 04:28:35 +00:00
|
|
|
|
|
|
|
|
|
if (!HandleQueue.size())
|
|
|
|
|
{
|
|
|
|
|
if (!alloc_handle_block())
|
|
|
|
|
{
|
2013-05-19 01:44:02 +00:00
|
|
|
|
return SetMemError(MacOS::memFullErr);
|
2013-02-21 04:28:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hh = HandleQueue.front();
|
|
|
|
|
HandleQueue.pop_front();
|
|
|
|
|
|
|
|
|
|
ptr = nullptr;
|
|
|
|
|
|
2013-08-03 23:18:50 +00:00
|
|
|
|
// todo -- size 0 should have a ptr to differentiate
|
|
|
|
|
// from purged.
|
2014-12-23 00:58:41 +00:00
|
|
|
|
|
|
|
|
|
// PPCLink calls NewHandle(0) but expects a valid pointer
|
|
|
|
|
// Assertion failed: *fHandle != NULL
|
2013-02-21 04:28:35 +00:00
|
|
|
|
|
2016-08-01 18:40:37 +00:00
|
|
|
|
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);
|
2013-02-21 04:28:35 +00:00
|
|
|
|
|
|
|
|
|
// need a handle -> ptr map?
|
|
|
|
|
HandleMap.emplace(std::make_pair(hh, HandleInfo(mcptr, size)));
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(mcptr, hh);
|
|
|
|
|
handle = hh;
|
2016-08-01 17:56:43 +00:00
|
|
|
|
SetMemError(0);
|
|
|
|
|
return hp{handle, mcptr};
|
2013-02-21 04:28:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> DisposeHandle(uint32_t handle)
|
2013-02-21 04:28:35 +00:00
|
|
|
|
{
|
|
|
|
|
auto iter = HandleMap.find(handle);
|
|
|
|
|
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-02-21 04:28:35 +00:00
|
|
|
|
|
|
|
|
|
HandleInfo info = iter->second;
|
|
|
|
|
|
|
|
|
|
HandleMap.erase(iter);
|
|
|
|
|
|
2013-06-27 02:48:20 +00:00
|
|
|
|
if (info.address)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *ptr = info.address + Memory;
|
2013-02-21 04:28:35 +00:00
|
|
|
|
|
2013-06-27 02:48:20 +00:00
|
|
|
|
mplite_free(&pool, ptr);
|
|
|
|
|
}
|
2013-02-21 04:28:35 +00:00
|
|
|
|
HandleQueue.push_back(handle);
|
|
|
|
|
|
|
|
|
|
return SetMemError(0);
|
2013-02-17 18:03:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-08-03 23:18:50 +00:00
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> ReallocHandle(uint32_t handle, uint32_t logicalSize)
|
2013-08-03 23:18:50 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
auto iter = HandleMap.find(handle);
|
|
|
|
|
|
|
|
|
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
|
|
|
|
|
|
|
|
|
auto& info = iter->second;
|
|
|
|
|
|
|
|
|
|
if (info.locked) return SetMemError(MacOS::memLockedErr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t mcptr = 0;
|
|
|
|
|
|
|
|
|
|
if (logicalSize)
|
|
|
|
|
{
|
|
|
|
|
// todo -- purge & retry on failure.
|
|
|
|
|
|
|
|
|
|
void *address = mplite_malloc(&pool, logicalSize);
|
|
|
|
|
if (!address) return SetMemError(MacOS::memFullErr);
|
|
|
|
|
|
|
|
|
|
mcptr = (uint8_t *)address - Memory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// the handle is not altered in the event of an error.
|
|
|
|
|
if (info.address)
|
|
|
|
|
{
|
|
|
|
|
void *address = Memory + info.address;
|
|
|
|
|
|
|
|
|
|
mplite_free(&pool, address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info.address = mcptr;
|
|
|
|
|
info.size = logicalSize;
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(mcptr, handle);
|
|
|
|
|
|
|
|
|
|
// lock? clear purged flag?
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return MacOS::noErr;
|
2013-08-03 23:18:50 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> SetHandleSize(uint32_t handle, uint32_t newSize)
|
2013-08-03 23:18:50 +00:00
|
|
|
|
{
|
2014-12-22 22:58:35 +00:00
|
|
|
|
if (handle == 0) return SetMemError(MacOS::nilHandleErr);
|
|
|
|
|
|
2013-08-03 23:18:50 +00:00
|
|
|
|
const auto iter = HandleMap.find(handle);
|
|
|
|
|
|
|
|
|
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
|
|
|
|
|
|
|
|
|
auto &info = iter->second;
|
|
|
|
|
|
|
|
|
|
// 0 - no change in size.
|
|
|
|
|
if (info.size == newSize) return SetMemError(0);
|
|
|
|
|
|
|
|
|
|
uint32_t mcptr = info.address;
|
|
|
|
|
uint8_t *ptr = mcptr + Memory;
|
|
|
|
|
|
|
|
|
|
// 1. - resizing to 0.
|
|
|
|
|
if (!newSize)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
if (info.locked)
|
2014-12-23 00:58:41 +00:00
|
|
|
|
{
|
|
|
|
|
//return SetMemError(MacOS::memLockedErr);
|
|
|
|
|
|
|
|
|
|
// ppclink resizes locked handles.
|
|
|
|
|
info.size = 0;
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
2013-08-03 23:18:50 +00:00
|
|
|
|
|
|
|
|
|
// todo -- size 0 should have a ptr to differentiate
|
|
|
|
|
// from purged.
|
|
|
|
|
|
|
|
|
|
mplite_free(&pool, ptr);
|
|
|
|
|
info.address = 0;
|
|
|
|
|
info.size = 0;
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(info.address, handle);
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. - resizing from 0.
|
|
|
|
|
|
|
|
|
|
if (!mcptr)
|
|
|
|
|
{
|
|
|
|
|
if (info.locked) return SetMemError(MacOS::memLockedErr);
|
|
|
|
|
|
|
|
|
|
ptr = (uint8_t *)mplite_malloc(&pool, newSize);
|
|
|
|
|
if (!ptr) return SetMemError(MacOS::memFullErr);
|
|
|
|
|
|
|
|
|
|
mcptr = ptr - Memory;
|
|
|
|
|
info.address = mcptr;
|
|
|
|
|
info.size = newSize;
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(info.address, handle);
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 2; ++i)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// 3. - locked
|
|
|
|
|
if (info.locked)
|
|
|
|
|
{
|
|
|
|
|
if (mplite_resize(&pool, ptr, mplite_roundup(&pool, newSize)) == MPLITE_OK)
|
|
|
|
|
{
|
|
|
|
|
info.size = newSize;
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// 4. - resize.
|
|
|
|
|
|
|
|
|
|
ptr = (uint8_t *)mplite_realloc(&pool, ptr, mplite_roundup(&pool, newSize));
|
|
|
|
|
|
|
|
|
|
if (ptr)
|
|
|
|
|
{
|
|
|
|
|
mcptr = ptr - Memory;
|
|
|
|
|
info.address = mcptr;
|
|
|
|
|
info.size = newSize;
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(info.address, handle);
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "mplite_realloc failed.\n");
|
2015-02-18 14:32:01 +00:00
|
|
|
|
Native::PrintMemoryStats();
|
2013-08-03 23:18:50 +00:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-17 23:01:25 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> HSetRBit(uint32_t handle)
|
|
|
|
|
{
|
|
|
|
|
return __with_handle(handle, [](HandleInfo &info) { info.resource = true; });
|
2013-08-17 23:01:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> HClrRBit(uint32_t handle)
|
2013-08-03 23:17:15 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return __with_handle(handle, [](HandleInfo &info) { info.resource = false; });
|
2013-08-03 23:17:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> HLock(uint32_t handle)
|
2013-08-03 23:17:15 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return __with_handle(handle, [](HandleInfo &info) { info.locked = true; });
|
2013-08-03 23:17:15 +00:00
|
|
|
|
}
|
2013-06-27 02:50:30 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<void> HUnlock(uint32_t handle)
|
2013-08-17 23:01:25 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return __with_handle(handle, [](HandleInfo &info) { info.locked = false; });
|
2013-08-17 23:01:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<uint32_t> GetHandleSize(uint32_t handle)
|
2013-08-17 23:01:25 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return __with_handle(handle, [](const HandleInfo &info){ return info.size; });
|
|
|
|
|
}
|
2013-08-17 23:01:25 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
tool_return<HandleInfo> GetHandleInfo(uint32_t handle)
|
|
|
|
|
{
|
|
|
|
|
return __with_handle(handle, [](const HandleInfo &info){ return info; });
|
2013-08-17 23:01:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-27 02:50:30 +00:00
|
|
|
|
|
2013-02-17 18:03:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
2015-02-07 17:30:12 +00:00
|
|
|
|
#pragma mark --
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark --
|
|
|
|
|
|
2013-02-08 04:44:58 +00:00
|
|
|
|
|
|
|
|
|
uint16_t BlockMove(uint16_t trap)
|
|
|
|
|
{
|
2014-12-18 19:39:48 +00:00
|
|
|
|
// also implements BlockMoveData.
|
|
|
|
|
// BlockMove will flush caches, BlockMoveData will not.
|
2015-02-18 14:32:01 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2013-02-08 04:44:58 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Pointer to source
|
|
|
|
|
* A1 Pointer to destination
|
|
|
|
|
* D0 Number of bytes to copy
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* A0 Address of the new block or NIL
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t source = cpuGetAReg(0);
|
|
|
|
|
uint32_t dest = cpuGetAReg(1);
|
|
|
|
|
uint32_t count = cpuGetDReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x BlockMove(%08x, %08x, %08x)\n",
|
2013-02-08 04:44:58 +00:00
|
|
|
|
trap, source, dest, count);
|
|
|
|
|
|
|
|
|
|
// TODO -- 32-bit clean?
|
|
|
|
|
// TODO -- verify within MemorySize?
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if (source == 0 || dest == 0 || count == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
2015-02-18 14:32:01 +00:00
|
|
|
|
|
2013-02-08 04:44:58 +00:00
|
|
|
|
std::memmove(Memory + dest, Memory + source, count);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-15 05:08:22 +00:00
|
|
|
|
|
|
|
|
|
uint32_t CompactMem(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// todo -- add function to check pool for largest block?
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-15 05:08:22 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* D0: cbNeeded (long word)
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: function result (long word)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
uint32_t cbNeeded = cpuGetDReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x CompactMem(%08x)\n", trap, cbNeeded);
|
2013-02-16 01:33:00 +00:00
|
|
|
|
|
2013-03-30 22:45:20 +00:00
|
|
|
|
|
2013-04-01 03:49:59 +00:00
|
|
|
|
SetMemError(0);
|
2013-03-30 22:45:20 +00:00
|
|
|
|
return mplite_maxmem(&pool);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t MaxMem(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// return largest contiguous free block size.
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-03-30 22:45:20 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* (nothing)
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: function result (long word)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Log("%04x MaxMem()\n", trap);
|
|
|
|
|
|
2013-04-01 03:49:59 +00:00
|
|
|
|
SetMemError(0);
|
2013-03-30 22:45:20 +00:00
|
|
|
|
return mplite_maxmem(&pool);
|
2013-02-15 05:08:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-17 23:05:03 +00:00
|
|
|
|
uint32_t MaxBlock(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
/*
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* The MaxBlock function returns the maximum contiguous space, in bytes, that you
|
|
|
|
|
* could obtain after compacting the current heap zone. MaxBlock does not actually
|
2013-05-17 23:05:03 +00:00
|
|
|
|
* do the compaction.
|
|
|
|
|
*/
|
2015-02-18 14:32:01 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2013-05-17 23:05:03 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* (nothing)
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: function result (long word)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Log("%04x MaxBlock()\n", trap);
|
|
|
|
|
|
|
|
|
|
SetMemError(0);
|
|
|
|
|
return mplite_maxmem(&pool);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-30 22:45:20 +00:00
|
|
|
|
uint32_t FreeMem(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// total free memory.
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-03-30 22:45:20 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* (nothing)
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: function result (long word)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Log("%04x FreeMem()\n", trap);
|
|
|
|
|
|
2013-04-01 03:49:59 +00:00
|
|
|
|
SetMemError(0);
|
2013-03-30 22:45:20 +00:00
|
|
|
|
return mplite_freemem(&pool);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-17 23:05:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-01 03:49:59 +00:00
|
|
|
|
uint16_t ReserveMem(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-04-01 03:49:59 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* D0: cbNeeded (long word)
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: Result code.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t cbNeeded = cpuGetDReg(0);
|
|
|
|
|
uint32_t available;
|
|
|
|
|
|
|
|
|
|
Log("%04x ReserveMem($%08x)\n", trap, cbNeeded);
|
|
|
|
|
|
|
|
|
|
available = mplite_maxmem(&pool);
|
|
|
|
|
// TODO -- if available < cbNeeded, purge handle and retry?
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (available < cbNeeded) return SetMemError(MacOS::memFullErr);
|
2013-04-01 03:49:59 +00:00
|
|
|
|
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-30 22:45:20 +00:00
|
|
|
|
|
2013-02-19 23:28:29 +00:00
|
|
|
|
uint16_t MoveHHi(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-19 23:28:29 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0: Handle to move
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: Result code.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t theHandle = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x MoveHHi(%08x)\n", trap, theHandle);
|
|
|
|
|
|
|
|
|
|
// check if it's valid.
|
|
|
|
|
|
|
|
|
|
auto iter = HandleMap.find(theHandle);
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-02-19 23:28:29 +00:00
|
|
|
|
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-15 05:08:22 +00:00
|
|
|
|
|
2013-06-27 02:50:53 +00:00
|
|
|
|
uint32_t StackSpace(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-06-27 02:50:53 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0: Number of bytes between stack and heap
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t sp = cpuGetAReg(7);
|
|
|
|
|
|
2013-06-28 00:28:20 +00:00
|
|
|
|
Log("%04x StackSpace(%08x)\n", trap);
|
|
|
|
|
|
|
|
|
|
|
2013-06-27 02:50:53 +00:00
|
|
|
|
SetMemError(0);
|
|
|
|
|
|
2014-12-18 20:40:12 +00:00
|
|
|
|
// MemorySize is the top of the heap. stack is after it.
|
2013-06-27 02:50:53 +00:00
|
|
|
|
|
2015-01-15 21:35:38 +00:00
|
|
|
|
return sp - HeapSize;
|
2013-06-27 02:50:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
|
|
|
|
|
#pragma mark Pointers
|
|
|
|
|
|
2013-02-17 18:03:03 +00:00
|
|
|
|
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint16_t NewPtr(uint16_t trap)
|
2013-02-11 01:19:11 +00:00
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-11 01:19:11 +00:00
|
|
|
|
* on entry:
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* D0 Number of logical bytes requested
|
2013-02-11 01:19:11 +00:00
|
|
|
|
*
|
|
|
|
|
* on exit:
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* A0 Address of the new block or NIL
|
2013-02-11 01:19:11 +00:00
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2013-02-17 18:03:03 +00:00
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
bool clear = trap & (1 << 9);
|
|
|
|
|
//bool sys = trap & (1 << 10);
|
2013-02-11 01:19:11 +00:00
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint32_t size = cpuGetDReg(0);
|
2013-02-11 01:19:11 +00:00
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x NewPtr(%08x)\n", trap, size);
|
2013-02-11 01:19:11 +00:00
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
// todo -- separate pools for sys vs non-sys?
|
|
|
|
|
// todo -- NewPtr(0) -- null or empty ptr?
|
2013-02-11 01:19:11 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::NewPtr(size, clear);
|
2013-02-11 01:19:11 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
cpuSetAReg(0, rv.value());
|
|
|
|
|
return rv.error(); //SetMemError(error);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint16_t DisposePtr(uint16_t trap)
|
2013-02-15 04:08:56 +00:00
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-15 04:08:56 +00:00
|
|
|
|
* on entry:
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* A0 Pointer to the nonrelocatable block to be disposed of
|
2013-02-15 04:08:56 +00:00
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint32_t mcptr = cpuGetAReg(0);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x DisposePtr(%08x)\n", trap, mcptr);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::DisposePtr(mcptr);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return rv.error(); //SetMemError(error);
|
2013-02-11 01:19:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint32_t GetPtrSize(uint16_t trap)
|
2013-02-08 03:12:30 +00:00
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-08 04:44:58 +00:00
|
|
|
|
* on entry:
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* A0 pointer
|
2013-02-08 04:44:58 +00:00
|
|
|
|
*
|
2013-02-08 03:12:30 +00:00
|
|
|
|
* on exit:
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* D0 size (32-bit) or error code
|
2013-02-08 04:44:58 +00:00
|
|
|
|
*
|
2013-02-08 03:12:30 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint32_t mcptr = cpuGetAReg(0);
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
2013-02-26 23:32:39 +00:00
|
|
|
|
Log("%08x GetPtrSize(%08x)\n", trap, mcptr);
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
auto iter = PtrMap.find(mcptr);
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == PtrMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-02-08 03:49:20 +00:00
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
return iter->second;
|
2013-02-08 03:12:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 01:33:00 +00:00
|
|
|
|
uint16_t SetPtrSize(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-16 01:33:00 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 pointer
|
|
|
|
|
* D0 new size
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t mcptr = cpuGetAReg(0);
|
|
|
|
|
uint32_t newSize = cpuGetDReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%08x SetPtrSize(%08x, %08x)\n", trap, mcptr, newSize);
|
2013-02-16 01:33:00 +00:00
|
|
|
|
|
|
|
|
|
auto iter = PtrMap.find(mcptr);
|
|
|
|
|
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == PtrMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-02-16 01:33:00 +00:00
|
|
|
|
|
|
|
|
|
uint8_t *ptr = mcptr + Memory;
|
|
|
|
|
|
2015-01-19 15:55:58 +00:00
|
|
|
|
if (mplite_resize(&pool, ptr, mplite_roundup(&pool, newSize)) < 0)
|
2013-02-16 01:33:00 +00:00
|
|
|
|
{
|
2013-05-19 01:44:02 +00:00
|
|
|
|
return SetMemError(MacOS::memFullErr);
|
2013-02-16 01:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
// update the size.
|
|
|
|
|
iter->second = newSize;
|
|
|
|
|
|
2013-02-16 01:33:00 +00:00
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
#pragma mark Handles
|
|
|
|
|
|
2013-02-15 04:08:56 +00:00
|
|
|
|
uint16_t NewHandle(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-15 04:08:56 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* D0 Number of logical bytes requested
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* A0 Address of the new handle or NIL
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool clear = trap & (1 << 9);
|
|
|
|
|
//bool sys = trap & (1 << 10);
|
|
|
|
|
|
|
|
|
|
uint32_t size = cpuGetDReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x NewHandle(%08x)\n", trap, size);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::NewHandle(size, clear);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
cpuSetAReg(0, rv.value().handle);
|
|
|
|
|
return rv.error();
|
2013-02-15 04:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint16_t DisposeHandle(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle to be disposed of
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x DisposeHandle(%08x)\n", trap, hh);
|
2013-02-16 20:37:55 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return Native::DisposeHandle(hh).error();
|
2013-02-16 20:37:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-03-04 02:54:53 +00:00
|
|
|
|
uint16_t EmptyHandle(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-03-04 02:54:53 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle to be disposed of
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
Log("%04x EmptyHandle(%08x)\n", trap, hh);
|
|
|
|
|
|
|
|
|
|
auto iter = HandleMap.find(hh);
|
|
|
|
|
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-03-04 02:54:53 +00:00
|
|
|
|
|
|
|
|
|
auto &info = iter->second;
|
|
|
|
|
if (info.address == 0) return SetMemError(0);
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (info.locked) return SetMemError(MacOS::memLockedErr); // ?
|
2013-03-04 02:54:53 +00:00
|
|
|
|
|
|
|
|
|
void *address = Memory + info.address;
|
|
|
|
|
|
|
|
|
|
mplite_free(&pool, address);
|
|
|
|
|
|
|
|
|
|
info.address = 0;
|
|
|
|
|
info.size = 0;
|
|
|
|
|
|
|
|
|
|
memoryWriteLong(0, hh);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ReallocHandle (h: Handle; logicalSize: Size);
|
2015-02-18 14:32:01 +00:00
|
|
|
|
*
|
2013-03-04 02:54:53 +00:00
|
|
|
|
* ReallocHandle allocates a new relocatable block with a logical
|
|
|
|
|
* size of logicalSize bytes. It then updates handle h by setting
|
|
|
|
|
* its master pointer to point to the new block. The main use of
|
|
|
|
|
* this procedure is to reallocate space for a block that has
|
|
|
|
|
* been purged. Normally h is an empty handle, but it need not
|
|
|
|
|
* be: If it points to an existing block, that block is released
|
|
|
|
|
* before the new block is created.
|
|
|
|
|
*
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* In case of an error, no new block is allocated and handle h is
|
2013-03-04 02:54:53 +00:00
|
|
|
|
* left unchanged.
|
|
|
|
|
*/
|
|
|
|
|
uint16_t ReallocHandle(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-03-04 02:54:53 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle to be disposed of
|
|
|
|
|
* D0 Logical Size
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
uint32_t logicalSize = cpuGetDReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x ReallocHandle(%08x, %08x)\n", trap, hh, logicalSize);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return Native::ReallocHandle(hh, logicalSize).error();
|
2013-08-03 23:18:50 +00:00
|
|
|
|
|
2013-03-04 02:54:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-25 04:20:38 +00:00
|
|
|
|
|
|
|
|
|
uint32_t GetHandleSize(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-25 04:20:38 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 size (32-bit) or error code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2014-12-22 22:58:35 +00:00
|
|
|
|
/*
|
|
|
|
|
* The trap dispatcher sets the condition codes before returning
|
|
|
|
|
* from a trap by testing the low-order word of register D0 with
|
|
|
|
|
* a TST.W instruction. Because the block size returned in D0 by
|
|
|
|
|
* _GetHandleSize is a full 32-bit long word, the word-length
|
|
|
|
|
* test sets the condition codes incorrectly in this case. To
|
|
|
|
|
* branch on the contents of D0, use your own TST.L instruction
|
|
|
|
|
* on return from the trap to test the full 32 bits of the register.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-02-25 04:20:38 +00:00
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
2014-12-22 22:58:35 +00:00
|
|
|
|
Log("%04x GetHandleSize(%08x)\n", trap, hh);
|
|
|
|
|
|
|
|
|
|
if (hh == 0) return SetMemError(MacOS::nilHandleErr); // ????
|
2013-02-25 04:20:38 +00:00
|
|
|
|
|
|
|
|
|
auto iter = HandleMap.find(hh);
|
|
|
|
|
|
2013-05-19 01:44:02 +00:00
|
|
|
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
2013-02-25 04:20:38 +00:00
|
|
|
|
|
|
|
|
|
return iter->second.size;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-26 23:31:43 +00:00
|
|
|
|
uint16_t SetHandleSize(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-26 23:31:43 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 pointer
|
|
|
|
|
* D0 new size
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
uint32_t newSize = cpuGetDReg(0);
|
|
|
|
|
|
2013-06-27 02:49:27 +00:00
|
|
|
|
Log("%04x SetHandleSize(%08x, %08x)\n", trap, hh, newSize);
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
return Native::SetHandleSize(hh, newSize).error();
|
2014-12-20 18:03:02 +00:00
|
|
|
|
}
|
2013-08-03 23:18:50 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
uint32_t RecoverHandle(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// FUNCTION RecoverHandle (p: Ptr): Handle;
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
/*
|
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Master pointer
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* A0 Handle to master pointer’s relocatable block
|
2014-12-20 18:03:02 +00:00
|
|
|
|
* D0 Unchanged
|
|
|
|
|
*
|
|
|
|
|
*/
|
2013-06-27 03:23:22 +00:00
|
|
|
|
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
uint32_t p = cpuGetAReg(0);
|
|
|
|
|
uint32_t hh = 0;
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
Log("%04x RecoverHandle(%08x)\n", trap, p);
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
uint16_t error = MacOS::memBCErr;
|
|
|
|
|
for (const auto kv : HandleMap)
|
2013-02-26 23:31:43 +00:00
|
|
|
|
{
|
2014-12-20 18:03:02 +00:00
|
|
|
|
const HandleInfo &info = kv.second;
|
2013-06-27 02:49:27 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
if (!info.address) continue;
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
uint32_t begin = info.address;
|
|
|
|
|
uint32_t end = info.address + info.size;
|
|
|
|
|
if (!info.size) end++;
|
|
|
|
|
if (p >= begin && p < end)
|
2013-06-27 02:49:27 +00:00
|
|
|
|
{
|
2014-12-20 18:03:02 +00:00
|
|
|
|
hh = kv.first;
|
|
|
|
|
error = MacOS::noErr;
|
|
|
|
|
break;
|
2013-06-27 02:49:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-02-26 23:31:43 +00:00
|
|
|
|
|
2014-12-20 18:03:02 +00:00
|
|
|
|
SetMemError(error);
|
|
|
|
|
cpuSetAReg(0, hh);
|
|
|
|
|
|
|
|
|
|
// return d0 register unchanged.
|
|
|
|
|
return cpuGetDReg(0);
|
2013-02-26 23:31:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-25 04:20:38 +00:00
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
#pragma mark Handle attributes
|
|
|
|
|
|
2013-08-03 23:17:50 +00:00
|
|
|
|
uint16_t HGetState(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 flag byte
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
unsigned flags = 0;
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x HGetState(%08x)\n", trap, hh);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// resouce 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);
|
2015-02-18 14:32:01 +00:00
|
|
|
|
if (info.locked) flags |= (1 << 7);
|
2013-08-03 23:17:50 +00:00
|
|
|
|
|
|
|
|
|
SetMemError(0);
|
|
|
|
|
return flags;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 16:56:33 +00:00
|
|
|
|
uint16_t HSetState(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle
|
|
|
|
|
* D0 flags
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 flag byte
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
uint16_t flags = cpuGetDReg(0);
|
2013-08-03 23:17:50 +00:00
|
|
|
|
|
2015-01-05 16:56:33 +00:00
|
|
|
|
Log("%04x HSetState(%08x, %04x)\n", trap, hh, flags);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2013-02-16 20:37:55 +00:00
|
|
|
|
|
2013-02-25 04:20:38 +00:00
|
|
|
|
uint16_t HPurge(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-25 04:20:38 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x HPurge(%08x)\n", trap, hh);
|
|
|
|
|
|
2016-08-01 18:40:37 +00:00
|
|
|
|
return __with_handle(hh, [](HandleInfo &info){ info.purgeable = true; }).error();
|
2015-01-14 19:26:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t HNoPurge(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2015-01-14 19:26:49 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x HNoPurge(%08x)\n", trap, hh);
|
|
|
|
|
|
2016-08-01 18:40:37 +00:00
|
|
|
|
return __with_handle(hh, [](HandleInfo &info){ info.purgeable = false; }).error();
|
2015-01-14 19:26:49 +00:00
|
|
|
|
|
2013-02-25 04:20:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 20:37:55 +00:00
|
|
|
|
uint16_t HLock(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x HLock(%08x)\n", trap, hh);
|
2013-02-16 20:37:55 +00:00
|
|
|
|
|
2016-08-01 18:40:37 +00:00
|
|
|
|
return __with_handle(hh, [](HandleInfo &info){ info.locked = true; }).error();
|
2013-02-16 20:37:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t HUnlock(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-16 20:37:55 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t hh = cpuGetAReg(0);
|
|
|
|
|
|
2013-02-16 23:51:28 +00:00
|
|
|
|
Log("%04x HUnlock(%08x)\n", trap, hh);
|
2013-02-15 04:08:56 +00:00
|
|
|
|
|
2016-08-01 18:40:37 +00:00
|
|
|
|
return __with_handle(hh, [](HandleInfo &info){ info.locked = false; }).error();
|
2013-02-16 20:37:55 +00:00
|
|
|
|
|
|
|
|
|
}
|
2013-02-08 03:12:30 +00:00
|
|
|
|
|
2013-02-26 23:32:39 +00:00
|
|
|
|
#pragma mark - OS Utility Routines
|
|
|
|
|
|
2013-07-13 23:19:49 +00:00
|
|
|
|
|
|
|
|
|
uint16_t HandToHand(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-07-13 23:19:49 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 source Handle
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* A0 destination Handle
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
2015-01-05 00:12:35 +00:00
|
|
|
|
*/
|
2013-07-13 23:19:49 +00:00
|
|
|
|
|
|
|
|
|
uint32_t srcHandle = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x HandToHand(%08x)\n", trap, srcHandle);
|
|
|
|
|
|
|
|
|
|
auto iter = HandleMap.find(srcHandle);
|
|
|
|
|
if (iter == HandleMap.end())
|
|
|
|
|
return SetMemError(MacOS::memWZErr);
|
|
|
|
|
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
auto const info = iter->second;
|
2013-07-13 23:19:49 +00:00
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::NewHandle(info.size, false);
|
|
|
|
|
|
|
|
|
|
if (!rv.error())
|
2013-07-13 23:19:49 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
std::memmove(memoryPointer(rv.value().pointer), memoryPointer(info.address), info.size);
|
2013-07-13 23:19:49 +00:00
|
|
|
|
}
|
2015-02-18 14:32:01 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
cpuSetAReg(0, rv.value().handle);
|
|
|
|
|
return rv.error(); // SetMemError called by Native::NewHandle.
|
2013-07-13 23:19:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-02-26 23:32:39 +00:00
|
|
|
|
uint16_t PtrToHand(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-26 23:32:39 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 source Pointer
|
|
|
|
|
* D0 size
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* A0 destination pointer
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
2015-01-05 00:12:35 +00:00
|
|
|
|
*/
|
2013-02-26 23:32:39 +00:00
|
|
|
|
|
|
|
|
|
uint32_t mcptr = cpuGetAReg(0);
|
|
|
|
|
uint32_t size = cpuGetDReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x PtrToHand(%08x, %08x)\n", trap, mcptr, size);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::NewHandle(size, false);
|
|
|
|
|
if (!rv.error())
|
2013-02-26 23:32:39 +00:00
|
|
|
|
{
|
2016-08-01 17:56:43 +00:00
|
|
|
|
std::memmove(memoryPointer(rv.value().pointer), memoryPointer(mcptr), size);
|
2013-02-26 23:32:39 +00:00
|
|
|
|
}
|
2015-02-18 14:32:01 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
cpuSetAReg(0, rv.value().handle);
|
|
|
|
|
return rv.error(); // SetMemError called by Native::NewHandle.
|
2013-02-26 23:32:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 00:12:35 +00:00
|
|
|
|
uint16_t PtrAndHand(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// FUNCTION PtrAndHand (pntr: Ptr; hndl: Handle; size: LongInt): OSErr;
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2015-01-05 00:12:35 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 source Pointer
|
|
|
|
|
* A1 dest Handle
|
|
|
|
|
* D0 number of bytes to concatenate
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* A0 destination Handle
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t ptr = cpuGetAReg(0);
|
|
|
|
|
uint32_t handle = cpuGetAReg(1);
|
|
|
|
|
uint32_t size = cpuGetDReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x PtrAndHand(%08x, %08x, %08x)\n", trap, ptr, handle, size);
|
|
|
|
|
|
|
|
|
|
cpuSetAReg(0, handle);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto tmp = Native::GetHandleSize(handle);
|
|
|
|
|
if (tmp.error()) return tmp.error();
|
|
|
|
|
uint32_t oldSize = tmp.value();
|
2015-01-05 00:12:35 +00:00
|
|
|
|
|
|
|
|
|
if ((uint64_t)oldSize + (uint64_t)size > UINT32_MAX)
|
|
|
|
|
return SetMemError(MacOS::memFullErr);
|
|
|
|
|
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto err = Native::SetHandleSize(handle, oldSize + size);
|
|
|
|
|
if (err.error()) return err.error();
|
2015-01-05 00:12:35 +00:00
|
|
|
|
|
|
|
|
|
auto iter = HandleMap.find(handle);
|
|
|
|
|
if (iter == HandleMap.end())
|
|
|
|
|
return SetMemError(MacOS::memWZErr);
|
|
|
|
|
|
2015-02-18 14:32:01 +00:00
|
|
|
|
auto const info = iter->second;
|
2015-01-05 00:12:35 +00:00
|
|
|
|
|
|
|
|
|
std::memmove(memoryPointer(info.address + oldSize), memoryPointer(ptr), size);
|
|
|
|
|
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
2013-02-25 22:33:26 +00:00
|
|
|
|
|
2013-07-13 23:19:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-02-25 22:33:26 +00:00
|
|
|
|
#pragma mark -
|
|
|
|
|
uint32_t StripAddress(uint16_t trap)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-02-25 22:33:26 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* d0 Address to strip
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Address that has been stripped.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// TODO -- in 32-bit mode, this is a nop.
|
|
|
|
|
// have a --24 / --32 flag?
|
|
|
|
|
|
|
|
|
|
uint32_t address = cpuGetDReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x StripAddress(%08x)\n", trap, address);
|
|
|
|
|
|
2015-01-15 21:35:38 +00:00
|
|
|
|
if (MemorySize <= 0x00ffffff)
|
|
|
|
|
address &= 0x00ffffff;
|
|
|
|
|
|
2013-02-25 22:33:26 +00:00
|
|
|
|
return address;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-27 03:50:08 +00:00
|
|
|
|
#pragma mark - zone
|
2013-06-27 02:50:53 +00:00
|
|
|
|
uint16_t HandleZone(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// FUNCTION HandleZone (h: Handle): THz;
|
2015-02-18 14:32:01 +00:00
|
|
|
|
/*
|
2013-06-27 02:50:53 +00:00
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Handle whose zone is to be found
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* A0 Pointer to handle’s heap zone
|
2013-06-27 02:50:53 +00:00
|
|
|
|
* D0 Result code
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t h = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x HandleZone(%08x)\n", trap, h);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (HandleMap.find(h) == HandleMap.end())
|
|
|
|
|
{
|
|
|
|
|
cpuSetAReg(0, 0);
|
|
|
|
|
return SetMemError(MacOS::memWZErr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cpuSetAReg(0, 0);
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
2013-02-25 22:33:26 +00:00
|
|
|
|
|
2013-06-27 03:50:08 +00:00
|
|
|
|
|
|
|
|
|
uint16_t GetZone(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// FUNCTION GetZone: THz;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* on entry:
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* A0 Pointer to current heap zone
|
2013-06-27 03:50:08 +00:00
|
|
|
|
* D0 Result code
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Log("%04x GetZone()\n", trap);
|
|
|
|
|
|
|
|
|
|
cpuSetAReg(0, 0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t SetZone(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// PROCEDURE SetZone (hz: THz);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* on entry:
|
|
|
|
|
* A0 Pointer to new current heap zone
|
|
|
|
|
*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t THz = cpuGetAReg(0);
|
|
|
|
|
Log("%04x SetZone(%08x)\n", trap, THz);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 15:37:21 +00:00
|
|
|
|
uint16_t MaxApplZone(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// PROCEDURE MaxApplZone;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* on exit:
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Log("%04x MaxApplZone\n", trap);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 13:55:10 +00:00
|
|
|
|
uint16_t SetApplLimit(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// PROCEDURE SetApplLimit (zoneLimit: Ptr);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* on entry
|
|
|
|
|
* A0 Pointer to desired new zone limit
|
|
|
|
|
*
|
|
|
|
|
* on exit
|
|
|
|
|
* D0 Result code
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
uint32_t zoneLimit = cpuGetAReg(0);
|
|
|
|
|
|
|
|
|
|
Log("%04x SetApplLimit(%08x)\n", trap, zoneLimit);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-15 00:51:49 +00:00
|
|
|
|
uint32_t PurgeSpace(uint16_t trap)
|
|
|
|
|
{
|
|
|
|
|
// PROCEDURE PurgeSpace (VAR total: LongInt; VAR contig: LongInt);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Registers on exit:
|
2015-02-18 14:32:01 +00:00
|
|
|
|
* A0 Maximum number of contiguous bytes after purge
|
2014-12-15 00:51:49 +00:00
|
|
|
|
* D0 Total free memory after purge
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Log("%04x PurgeSpace()\n", trap);
|
|
|
|
|
|
|
|
|
|
SetMemError(0);
|
|
|
|
|
cpuSetAReg(0, mplite_maxmem(&pool));
|
|
|
|
|
return mplite_freemem(&pool);
|
|
|
|
|
}
|
2014-12-15 00:52:08 +00:00
|
|
|
|
|
|
|
|
|
uint16_t TempMaxMem(void)
|
|
|
|
|
{
|
|
|
|
|
// FUNCTION TempMaxMem (VAR grow: Size): Size;
|
|
|
|
|
|
|
|
|
|
uint32_t address;
|
|
|
|
|
|
|
|
|
|
uint32_t sp = StackFrame<4>(address);
|
|
|
|
|
|
|
|
|
|
Log(" TempMaxMem(%08x)\n", address);
|
|
|
|
|
|
|
|
|
|
if (address) memoryWriteLong(0, address);
|
|
|
|
|
|
|
|
|
|
ToolReturn<4>(sp, mplite_maxmem(&pool));
|
|
|
|
|
|
2014-12-18 19:40:03 +00:00
|
|
|
|
return SetMemError(0);
|
2014-12-15 00:52:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-18 19:40:03 +00:00
|
|
|
|
uint16_t TempFreeMem(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// FUNCTION TempFreeMem: LongInt;
|
|
|
|
|
|
|
|
|
|
Log(" TempFreeMem()\n");
|
|
|
|
|
|
|
|
|
|
ToolReturn<4>(-1, mplite_freemem(&pool));
|
|
|
|
|
|
|
|
|
|
return SetMemError(0);
|
|
|
|
|
}
|
2014-12-28 23:15:27 +00:00
|
|
|
|
|
|
|
|
|
uint16_t TempNewHandle(void)
|
|
|
|
|
{
|
|
|
|
|
// FUNCTION TempNewHandle (logicalSize: Size;
|
|
|
|
|
// VAR resultCode: OSErr): Handle;
|
|
|
|
|
uint32_t logicalSize;
|
|
|
|
|
uint32_t resultCode;
|
|
|
|
|
|
|
|
|
|
uint32_t sp = StackFrame<8>(logicalSize, resultCode);
|
|
|
|
|
|
|
|
|
|
Log(" TempNewHandle(%08x, %08x)\n", logicalSize, resultCode);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::NewHandle(logicalSize, true);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
if (resultCode) memoryWriteWord(rv.error(), resultCode);
|
|
|
|
|
ToolReturn<4>(sp, rv.value().handle);
|
|
|
|
|
return rv.error();
|
2014-12-28 23:15:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t TempHLock(void)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
// PROCEDURE TempHLock (theHandle: Handle; VAR resultCode: OSErr);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
uint32_t theHandle;
|
|
|
|
|
uint32_t resultCode;
|
|
|
|
|
|
|
|
|
|
StackFrame<8>(theHandle, resultCode);
|
|
|
|
|
|
|
|
|
|
Log(" TempHLock(%08x, %08x)\n", theHandle, resultCode);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::HLock(theHandle);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
if (resultCode) memoryWriteWord(rv.error(), resultCode);
|
|
|
|
|
return rv.error();
|
2014-12-28 23:15:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t TempHUnlock(void)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
// PROCEDURE TempHUnlock (theHandle: Handle; VAR resultCode: OSErr);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
uint32_t theHandle;
|
|
|
|
|
uint32_t resultCode;
|
|
|
|
|
|
|
|
|
|
StackFrame<8>(theHandle, resultCode);
|
|
|
|
|
|
|
|
|
|
Log(" TempHUnlock(%08x, %08x)\n", theHandle, resultCode);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::HUnlock(theHandle);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
if (resultCode) memoryWriteWord(rv.error(), resultCode);
|
|
|
|
|
return rv.error();
|
2014-12-28 23:15:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t TempDisposeHandle(void)
|
|
|
|
|
{
|
2015-02-18 14:32:01 +00:00
|
|
|
|
// PROCEDURE TempDisposeHandle (theHandle: Handle; VAR resultCode: OSErr);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
uint32_t theHandle;
|
|
|
|
|
uint32_t resultCode;
|
|
|
|
|
|
|
|
|
|
StackFrame<8>(theHandle, resultCode);
|
|
|
|
|
|
|
|
|
|
Log(" TempDisposeHandle(%08x, %08x)\n", theHandle, resultCode);
|
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
auto rv = Native::DisposeHandle(theHandle);
|
2014-12-28 23:15:27 +00:00
|
|
|
|
|
2016-08-01 17:56:43 +00:00
|
|
|
|
if (resultCode) memoryWriteWord(rv.error(), resultCode);
|
|
|
|
|
return rv.error();
|
2014-12-28 23:15:27 +00:00
|
|
|
|
}
|
2014-07-24 15:37:21 +00:00
|
|
|
|
}
|