mpw/toolbox/rm.cpp

407 lines
7.3 KiB
C++
Raw Normal View History

2013-02-21 04:28:55 +00:00
#include <string>
//#include <unordered_map>
#include <list>
#include <CoreServices/CoreServices.h>
2013-02-07 04:44:12 +00:00
#include "rm.h"
2013-02-14 04:07:33 +00:00
#include "toolbox.h"
2013-02-19 23:28:58 +00:00
#include "mm.h"
2013-06-24 00:42:16 +00:00
#include "os_internal.h"
2013-02-07 04:44:12 +00:00
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
#include <cpu/fmem.h>
2013-05-13 02:36:22 +00:00
#include <macos/sysequ.h>
2013-06-24 00:42:16 +00:00
#include <macos/errors.h>
2013-02-21 04:28:55 +00:00
2013-02-16 01:42:20 +00:00
#include "stackframe.h"
2013-02-07 04:44:12 +00:00
2013-02-16 23:51:28 +00:00
using ToolBox::Log;
2013-06-24 00:42:16 +00:00
using namespace OS::Internal;
2013-02-19 23:28:58 +00:00
namespace
{
2013-02-21 04:28:55 +00:00
#if 0
struct ResEntry
{
ResEntry(uint32_t type = 0, uint32_t id = 0) :
resType(type), resID(id)
{}
uint32_t resType;
uint32_t resID;
uint32_t handle;
};
std::list<ResEntry> ResourceMapList;
#endif
// sigh... really need to create a resmap for every open
// resource file and update that with the pointer.
2013-02-26 23:33:21 +00:00
inline uint16_t SetResError(uint16_t error)
{
2013-05-13 02:36:22 +00:00
memoryWriteWord(error, MacOS::ResErr);
2013-02-26 23:33:21 +00:00
return error;
}
2013-02-19 23:28:58 +00:00
std::string TypeToString(uint32_t type)
{
char tmp[5] = { 0, 0, 0, 0, 0};
for (unsigned i = 0; i < 4; ++i)
{
char c = type & 0xff;
type >>= 8;
c = isprint(c) ? c : '.';
tmp[3 - i] = c;
}
return std::string(tmp);
}
2013-02-21 04:28:55 +00:00
2013-03-27 03:54:08 +00:00
}
namespace RM
{
2013-02-21 04:28:55 +00:00
2013-03-27 03:54:08 +00:00
namespace Native
{
2013-02-21 04:28:55 +00:00
2013-03-27 03:54:08 +00:00
uint16_t GetResource(uint32_t type, uint16_t id, uint32_t &theHandle)
{
uint32_t ptr;
uint16_t error;
Handle nativeHandle;
uint32_t size;
theHandle = 0;
switch (type)
{
case 0x76657273: // 'vers';
case 0x48455841: // 'HEXA'
case 0x53545220: // 'STR '
case 0x53545223: // 'STR#' (reziigs)
case 0x59414343: // 'YACC' (pascaliigs)
2013-04-11 01:20:35 +00:00
case 0x72547970: // 'rTyp' (rezIIgs)
case 0x756e6974: // 'unit' (Pascal)
2013-03-27 03:54:08 +00:00
break;
default:
return SetResError(resNotFound);
}
nativeHandle = ::Get1Resource(type, id);
if (!nativeHandle) return SetResError(resNotFound);
size = ::GetHandleSize(nativeHandle);
error = MM::Native::NewHandle(size, false, theHandle, ptr);
if (!theHandle)
{
::ReleaseResource(nativeHandle);
return error;
}
std::memcpy(memoryPointer(ptr), *(void **)nativeHandle, size);
::ReleaseResource(nativeHandle);
return 0;
}
2013-02-21 04:28:55 +00:00
}
2013-02-26 23:33:21 +00:00
uint16_t CloseResFile(uint16_t trap)
{
uint16_t refNum;
StackFrame<2>(refNum);
Log("%04x CloseResFile(%04x)\n", trap, refNum);
return SetResError(resFNotFound);
}
2013-02-08 03:12:30 +00:00
uint16_t Get1NamedResource(uint16_t trap)
2013-02-07 04:44:12 +00:00
{
// 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;
2013-02-26 23:30:25 +00:00
uint32_t resourceHandle = 0;
2013-02-16 01:42:20 +00:00
sp = StackFrame<8>(theType, name);
2013-02-07 04:44:12 +00:00
2013-02-14 04:07:33 +00:00
std::string sname = ToolBox::ReadPString(name);
2013-02-07 04:44:12 +00:00
2013-02-16 23:51:28 +00:00
Log("%04x Get1NamedResource(%08x, %s)\n", trap, theType, sname.c_str());
2013-02-07 04:44:12 +00:00
2013-02-26 23:30:25 +00:00
ToolReturn<4>(sp, resourceHandle);
return SetResError(resourceHandle ? 0 : resNotFound);
2013-02-07 04:44:12 +00:00
}
2013-02-14 04:07:33 +00:00
2013-02-19 23:28:58 +00:00
2013-02-14 04:07:33 +00:00
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;
2013-03-27 03:54:08 +00:00
uint32_t d0;
2013-02-14 04:07:33 +00:00
2013-02-21 04:28:55 +00:00
uint32_t resourceHandle;
2013-02-16 01:42:20 +00:00
sp = StackFrame<6>(theType, theID);
2013-02-14 04:07:33 +00:00
2013-02-19 23:28:58 +00:00
Log("%04x GetResource(%08x ('%s'), %04x)\n", trap, theType, TypeToString(theType).c_str(), theID);
2013-02-21 04:28:55 +00:00
2013-03-27 03:54:08 +00:00
d0 = Native::GetResource(theType, theID, resourceHandle);
2013-02-21 04:28:55 +00:00
ToolReturn<4>(sp, resourceHandle);
2013-03-27 03:54:08 +00:00
return d0;
2013-02-19 23:28:58 +00:00
}
2013-02-21 04:28:55 +00:00
2013-02-19 23:28:58 +00:00
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;
2013-02-21 04:28:55 +00:00
uint32_t resourceHandle;
2013-03-27 03:54:08 +00:00
uint32_t d0;
2013-02-21 04:28:55 +00:00
2013-02-19 23:28:58 +00:00
sp = StackFrame<6>(theType, theID);
Log("%04x Get1Resource(%08x ('%s'), %04x)\n", trap, theType, TypeToString(theType).c_str(), theID);
2013-02-14 04:07:33 +00:00
2013-03-27 03:54:08 +00:00
d0 = Native::GetResource(theType, theID, resourceHandle);
2013-02-21 04:28:55 +00:00
ToolReturn<4>(sp, resourceHandle);
2013-03-27 03:54:08 +00:00
return d0;
2013-02-14 04:07:33 +00:00
}
2013-02-19 23:28:58 +00:00
uint16_t ReleaseResource(uint16_t trap)
{
// ReleaseResource (theResource: Handle);
/*
* ------------
* +0 theResource
* ------------
*
*/
2013-02-21 04:28:55 +00:00
uint32_t sp;
uint32_t theResource;
2013-02-19 23:28:58 +00:00
2013-02-21 04:28:55 +00:00
sp = StackFrame<4>(theResource);
2013-02-19 23:28:58 +00:00
2013-02-21 04:28:55 +00:00
Log("%04x ReleaseResource(%08x)\n", trap, theResource);
2013-02-19 23:28:58 +00:00
2013-02-26 23:33:21 +00:00
return SetResError(0);
}
uint16_t ResError(uint16_t trap)
{
Log("%04x ResError()\n", trap);
2013-05-13 02:36:22 +00:00
return memoryReadWord(MacOS::ResErr);
2013-02-26 23:33:21 +00:00
}
// SetResLoad (load: BOOLEAN);
uint16_t SetResLoad(uint16_t trap)
{
uint16_t load;
StackFrame<2>(load);
Log("%04x SetResLoad(%04x)\n", trap, load);
2013-05-13 02:36:22 +00:00
memoryWriteByte(load ? 0xff : 0x00, MacOS::ResLoad); // word or byte?
2013-02-21 04:28:55 +00:00
return 0;
2013-02-19 23:28:58 +00:00
}
2013-02-26 23:33:21 +00:00
uint16_t OpenResFile(uint16_t trap)
{
// OpenResFile (fileName: Str255) : INTEGER;
uint32_t sp;
uint32_t fileName;
sp = StackFrame<4>(fileName);
2013-06-24 00:42:16 +00:00
std::string sname = ToolBox::ReadPString(fileName, true);
2013-02-26 23:33:21 +00:00
Log("%04x OpenResFile(%s)\n", trap, sname.c_str());
ToolReturn<2>(sp, (uint16_t)-1);
return SetResError(resFNotFound);
}
2013-03-03 01:53:54 +00:00
uint16_t CurResFile(uint16_t trap)
{
Log("%04x CurResFile()\n", trap);
ResFileRefNum refNum = ::CurResFile();
ToolReturn<2>(-1, refNum);
return SetResError(::ResError());
}
2013-03-04 02:55:33 +00:00
uint16_t UseResFile(uint16_t trap)
{
uint16_t resFile;
StackFrame<2>(resFile);
Log("%04x UseResFile(%04x)\n", trap, resFile);
::UseResFile(resFile);
return SetResError(::ResError());
}
2013-03-03 01:53:54 +00:00
2013-06-24 00:42:16 +00:00
uint16_t CreateResFile(uint16_t trap)
{
// PROCEDURE CreateResFile (fileName: Str255);
/*
* CreateResFile creates a resource file containing no resource
* data. If there's no file at all with the given name, it also
* creates an empty data fork for the file. If there's already a
* resource file with the given name (that is, a resource fork
* that isn't empty), CreateResFile will do nothing and the
* ResError function will return an appropriate Operating System
* result code.
*/
// FSCreateResourceFile uses the parent FSRef + a file name.
uint32_t fileName;
FSRef ref;
OSErr error;
int fd;
StackFrame<4>(fileName);
std::string sname = ToolBox::ReadPString(fileName, true);
Log("%04x CreateResFile(%s)\n", trap, sname.c_str());
if (!sname.length()) return SetResError(MacOS::paramErr);
// 1. if the file exists, call FSCreateResourceFork on the file.
// 2. if the file does not exist, create the file then call
// FSCreateResourceFork
error = FSPathMakeRef((const UInt8 *)sname.c_str(), &ref, NULL);
if (error != noErr)
{
return SetResError(error);
}
fd = open(sname.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd < 0)
{
if (errno != EEXIST) return SetResError(errno_to_oserr(errno));
}
if (fd >= 0) close(fd);
HFSUniStr255 fork = {0,{0}};
FSGetResourceForkName(&fork);
error = FSCreateResourceFork(&ref, fork.length, fork.unicode, 0);
return SetResError(error);
}
2013-03-03 01:53:54 +00:00
2013-02-26 23:33:21 +00:00
// todo -- move since it's not RM related.
2013-02-16 01:42:20 +00:00
uint16_t UnloadSeg(uint16_t trap)
{
// UnloadSeg (routineAddr: Ptr);
/*
* ------------
* +0 routineAddr
* ------------
*
*/
uint32_t sp;
uint32_t routineAddr;
sp = StackFrame<4>(routineAddr);
2013-02-16 23:51:28 +00:00
Log("%04x UnloadSeg(%08x)\n", trap, routineAddr);
2013-02-16 01:42:20 +00:00
return 0;
}
2013-02-07 04:44:12 +00:00
}