Exemplo n.º 1
0
Arquivo: mm.cpp Projeto: iKarith/mpw
	/*
	 * ReallocHandle (h: Handle; logicalSize: Size);
	 *
	 * 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.
	 *
	 * In case of an error, no new block is allocated and handle h is
	 * left unchanged.
	 */
	uint16_t ReallocHandle(uint16_t trap)
	{
		/*
		 * 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);

		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
	}
Exemplo n.º 2
0
static void fhfileOpen(void) {
  if (cpuGetDReg(0) < FHFILE_MAX_DEVICES) {
    memoryWriteByte(7, cpuGetAReg(1) + 8);                     /* ln_type (NT_REPLYMSG) */
    memoryWriteByte(0, cpuGetAReg(1) + 31);                    /* io_error */
    memoryWriteLong(cpuGetDReg(0), cpuGetAReg(1) + 24);                 /* io_unit */
    memoryWriteLong(memoryReadLong(cpuGetAReg(6) + 32) + 1, cpuGetAReg(6) + 32);  /* LIB_OPENCNT */
    cpuSetDReg(0, 0);                              /* ? */
  }
  else {
    memoryWriteLong(-1, cpuGetAReg(1) + 20);            
    memoryWriteByte(-1, cpuGetAReg(1) + 31);                   /* io_error */
    cpuSetDReg(0, -1);                             /* ? */
  }
}
Exemplo n.º 3
0
static void cpuFrame2(UWO vector_offset, ULO pc)
{
  // save inst address
  cpuSetAReg(7, cpuGetAReg(7) - 4);
  memoryWriteLong(cpuGetOriginalPC(), cpuGetAReg(7));
  cpuFrame4Words(0x2000, vector_offset, pc);
}
Exemplo n.º 4
0
static BYT fhfileWrite(ULO index)
{
  ULO dest = memoryReadLong(cpuGetAReg(1) + 40);
  ULO offset = memoryReadLong(cpuGetAReg(1) + 44);
  ULO length = memoryReadLong(cpuGetAReg(1) + 36);

  if (fhfile_devs[index].readonly ||
    ((offset + length) > fhfile_devs[index].size))
  {
    return -3;
  }
  fhfileSetLed(true);
#ifdef RETRO_PLATFORM
  if(RP.GetHeadlessMode())
     RP.PostHardDriveLED(index, true, true);
#endif
  fseek(fhfile_devs[index].F, offset, SEEK_SET);
  fwrite(memoryAddressToPtr(dest),1, length, fhfile_devs[index].F);
  memoryWriteLong(length, cpuGetAReg(1) + 32);
  fhfileSetLed(false);
 #ifdef RETRO_PLATFORM
  if(RP.GetHeadlessMode())
     RP.PostHardDriveLED(index, false, true);
#endif
  return 0;
}
Exemplo n.º 5
0
Arquivo: mm.cpp Projeto: iKarith/mpw
	uint16_t EmptyHandle(uint16_t trap)
	{
		/*
		 * 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);

		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;
	}
Exemplo n.º 6
0
static void cpuFrameGroup2(UWO vector_offset, ULO pcPtr)
{
  // save PC
  cpuSetAReg(7, cpuGetAReg(7) - 4);
  memoryWriteLong(pcPtr, cpuGetAReg(7));

  // save SR
  cpuSetAReg(7, cpuGetAReg(7) - 2);
  memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));

  // fault address, skip ireg
  cpuSetAReg(7, cpuGetAReg(7) - 6);
  memoryWriteLong(memory_fault_address, cpuGetAReg(7));

  cpuSetAReg(7, cpuGetAReg(7) - 2);
  memoryWriteLong(memory_fault_read << 4, cpuGetAReg(7));
}
Exemplo n.º 7
0
static void cpuFrameGroup1(UWO vector_offset, ULO pcPtr)
{
  // save PC
  cpuSetAReg(7, cpuGetAReg(7) - 4);
  memoryWriteLong(pcPtr, cpuGetAReg(7));

  // save SR
  cpuSetAReg(7, cpuGetAReg(7) - 2);
  memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
}
Exemplo n.º 8
0
	uint32_t ftrap_get_font_info(uint32_t name, uint32_t parm)
	{
		// get_font_info(const char *name, uint32 *fontSize)

		std::string sname = ToolBox::ReadCString(name, true);

		Log("     get_font_info(%s, %04x)\n", sname.c_str(), parm);

		// default to 9pt
		if (parm) memoryWriteLong(9, parm);
		return 0;
	}
Exemplo n.º 9
0
static void cpuFrame4Words(UWO frame_code, UWO vector_offset, ULO pc)
{
  // save vector_offset word
  cpuSetAReg(7, cpuGetAReg(7) - 2);
  memoryWriteWord(frame_code | vector_offset, cpuGetAReg(7));

  // save PC
  cpuSetAReg(7, cpuGetAReg(7) - 4);
  memoryWriteLong(pc, cpuGetAReg(7));

  // save SR
  cpuSetAReg(7, cpuGetAReg(7) - 2);
  memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
}
Exemplo n.º 10
0
Arquivo: mm.cpp Projeto: iKarith/mpw
	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));

		return SetMemError(0);
	}
Exemplo n.º 11
0
Arquivo: mm.cpp Projeto: iKarith/mpw
		uint16_t NewHandle(uint32_t size, bool clear, uint32_t &handle, uint32_t &mcptr)
		{
			uint8_t *ptr;
			uint32_t hh;

			handle = 0;
			mcptr = 0;

			if (!HandleQueue.size())
			{
				if (!alloc_handle_block())
				{
					return SetMemError(MacOS::memFullErr);
				}
			}

			hh = HandleQueue.front();
			HandleQueue.pop_front();

			ptr = nullptr;

			// 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;
			return SetMemError(0);
		}
Exemplo n.º 12
0
	uint32_t ftrap_get_tab_info(uint32_t name, uint32_t parm)
	{
		// get_tab_info(const char *name, uint32_t *tabSize)

		// hard code for now.
		// Could check xattr for actual value.
		// That would be rather pointless unless some editor respected
		// it.
		// Could check an environment variable.

		std::string sname = ToolBox::ReadCString(name, true);

		Log("     get_tab_info(%s)\n", sname.c_str());


		if (parm) memoryWriteLong(8, parm);
		return 0;
	}
Exemplo n.º 13
0
Arquivo: mm.cpp Projeto: iKarith/mpw
		uint16_t ReallocHandle(uint32_t handle, uint32_t logicalSize)
		{

			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?

			return 0;

		}
Exemplo n.º 14
0
static void fhfileClose(void) {
  memoryWriteLong(memoryReadLong(cpuGetAReg(6) + 32) - 1, cpuGetAReg(6) + 32);    /* LIB_OPENCNT */
  cpuSetDReg(0, 0);                                /* ? */
}
Exemplo n.º 15
0
Arquivo: mpw.cpp Projeto: iKarith/mpw
	uint16_t Init(int argc, char **argv)
	{
		/*
		FDTable.resize(16);

		FDTable[STDIN_FILENO] = 1;
		FDTable[STDOUT_FILENO] = 1;
		FDTable[STDERR_FILENO] = 1;
		*/

		/*
		OS::Internal::FDTable.resize(3);
		FDTable[STDIN_FILENO].refcount = 1;
		FDTable[STDIN_FILENO].text = true;

		FDTable[STDOUT_FILENO].refcount = 1;
		FDTable[STDOUT_FILENO].text = true;

		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;


		std::string command = argv[0];

		command = ToolBox::UnixToMac(command);
		//std::replace(command.begin(), command.end(), '/', ':');

		argv[0] = basename(argv[0]);


		// 0x0910 CurApName
		{
			char str32[32];

			char * name = argv[0];
			int l = strlen(name);
			l = std::min(l, 32);
			str32[0] = l;
			std::memcpy(str32 + 1, name, l);
			while (l < 32) str32[l++] = 0;

			std::memcpy(memoryPointer(MacOS::CurApName), str32, 32);
		}


		uint32_t argvptr = 0;
		uint32_t envptr = 0;
		uint32_t ioptr = 0;
		uint32_t devptr = 0;
		uint32_t fptr = 0;

		uint16_t error;

		// create the argv-data.
		{
			uint32_t size = 0;

			size = 4 * (argc + 1); // argv data.

			for (int i = 0; i < argc; ++i)
			{
				int l = strlen(argv[i]) + 1;
				if (l & 0x01) l++;
				size += l;
			}

			error = MM::Native::NewPtr(size, true, argvptr);
			if (error) return error;


			uint8_t *xptr = memoryPointer(argvptr);
			uint32_t offset = 0;

			offset = 4 * (argc + 1);

			for (int i = 0; i < argc; ++i)
			{
				memoryWriteLong(argvptr + offset, argvptr + 4 * i);

				// just use strcat?
				int l = strlen(argv[i]) + 1;
				if (l & 0x01) l++;

				strcpy((char *)xptr + offset, argv[i]);

				offset += l;
			}

			// null-terminate it.
			memoryWriteLong(0, argvptr + 4 * argc);

		}

		// environment
		{
			Environment.emplace(std::string("Command"), command);

			std::deque<std::string> e;

			for (const auto &iter : Environment)
			{
				std::string tmp;
				tmp.append(iter.first);
				tmp.push_back(0);
				tmp.append(iter.second);
				e.emplace_back(std::move(tmp));
			}


			uint32_t size = 0;
			for (const std::string &s : e)
			{
				int l = s.length() + 1;
				if (l & 0x01) l++;
				size = size + l + 4;
			}

			size += 4; // space for null terminator.

			error = MM::Native::NewPtr(size, true, envptr);
			if (error) return error;


			uint8_t *xptr = memoryPointer(envptr);
			uint32_t offset = 0;

			offset = 4 * (e.size() + 1);
			unsigned i = 0;
			for (const std::string &s : e)
			{
				// ptr
				memoryWriteLong(envptr + offset, envptr + i * 4);

				int l = s.length() + 1;

				std::memcpy(xptr + offset, s.c_str(), l);

				if (l & 0x01) l++;
				offset += l;
				++i;
			}


			// null-terminate it.
			memoryWriteLong(0, envptr + 4 * e.size());
		}

		// ftable
		{
			// these are ftraps for emulated/native function ptrs.
			uint32_t size = 6 * 4;

			error = MM::Native::NewPtr(size, true, fptr);

			if (error) return error;

			memoryWriteWord(fQuit, fptr + 0);
			memoryWriteWord(0x4E75, fptr + 2); // rts

			memoryWriteWord(fAccess, fptr + 4);
			memoryWriteWord(0x4E75, fptr + 6); // rts

			memoryWriteWord(fClose, fptr + 8);
			memoryWriteWord(0x4E75, fptr + 10); // rts

			memoryWriteWord(fRead, fptr + 12);
			memoryWriteWord(0x4E75, fptr + 14); // rts

			memoryWriteWord(fWrite, fptr + 16);
			memoryWriteWord(0x4E75, fptr + 18); // rts

			memoryWriteWord(fIOCtl, fptr + 20);
			memoryWriteWord(0x4E75, fptr + 22); // rts

		}


		// dev table
		{
			uint32_t size = 0x78;

			error = MM::Native::NewPtr(size, true, devptr);

			if (error) return error;

			memoryWriteLong(0x46535953, devptr + 0); // 'FSYS'
			memoryWriteLong(fptr + 4, devptr + 4);
			memoryWriteLong(fptr + 8, devptr + 8);
			memoryWriteLong(fptr + 12, devptr + 12);
			memoryWriteLong(fptr + 16, devptr + 16);
			memoryWriteLong(fptr + 20, devptr + 20);

			memoryWriteLong(0x45434f4e, devptr + 24); // 'ECON' -- not implemented.
			memoryWriteLong(0x53595354, devptr + 48); // 'SYST' -- not implemented.

		}

		// io table.
		{

			uint32_t size = 0x3c;
			uint32_t ptr;

			error = MM::Native::NewPtr(size, true, ioptr);

			if (error) return error;

			ptr = ioptr;
			// stdin
			memoryWriteWord(0x0001, ptr + 0); // open flags (read)
			memoryWriteWord(0x0000, ptr + 2); // os err
			memoryWriteLong(devptr, ptr + 4); // -> 'FSYS'
			memoryWriteLong(STDIN_FILENO, ptr + 8); // cookie
			memoryWriteLong(0, ptr + 12); // transfer count.
			memoryWriteLong(0, ptr + 16); // buffer

			ptr = ioptr + 20;
			// stdout
			memoryWriteWord(0x0002, ptr + 0); // open flags (write)
			memoryWriteWord(0x0000, ptr + 2); // os err
			memoryWriteLong(devptr, ptr + 4); // -> 'FSYS'
			memoryWriteLong(STDOUT_FILENO, ptr + 8); // cookie
			memoryWriteLong(0, ptr + 12); // transfer count.
			memoryWriteLong(0, ptr + 16); // buffer

			ptr = ioptr + 40;
			// stderr
			memoryWriteWord(0x0002, ptr + 0); // open flags (write)
			memoryWriteWord(0x0000, ptr + 2); // os err
			memoryWriteLong(devptr, ptr + 4); // -> 'FSYS'
			memoryWriteLong(STDERR_FILENO, ptr + 8); // cookie
			memoryWriteLong(0, ptr + 12); // transfer count.
			memoryWriteLong(0, ptr + 16); // buffer

		}



		uint32_t mpi = 0;

		error = MM::Native::NewPtr(8 + 0x30, true, mpi);
		if (error) return error;

		MacProgramInfo = mpi + 8;

		memoryWriteLong(0x4d50474d, mpi); // 'MPGM' - magic
		memoryWriteLong(mpi + 8, mpi + 4);

		memoryWriteLong(mpi, 0x0316);

		mpi += 8;
		memoryWriteWord(0x5348, mpi + 0x00); // 'SH' - more magic

		memoryWriteLong(argc, mpi + 0x02);
		memoryWriteLong(argvptr, mpi + 0x06);
		memoryWriteLong(envptr, mpi + 0x0a);

		// 0x0e = exit code

		// ??? default fd table size?
		memoryWriteWord(0x190, mpi + 0x1a);

		// io table - stdin/stdout/stderr
		memoryWriteLong(ioptr, mpi + 0x1c);

		// device table
		memoryWriteLong(devptr, mpi + 0x20);


		return 0;
	}
Exemplo n.º 16
0
static void fhfileWriteProt(ULO index) {
  memoryWriteLong(fhfile_devs[index].readonly, cpuGetAReg(1) + 32);
}
Exemplo n.º 17
0
static void fhfileGetDriveType(ULO index) {
  memoryWriteLong(1, cpuGetAReg(1) + 32);
}
Exemplo n.º 18
0
Arquivo: mm.cpp Projeto: iKarith/mpw
		uint16_t SetHandleSize(uint32_t handle, uint32_t newSize)
		{
			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;

			// 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)
			{
				if (info.locked)
				{
					//return SetMemError(MacOS::memLockedErr);

					// ppclink resizes locked handles.
					info.size = 0;
					return SetMemError(0);
				}

				// 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");
				Native::PrintMemoryStats();

				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);

		}
Exemplo n.º 19
0
static void fhfileIgnore(ULO index) {
  memoryWriteLong(0, cpuGetAReg(1) + 32);
  cpuSetDReg(0, 0);
}
Exemplo n.º 20
0
static void fhfileGetNumberOfTracks(ULO index) {
  memoryWriteLong(fhfile_devs[index].tracks, cpuGetAReg(1) + 32);
}
Exemplo n.º 21
0
/*


	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 = 0;
		std::memset(&f, 0, sizeof(f));

		f.flags = memoryReadWord(parm);


		nativeFlags = 0;
		switch (f.flags & 0x03)
		{
			case 0x01:
				nativeFlags = O_RDONLY;
				break;
			case 0x02:
				nativeFlags = O_WRONLY;
				break;
			case 0x00: // ????
			case 0x03:
				nativeFlags = O_RDWR;
				break;
		}

		if (f.flags & kO_APPEND) nativeFlags |= O_APPEND;
		if (f.flags & kO_CREAT) nativeFlags |= O_CREAT;
		if (f.flags & kO_TRUNC) nativeFlags |= O_TRUNC;
		if (f.flags & kO_EXCL) nativeFlags |= O_EXCL;


		sname = ToolBox::ReadCString(name, true);
		std::string xname = sname;

		Log("     open(%s, %04x)\n", sname.c_str(), f.flags);


		if (f.flags & kO_RSRC) {

			// 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 an errno.
			d0 = 0x40000000 | mpw_errno_from_errno();
			f.error = MacOS::ioErr;
			f.cookie = 0;
		}
		else
		{
			d0 = 0;
			f.error = 0;
			f.cookie = fd;


			// 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 (OS::IsTextFile(sname)) f.flags &= ~kO_BINARY;
			if (OS::IsBinaryFile(sname)) f.flags |= kO_BINARY;

			if (f.flags & kO_RSRC) f.flags |= kO_BINARY;

			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);
		memoryWriteWord(f.error, parm + 2);
		memoryWriteLong(f.cookie, parm + 8);

		return d0;
	}