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); /* ? */ } }
uint16_t Gestalt(uint16_t trap) { // FUNCTION Gestalt (selector: OSType; VAR response: LongInt): OSErr; /* * on entry: * D0 Selector code * * on exit: * A0 Response * D0 Result code * */ uint32_t selector = cpuGetDReg(0); uint32_t response; Log("%04x Gestalt('%s')\n", trap, ToolBox::TypeToString(selector).c_str()); auto iter = GestaltMap.find(selector); if (iter == GestaltMap.end()) return gestaltUndefSelectorErr; response = iter->second; cpuSetAReg(0, response); return 0; }
uint16_t PtrToHand(uint16_t trap) { /* * on entry: * A0 source Pointer * D0 size * * on exit: * A0 destination pointer * D0 Result code * */ uint32_t mcptr = cpuGetAReg(0); uint32_t size = cpuGetDReg(0); Log("%04x PtrToHand(%08x, %08x)\n", trap, mcptr, size); uint32_t destHandle; uint32_t destPtr; uint32_t d0 = Native::NewHandle(size, false, destHandle, destPtr); if (d0 == 0) { std::memmove(memoryPointer(destPtr), memoryPointer(mcptr), size); } cpuSetAReg(0, destHandle); return d0; // SetMemError called by Native::NewHandle. }
uint16_t NewHandle(uint16_t trap) { /* * on entry: * D0 Number of logical bytes requested * * on exit: * A0 Address of the new handle or NIL * D0 Result code * */ uint32_t hh = 0; uint16_t error; bool clear = trap & (1 << 9); //bool sys = trap & (1 << 10); uint32_t size = cpuGetDReg(0); Log("%04x NewHandle(%08x)\n", trap, size); error = Native::NewHandle(size, clear, hh); cpuSetAReg(0, hh); return error; }
uint16_t NewPtr(uint16_t trap) { /* * on entry: * D0 Number of logical bytes requested * * on exit: * A0 Address of the new block or NIL * D0 Result code * */ bool clear = trap & (1 << 9); //bool sys = trap & (1 << 10); uint32_t size = cpuGetDReg(0); Log("%04x NewPtr(%08x)\n", trap, size); // todo -- separate pools for sys vs non-sys? // todo -- NewPtr(0) -- null or empty ptr? uint32_t mcptr; uint16_t error; error = Native::NewPtr(size, clear, mcptr); cpuSetAReg(0, mcptr); return error; //SetMemError(error); }
uint16_t SetPtrSize(uint16_t trap) { /* * on entry: * A0 pointer * D0 new size * * on exit: * D0 Result code * */ uint32_t mcptr = cpuGetAReg(0); uint32_t newSize = cpuGetDReg(0); Log("%08x SetPtrSize(%08x, %08x)\n", trap, mcptr, newSize); auto iter = PtrMap.find(mcptr); if (iter == PtrMap.end()) return SetMemError(MacOS::memWZErr); uint8_t *ptr = mcptr + Memory; if (mplite_resize(&pool, ptr, mplite_roundup(&pool, newSize)) < 0) { return SetMemError(MacOS::memFullErr); } // update the size. iter->second = newSize; return SetMemError(0); }
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); 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); }
/* * 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 }
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; }
uint16_t PtrAndHand(uint16_t trap) { // FUNCTION PtrAndHand (pntr: Ptr; hndl: Handle; size: LongInt): OSErr; /* * 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); uint32_t oldSize = 0; uint32_t d0; d0 = Native::GetHandleSize(handle, oldSize); if (d0) return d0; if ((uint64_t)oldSize + (uint64_t)size > UINT32_MAX) return SetMemError(MacOS::memFullErr); d0 = Native::SetHandleSize(handle, oldSize + size); if (d0) return d0; auto iter = HandleMap.find(handle); if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr); auto const info = iter->second; std::memmove(memoryPointer(info.address + oldSize), memoryPointer(ptr), size); return SetMemError(0); }
uint32_t RecoverHandle(uint16_t trap) { // FUNCTION RecoverHandle (p: Ptr): Handle; /* * on entry: * A0 Master pointer * * on exit: * A0 Handle to master pointer’s relocatable block * D0 Unchanged * */ uint32_t p = cpuGetAReg(0); uint32_t hh = 0; Log("%04x RecoverHandle(%08x)\n", trap, p); uint16_t error = MacOS::memBCErr; 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 (p >= begin && p < end) { hh = kv.first; error = MacOS::noErr; break; } } SetMemError(error); cpuSetAReg(0, hh); // return d0 register unchanged. return cpuGetDReg(0); }
uint32_t CompactMem(uint16_t trap) { // todo -- add function to check pool for largest block? /* * on entry: * D0: cbNeeded (long word) * * on exit: * D0: function result (long word) * */ uint32_t cbNeeded = cpuGetDReg(0); Log("%04x CompactMem(%08x)\n", trap, cbNeeded); SetMemError(0); return mplite_maxmem(&pool); }
uint16_t SetHandleSize(uint16_t trap) { /* * on entry: * A0 pointer * D0 new size * * on exit: * D0 Result code * */ uint32_t hh = cpuGetAReg(0); uint32_t newSize = cpuGetDReg(0); Log("%04x SetHandleSize(%08x, %08x)\n", trap, hh, newSize); return Native::SetHandleSize(hh, newSize); }
uint16_t HWPriv(uint16_t trap) { uint16_t selector; uint16_t d0 = 0; selector = cpuGetDReg(0) & 0xffff; Log("%04x HWTrap(%04x)\n", trap, selector); switch(selector) { case 0x0000: d0 = SwapInstructionCache(); break; case 0x0001: d0 = FlushInstructionCache(); break; case 0x0002: d0 = SwapDataCache(); break; case 0x0003: d0 = FlushDataCache(); break; case 0x0009: d0 = FlushCodeCacheRange(); break; default: fprintf(stderr, "HWTrap selector %04x not yet supported\n", selector); exit(1); } return d0; }
uint16_t ReserveMem(uint16_t trap) { /* * 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? if (available < cbNeeded) return SetMemError(MacOS::memFullErr); return SetMemError(0); }
uint16_t AliasDispatch(uint16_t trap) { uint16_t selector = cpuGetDReg(0); Log("%04x AliasDispatch($%04x)\n", trap, selector); switch (selector) { case 0x000c: return ResolveAliasFile(); break; default: fprintf(stderr, "AliasDispatch: selector $%04x not implemented\n", selector); exit(1); } return 0; }
uint32_t StripAddress(uint16_t trap) { /* * 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); if (MemorySize <= 0x00ffffff) address &= 0x00ffffff; return address; }
uint16_t BlockMove(uint16_t trap) { // also implements BlockMoveData. // BlockMove will flush caches, BlockMoveData will not. /* * 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); Log("%04x BlockMove(%08x, %08x, %08x)\n", trap, source, dest, count); // TODO -- 32-bit clean? // TODO -- verify within MemorySize? #if 0 if (source == 0 || dest == 0 || count == 0) return 0; #endif std::memmove(Memory + dest, Memory + source, count); return 0; }