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; }
void ftrap_access(uint16_t trap) { // open a file, rename a file, or delete a file. std::string sname; uint32_t d0; uint32_t sp = cpuGetAReg(7); // hmmm not sure if 3 or 4 parameters. uint32_t name = memoryReadLong(sp + 4); uint32_t op = memoryReadLong(sp + 8); uint32_t parm = memoryReadLong(sp + 12); Log("%04x Access(%08x, %04x, %08x)\n", trap, name, op, parm); switch (op) { case kF_OPEN: d0 = ftrap_open(name, parm); break; case kF_DELETE: d0 = ftrap_delete(name); break; case kF_RENAME: d0 = ftrap_rename(name, parm); break; case kF_GTABINFO: d0 = ftrap_get_tab_info(name, parm); break; case kF_STABINFO: d0 = ftrap_set_tab_info(name, parm); break; case kF_GFONTINFO: d0 = ftrap_get_font_info(name, parm); break; case kF_SFONTINFO: d0 = ftrap_set_font_info(name, parm); break; default: d0 = 0x40000000 | kEINVAL; fprintf(stderr, "faccess - unsupported op %04x\n", op); exit(1); } cpuSetDReg(0, d0); }
void cpuSetUpInterrupt(ULO new_interrupt_level) { UWO vector_offset = (UWO) (0x60 + new_interrupt_level*4); ULO vector_address = memoryReadLong(cpuGetVbr() + vector_offset); cpuActivateSSP(); // Switch to using ssp or msp. Loads a7 and preserves usp if we came from user-mode. cpuStackFrameGenerate(vector_offset, cpuGetPC()); // This will end up on msp if master is enabled, or on the ssp/isp if not. cpuSetSR(cpuGetSR() & 0x38ff); // Clear interrupt level cpuSetSR(cpuGetSR() | 0x2000); // Set supervisor mode cpuSetSR(cpuGetSR() | (UWO)(new_interrupt_level << 8)); // Set interrupt level #ifdef CPU_INSTRUCTION_LOGGING cpuCallInterruptLoggingFunc(new_interrupt_level, vector_address); #endif if (cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6) { if (cpuGetFlagMaster()) { // If the cpu was in master mode, preserve msp, and switch to using ssp (isp) in a7. ULO oldA7 = cpuGetAReg(7); cpuSetMspDirect(oldA7); cpuSetAReg(7, cpuGetSspDirect()); cpuFrame1(vector_offset, cpuGetPC()); // Make the throwaway frame on ssp/isp cpuSetSR(cpuGetSR() & 0xefff); // Clear master bit } } cpuInitializeFromNewPC(vector_address); cpuSetStop(FALSE); cpuSetRaiseInterrupt(FALSE); }
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); /* ? */ } }
static void fhfileBeginIO(void) { BYT error = 0; ULO unit = memoryReadLong(cpuGetAReg(1) + 24); UWO cmd = memoryReadWord(cpuGetAReg(1) + 28); switch (cmd) { case 2: error = fhfileRead(unit); break; case 3: case 11: error = fhfileWrite(unit); break; case 18: fhfileGetDriveType(unit); break; case 19: fhfileGetNumberOfTracks(unit); break; case 15: fhfileWriteProt(unit); break; case 4: case 5: case 9: case 10: case 12: case 13: case 14: case 20: case 21: fhfileIgnore(unit); break; default: error = -3; cpuSetDReg(0, 0); break; } memoryWriteByte(5, cpuGetAReg(1) + 8); /* ln_type */ memoryWriteByte(error, cpuGetAReg(1) + 31); /* ln_error */ }
void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp) { ULO vector_address; #ifdef CPU_INSTRUCTION_LOGGING cpuCallExceptionLoggingFunc(cpuGetExceptionName(vector_offset), cpuGetOriginalPC(), cpuGetCurrentOpcode()); #endif cpuActivateSSP(); cpuStackFrameGenerate((UWO) vector_offset, pc); // read a memory position vector_address = memoryReadLong(cpuGetVbr() + vector_offset); if (cpuGetModelMajor() < 2 && vector_address & 0x1 && vector_offset == 0xc) { // Avoid endless loop that will crash the emulator. // The (odd) address error exception vector contained an odd address. cpuCallResetExceptionFunc(); cpuHardReset(); cpuSetInstructionTime(132); } else { // set supervisor modus cpuSetSR(cpuGetSR() | 0x2000); cpuSetSR(cpuGetSR() & 0x3fff); // restart cpu, if needed cpuSetStop(FALSE); cpuInitializeFromNewPC(vector_address); cpuSetInstructionTime(40); } // If the exception happened mid-instruction... if (executejmp) { cpuCallMidInstructionExceptionFunc(); // Supposed to be doing setjmp/longjmp back to machine emulator code } }
static void fhfileClose(void) { memoryWriteLong(memoryReadLong(cpuGetAReg(6) + 32) - 1, cpuGetAReg(6) + 32); /* LIB_OPENCNT */ cpuSetDReg(0, 0); /* ? */ }
static ULO cpuGetNextLongInternal(void) { ULO data = memoryReadLong(cpuGetPC() + 2); return data; }
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); }
uint32_t ExitStatus() { if (!MacProgramInfo) return -1; return memoryReadLong(MacProgramInfo + 0x0e); }