/** * Set watchpoint for data comparison with another 2 comparator used for data address matching * Note : Will automatically set processor to CORE_DEBUG_MODE * * Input : matchingCompNumber1 is the first comparator going to be used for data address matching * Possible value : * COMPARATOR_0 DWT Comparator Number 0 * COMPARATOR_2 DWT Comparator Number 2 * COMPARATOR_3 DWT Comparator Number 3 * * address1 is the first address to be used for data address matching * addressMask1 is the mask going to be applied to the first address * Possible value : * WATCHPOINT_MASK_NOTHING Compare all 32 bits of address set in DWT_COMPn * WATCHPOINTMASK_BIT0 Ignore Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINTMASK_BIT1_BIT0 Ignore Bit1 and Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINTMASK_BIT2_BIT0 Ignore Bit2 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINTMASK_BIT3_BIT0 Ignore Bit3 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT4_BIT0 Ignore Bit4 to Bit 0 of address set in DWT_COMPn during comparison * "" "" * WATCHPOINT_MASK_BIT12_BIT0 Ignore Bit12 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT13_BIT0 Ignore Bit13 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT14_BIT0 Ignore Bit14 to Bit 0 of address set in DWT_COMPn during comparison * * matchingCompNumber2 is the second comparator going to be used for data address matching * Possible value : * COMPARATOR_0 DWT Comparator Number 0 * COMPARATOR_2 DWT Comparator Number 2 * COMPARATOR_3 DWT Comparator Number 3 * * address2 is the second address to be used for data address matching * addressMask2 is the mask going to be applied to the second address * Possible value : * WATCHPOINT_MASK_NOTHING Compare all 32 bits of address set in DWT_COMPn * WATCHPOINT_MASK_BIT0 Ignore Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT1_BIT0, Ignore Bit1 and Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT2_BIT0, Ignore Bit2 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT3_BIT0, Ignore Bit3 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT4_BIT0 Ignore Bit4 to Bit 0 of address set in DWT_COMPn during comparison * "" "" * WATCHPOINT_MASK_BIT12_BIT0 Ignore Bit12 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT13_BIT0 Ignore Bit13 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT14_BIT0 Ignore Bit14 to Bit 0 of address set in DWT_COMPn during comparison * * matchedData is the data going to be matched/compared * dataSize is the data size going to be compared * Possible value : * WATCHPOINT_BYTE * WATCHPOINT_HALFWORD * WATCHPOINT_WORD * * accessMode is the access mode for the watchpoint * Possible value : * WATCHPOINT_READ Watchpoint on read access * WATCHPOINT_WRITE Watchpoint on write access * WATCHPOINT_READWRITE Watchpoint on read/write access * * Output : return 0 if watchpoint is set * return -1 if invalid comparator is selected */ int setDataWatchpoint_MatchingTwoComparator(int matchingCompNumber1,uint32_t address1,Watchpoint_AddressMask addressMask1, int matchingCompNumber2,uint32_t address2,Watchpoint_AddressMask addressMask2, uint32_t matchedData,Watchpoint_DataSize dataSize,Watchpoint_AccessMode accessMode) { int result = 0 ; int valid1 = 0 , valid2 = 0 ; uint32_t configData = 0 ; valid1 = checkForValidDWTComparator(matchingCompNumber1); valid2 = checkForValidDWTComparator(matchingCompNumber2); if(matchingCompNumber1 == 1 || matchingCompNumber2 == 1 || valid1 == -1 || valid2 == -1) return -1 ; configData = (matchingCompNumber2 << 16) + (matchingCompNumber1 << 12) + (dataSize << 10) + (DATA_COMPARISON << 8) + accessMode ; setAddressWatchpoint(matchingCompNumber1,address1,addressMask1,DISABLE_DWTCOMPARATOR); setAddressWatchpoint(matchingCompNumber2,address2,addressMask2,DISABLE_DWTCOMPARATOR); memoryWriteWord((uint32_t)(&DWT_COMP[1].FUNCTION),DISABLE_DWTCOMPARATOR); //disable selected comparator first memoryWriteWord((uint32_t)(&DWT_COMP[1].COMP),matchedData); memoryWriteWord((uint32_t)(&DWT_COMP[1].MASK),WATCHPOINT_MASK_NOTHING); memoryWriteWord((uint32_t)(&DWT_COMP[1].FUNCTION),configData); return result ; }
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)); }
/* * interruptSet() * * ustawia funkcjê obs³ugi przerwania. */ void interruptSet(byte number, word offset) { word segCS = 0; #asm push ax mov ax,cs mov -6[bp],ax pop ax #endasm memoryWriteWord(0x0000, number * 4, offset); memoryWriteWord(0x0000, number * 4 + 2, segCS); }
uint16_t SysEnvirons(uint16_t trap) { // FUNCTION SysEnvirons (versionRequested: Integer; // VAR theWorld: SysEnvRec): OSErr; /* * on entry: * D0 Version requested * A0 SysEnvRec pointer * * on exit: * D0 Result code * */ enum { /* SysEnvRec */ _environsVersion = 0, _machineType = 2, _systemVersion = 4, _processor = 6, _hasFPU = 8, _hasColorQD = 9, _keyBoardType = 10, _atDrvrVersNum = 12, _sysVRefNum = 14, }; uint16_t versionRequested = cpuGetDReg(0); uint32_t theWorld = cpuGetAReg(0); Log("%04x SysEnvirons(%04x, %08x)\n", trap, versionRequested, theWorld); memoryWriteWord(2, theWorld + _environsVersion); // negative version. if (versionRequested >= 0x8000) return MacOS::envBadVers; if (versionRequested > 2) return MacOS::envVersTooBig; memoryWriteWord(0, theWorld + _machineType); // 0 = unknown model newer than the IIci (v1) or IIfx (v2) memoryWriteWord(1 + cpuGetModelMajor(), theWorld + _processor); memoryWriteWord(0x0700, theWorld + _systemVersion); // system 7 memoryWriteWord(0, theWorld + _hasFPU); memoryWriteWord(0, theWorld + _hasColorQD); memoryWriteWord(5, theWorld + _keyBoardType); // standard adb I guess memoryWriteWord(0, theWorld + _atDrvrVersNum); // no appletalk memoryWriteWord(-1, theWorld + _sysVRefNum); // System folder # return 0; }
void mmuWriteWord(Word vAddr, Word data, Bool userMode) { if ((vAddr & 3) != 0) { /* throw illegal address exception */ mmuBadAccs = MMU_ACCS_WRITE | MMU_ACCS_WORD; mmuBadAddr = vAddr; throwException(EXC_ILL_ADDRESS); } memoryWriteWord(v2p(vAddr, userMode, true, MMU_ACCS_WORD), data); }
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)); }
/** * Set watchpoint for address comparison * Note : Will automatically set processor to CORE_DEBUG_MODE * * Input : dwtCompNumber is the comparator going to be used * Possible value : * COMPARATOR_0 DWT Comparator Number 0 * COMPARATOR_1 DWT Comparator Number 1 * COMPARATOR_2 DWT Comparator Number 2 * COMPARATOR_3 DWT Comparator Number 3 * * address is the address to be compared * addressMask is the mask going to be applied to the address * Possible value : * WATCHPOINT_MASK_NOTHING Compare all 32 bits of address set in DWT_COMPn * WATCHPOINT_MASK_BIT0 Ignore Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT1_BIT0, Ignore Bit1 and Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT2_BIT0, Ignore Bit2 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT3_BIT0, Ignore Bit3 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT4_BIT0 Ignore Bit4 to Bit 0 of address set in DWT_COMPn during comparison * "" "" * WATCHPOINT_MASK_BIT12_BIT0 Ignore Bit12 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT13_BIT0 Ignore Bit13 to Bit 0 of address set in DWT_COMPn during comparison * WATCHPOINT_MASK_BIT14_BIT0 Ignore Bit14 to Bit 0 of address set in DWT_COMPn during comparison * * accessMode is the access mode for the watchpoint * Possible value : * WATCHPOINT_READ Watchpoint on read access * WATCHPOINT_WRITE Watchpoint on write access * WATCHPOINT_READWRITE Watchpoint on read/write access * * Output : return 0 if watchpoint is set * return -1 if invalid comparator is selected */ int setAddressWatchpoint(int dwtCompNumber,uint32_t address,Watchpoint_AddressMask addressMask,Watchpoint_AccessMode accessMode) { int result = 0 ; int valid = checkForValidDWTComparator(dwtCompNumber) ; if(valid == -1) return -1 ; enableDWTandITM(); //enable global enable for DWT (Needed for reading & writing DWT Register) setCoreMode(CORE_DEBUG_MODE); memoryWriteWord((uint32_t)(&DWT_COMP[dwtCompNumber].FUNCTION),DISABLE_DWTCOMPARATOR); //disable selected comparator first memoryWriteWord((uint32_t)(&DWT_COMP[dwtCompNumber].COMP),address); memoryWriteWord((uint32_t)(&DWT_COMP[dwtCompNumber].MASK),addressMask); if(accessMode != DISABLE_DWTCOMPARATOR)//prevent setting to disable mode twice memoryWriteWord((uint32_t)(&DWT_COMP[dwtCompNumber].FUNCTION),accessMode); return result ; }
/** * Disable the selected DWT Comparator * * Input : dwtCompNumber is the comparator going to be used * Possible value : * COMPARATOR_0 DWT Comparator Number 0 * COMPARATOR_1 DWT Comparator Number 1 * COMPARATOR_2 DWT Comparator Number 2 * COMPARATOR_3 DWT Comparator Number 3 * * Output : return 0 if the comparator is disabled * return -1 if invalid comparator is selected */ int disableDWTComparator(int dwtCompNumber) { int valid = 0 ; valid = checkForValidDWTComparator(dwtCompNumber) ; if(valid == -1) return valid ; memoryWriteWord((uint32_t)(&DWT_COMP[dwtCompNumber].FUNCTION),DISABLE_DWTCOMPARATOR); return 0 ; }
uint16_t TempDisposeHandle(void) { // PROCEDURE TempDisposeHandle (theHandle: Handle; VAR resultCode: OSErr); uint32_t theHandle; uint32_t resultCode; StackFrame<8>(theHandle, resultCode); Log(" TempDisposeHandle(%08x, %08x)\n", theHandle, resultCode); uint16_t rv = Native::DisposeHandle(theHandle); if (resultCode) memoryWriteWord(rv, resultCode); return rv; }
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)); }
uint16_t TempNewHandle(void) { // FUNCTION TempNewHandle (logicalSize: Size; // VAR resultCode: OSErr): Handle; uint16_t rv; uint32_t logicalSize; uint32_t resultCode; uint32_t theHandle; uint32_t sp = StackFrame<8>(logicalSize, resultCode); Log(" TempNewHandle(%08x, %08x)\n", logicalSize, resultCode); rv = Native::NewHandle(logicalSize, true, theHandle); if (resultCode) memoryWriteWord(rv, resultCode); ToolReturn<4>(sp, theHandle); return rv; }
void ftrap_close(uint16_t trap) { // returns an mpw_errno // close actually checks the error in the File Entry and converts that to unix. // (sigh) uint32_t d0 = 0; uint32_t sp = cpuGetAReg(7); uint32_t parm = memoryReadLong(sp + 4); MPWFile f; f.flags = memoryReadWord(parm); f.error = memoryReadWord(parm + 2); f.device = memoryReadLong(parm + 4); f.cookie = memoryReadLong(parm + 8); f.count = memoryReadLong(parm + 12); f.buffer = memoryReadLong(parm + 16); Log("%04x Close(%08x)\n", trap, parm); if (!parm) { cpuSetDReg(0, kEINVAL); return; } int fd = f.cookie; int rv = OS::Internal::FDEntry::close(fd); if (rv < 0) { f.error = MacOS::notOpenErr; d0 = kEINVAL; } else { f.error = 0; d0 = 0; } #if 0 if (fd < 0 || fd >= OS::Internal::FDTable.size()) { f.error = OS::notOpenErr; d0 = kEINVAL; } else { auto &e = OS::Internal::FDTable[fd]; if (e.refcount == 0) { f.error = OS::notOpenErr; d0 = kEINVAL; } else { if (--e.refcount == 0) { Log(" close(%02x)\n", fd); ::close(fd); } f.error = 0; d0 = 0; } } #endif memoryWriteWord(f.error, parm + 2); cpuSetDReg(0, 0); }
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; }
/* 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; }